diff --git a/bootstrap/gitea/README.md b/bootstrap/gitea/README.md new file mode 100644 index 0000000..9272857 --- /dev/null +++ b/bootstrap/gitea/README.md @@ -0,0 +1,33 @@ +# bootstrap/gitea — Phase-1 host Gitea (GitOps bootstrap source) + +Solves the self-hosted-git chicken-and-egg for Phase 1: the platform's Gitea will eventually run +*in* the cluster (Phase 6), but the cluster needs a git source to bootstrap *from*. So during +bring-up we run **a single Gitea container on the host**, outside the cluster, and Flux pulls this +repo from it. + +## How it fits +- `bootstrap-gitea.sh` starts `gitea/gitea` on the host with a persistent data dir, HTTP on + `:3000`, reachable from the cluster VMs on the **k3s-dev NAT gateway `10.73.0.1`**. +- The repo is pushed to it as a **public** repo (`Home-Network/home-network-k3s-impl`) — public so + Flux needs no credentials; safe because this Gitea is **NAT-only, not internet-exposed**. +- Flux's `flux-system` GitRepository is wired to + `http://10.73.0.1:3000/Home-Network/home-network-k3s-impl.git` (inlined in + `clusters/dev/kustomization.yaml`). `bootstrap/flux/bootstrap.sh` then `apply -k clusters/dev` and + Flux reconciles from here. + +## Bring-up order (operator, at execution time — not now) +1. `./bootstrap/gitea/bootstrap-gitea.sh` → create admin + public repo → `git push bootstrap main`. +2. `tofu apply` (infra/tofu) — VMs + `k3s-dev` net. +3. Ansible `site.yml` — k3s HA + Cilium. +4. `bootstrap/sops/age-keygen.sh` → `install-age-key.sh` → `bootstrap/flux/bootstrap.sh`. +5. Flux reconciles `clusters/dev` from the host Gitea. + +## Phase 6 cutover +Once the **in-cluster** Gitea is onboarded (`gitea.home.keithjackson.dev`), push the repo there, +repoint the `flux-system` GitRepository URL, and keep an **off-cluster mirror** (docs/05 +"Circularity & DR"). The host Gitea can then be retired. + +## Notes +- Pinned `gitea/gitea:1.22` (override `GITEA_IMAGE`); data at + `~/.local/share/home-k3s-bootstrap-gitea` (override `GITEA_DATA_DIR`). +- No secrets here: admin credentials are created interactively at bring-up, never committed. diff --git a/bootstrap/gitea/bootstrap-gitea.sh b/bootstrap/gitea/bootstrap-gitea.sh new file mode 100755 index 0000000..c8f06d5 --- /dev/null +++ b/bootstrap/gitea/bootstrap-gitea.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# bootstrap/gitea/bootstrap-gitea.sh — run a SINGLE Gitea container on the HOST (outside the +# cluster) as the Phase-1 GitOps bootstrap source. While the cluster is built, Flux (in-cluster) +# reconciles this repo from the host Gitea over the k3s-dev NAT gateway. This is the "local +# bootstrap source" that migrates to in-cluster Gitea in Phase 6 (docs/05 "Source-of-truth", +# CONTRIBUTING.md). +# +# Run by the OPERATOR at bring-up — NOT during author-only, NOT by any agent. +set -euo pipefail +ENGINE="${ENGINE:-podman}" +GITEA_IMAGE="${GITEA_IMAGE:-docker.io/gitea/gitea:1.22}" # pinned; bump if needed +NAME="${GITEA_NAME:-home-k3s-bootstrap-gitea}" +HTTP_PORT="${GITEA_HTTP_PORT:-3000}" +SSH_PORT="${GITEA_SSH_PORT:-2222}" +DATA_DIR="${GITEA_DATA_DIR:-${HOME}/.local/share/home-k3s-bootstrap-gitea}" +# The cluster VMs reach the host on the k3s-dev NAT gateway (10.73.0.1). ROOT_URL must match so +# clone/redirect URLs are correct from inside the cluster. +HOST_NAT_IP="${HOST_NAT_IP:-10.73.0.1}" +ORG="${GITEA_ORG:-Home-Network}" +REPO="${GITEA_REPO:-home-network-k3s-impl}" + +mkdir -p "${DATA_DIR}" +if "$ENGINE" container exists "$NAME" 2>/dev/null; then + echo "Gitea container '${NAME}' already exists — starting it." + "$ENGINE" start "$NAME" >/dev/null +else + "$ENGINE" run -d --name "$NAME" --restart unless-stopped \ + -p "${HTTP_PORT}:3000" -p "${SSH_PORT}:22" \ + -v "${DATA_DIR}:/data" \ + -e GITEA__server__ROOT_URL="http://${HOST_NAT_IP}:${HTTP_PORT}/" \ + -e GITEA__server__SSH_PORT="${SSH_PORT}" \ + -e GITEA__security__INSTALL_LOCK=true \ + "$GITEA_IMAGE" +fi + +cat < --password --email --admin + 2. In the UI (or API) create org '${ORG}' and a **PUBLIC** repo '${REPO}' + (public => Flux needs no git credentials; this Gitea is NAT-only, not internet-exposed). + 3. Push this repo up: + git remote add bootstrap http://:@${HOST_NAT_IP}:${HTTP_PORT}/${ORG}/${REPO}.git + git push bootstrap main + +Flux's flux-system GitRepository url is already wired to: + http://${HOST_NAT_IP}:${HTTP_PORT}/${ORG}/${REPO}.git (clusters/dev) +EOF diff --git a/clusters/dev/kustomization.yaml b/clusters/dev/kustomization.yaml index d23fa11..eb9767f 100644 --- a/clusters/dev/kustomization.yaml +++ b/clusters/dev/kustomization.yaml @@ -42,9 +42,10 @@ patches: name: flux-system namespace: flux-system spec: - # >>> REPLACE-ME at bootstrap <<< how the local repo is served to the cluster - # (git-over-ssh / a git daemon on the NAT gateway, etc. — WS-INFRA/operator, OQ). - url: https://REPLACE-ME.invalid/home-network-k3s-impl.git + # Phase-1 bootstrap source: a single Gitea container on the HOST (bootstrap/gitea/), + # reachable from the cluster on the k3s-dev NAT gateway. PUBLIC repo => Flux needs no + # creds (NAT-only). Phase 6 cutover -> in-cluster gitea.home.keithjackson.dev (docs/05). + url: http://10.73.0.1:3000/Home-Network/home-network-k3s-impl.git ref: branch: main # --- dev-scoped cluster-vars (R-ENV-02) --- diff --git a/infra/PHASE1-SCOPE.md b/infra/PHASE1-SCOPE.md index b95fa3f..8b9a3e1 100644 --- a/infra/PHASE1-SCOPE.md +++ b/infra/PHASE1-SCOPE.md @@ -67,8 +67,14 @@ Totals: 12 vCPU · **18 GiB RAM** (~4 GiB host headroom) · ~180 GiB thin-alloca Proposed Phase-1 impl tree: `infra/{tofu,ansible,cloud-init}/` and `bootstrap/{sops,flux}/`. ## Sequencing -`tofu apply` (VMs up) → cloud-init baseline → Ansible (k3s + Cilium) → Flux + SOPS bootstrap → -verify reconcile → destroy/rebuild proof → `CLUSTER_AVAILABLE=true` → conformance L2/L3 begins. +**Start host Gitea** (`bootstrap/gitea/`) + push repo → `tofu apply` (VMs up) → cloud-init baseline → +Ansible (k3s + Cilium) → Flux + SOPS bootstrap (Flux pulls from the host Gitea) → verify reconcile → +destroy/rebuild proof → `CLUSTER_AVAILABLE=true` → conformance L2/L3 begins. + +**Bootstrap source — RESOLVED:** a single **Gitea container on the host** (`bootstrap/gitea/`), +reachable from the cluster at `http://10.73.0.1:3000/…` (NAT gateway), public repo → Flux needs no +creds. Migrates to in-cluster Gitea in Phase 6. **Pins CONFIRMED:** k3s `v1.31.5+k3s1`, Cilium chart +`1.16.5`, single-node `k8sServiceHost` (dev-acceptable SPOF). ## Risks & mitigations - **libvirt perms** — use `qemu:///system`; ensure the socket (virtqemud/libvirtd socket-activated) is