Codify host firewall + Gitea bootstrap as IaC (hands-off rebuild)
Per operator: the firewalld rule (VM->host:3000 for the Flux<-Gitea source) must be IaC, not a manual command (R-ENV-01, R-PLAT-04). - infra/ansible/playbooks/host-prereqs.yml: idempotent firewalld open on the libvirt zone (localhost play, become; no extra collection). - bootstrap/gitea/bootstrap-gitea.sh: now fully automates admin + public repo + push (was manual instructions) — idempotent; creds stay 0600 on host, never committed. Applying host-prereqs still needs host sudo (I lack non-interactive sudo); with passwordless become a destroy/rebuild is fully unattended. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
1 parent
4f39bb8d45
commit
3df5071bd1
3 files changed
+84
-17
No files matched your search
+6
-3
@@ -27,9 +27,12 @@ need the operator are called out.
|
|||||||
`platform/kyverno` (verified). Gate green.
|
`platform/kyverno` (verified). Gate green.
|
||||||
- **Flux INSTALLED** on the cluster (4 controllers Running). Host **Gitea working** (named-volume fix),
|
- **Flux INSTALLED** on the cluster (4 controllers Running). Host **Gitea working** (named-volume fix),
|
||||||
repo pushed. GitRepository created → **BLOCKED**: cluster pods can't reach `10.73.0.1:3000`
|
repo pushed. GitRepository created → **BLOCKED**: cluster pods can't reach `10.73.0.1:3000`
|
||||||
(firewalld `libvirt` zone drops VM→host:3000). **Needs operator (one command, I lack sudo):**
|
(firewalld `libvirt` zone drops VM→host:3000).
|
||||||
`sudo firewall-cmd --zone=libvirt --add-port=3000/tcp --permanent && sudo firewall-cmd --reload`
|
- **Now codified as IaC (per operator: no manual commands):** `infra/ansible/playbooks/host-prereqs.yml`
|
||||||
Then Flux reconciles from Gitea (Phase-1 T-1.4 exit).
|
opens the port idempotently; `bootstrap/gitea/bootstrap-gitea.sh` now **fully automates** admin +
|
||||||
|
public repo + push (was manual). A rebuild is hands-off. To APPLY the firewall (I lack
|
||||||
|
non-interactive sudo): `ansible-playbook infra/ansible/playbooks/host-prereqs.yml --ask-become-pass`
|
||||||
|
(or passwordless host sudo for unattended rebuilds). Then Flux reconciles → Phase-1 T-1.4 exit.
|
||||||
- **NOT deployed:** `platform`/`apps` Kustomizations were deliberately NOT created — the running
|
- **NOT deployed:** `platform`/`apps` Kustomizations were deliberately NOT created — the running
|
||||||
cluster (Cilium etc.) is untouched. Only Flux controllers + the GitRepository source exist.
|
cluster (Cilium etc.) is untouched. Only Flux controllers + the GitRepository source exist.
|
||||||
|
|
||||||
|
|||||||
@@ -38,20 +38,45 @@ else
|
|||||||
"$GITEA_IMAGE"
|
"$GITEA_IMAGE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- automated, idempotent setup (admin + PUBLIC repo + push) — NO manual steps (R-ENV-01) ---
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
ADMIN_CRED_FILE="${GITEA_ADMIN_CRED_FILE:-${HOME}/.config/home-k3s-bootstrap-gitea-admin.txt}"
|
||||||
|
BASE="http://localhost:${HTTP_PORT}" # host-side mgmt via localhost; the cluster uses HOST_NAT_IP
|
||||||
|
|
||||||
|
echo "Waiting for Gitea to be healthy..."
|
||||||
|
curl -fsS --retry 40 --retry-delay 2 --retry-all-errors "${BASE}/api/healthz" >/dev/null
|
||||||
|
|
||||||
|
# Admin credentials: generated once, stored 0600 on the host (never committed, never printed).
|
||||||
|
if [ ! -s "$ADMIN_CRED_FILE" ]; then
|
||||||
|
mkdir -p "$(dirname "$ADMIN_CRED_FILE")"
|
||||||
|
printf 'user=gitops\npass=%s\n' "$(openssl rand -base64 18 | tr -dc 'A-Za-z0-9' | head -c 22)" > "$ADMIN_CRED_FILE"
|
||||||
|
chmod 600 "$ADMIN_CRED_FILE"
|
||||||
|
fi
|
||||||
|
ADMIN_USER="$(sed -n 's/^user=//p' "$ADMIN_CRED_FILE")"
|
||||||
|
ADMIN_PW="$(sed -n 's/^pass=//p' "$ADMIN_CRED_FILE")"
|
||||||
|
|
||||||
|
# Create the admin user if missing (idempotent).
|
||||||
|
if ! "$ENGINE" exec -u git "$NAME" gitea admin user list 2>/dev/null | grep -qw "$ADMIN_USER"; then
|
||||||
|
"$ENGINE" exec -u git "$NAME" gitea admin user create \
|
||||||
|
--username "$ADMIN_USER" --password "$ADMIN_PW" --email "${ADMIN_USER}@home.local" \
|
||||||
|
--admin --must-change-password=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Org + PUBLIC repo (idempotent — 'already exists' is fine; public => Flux needs no git creds).
|
||||||
|
curl -fsS -u "${ADMIN_USER}:${ADMIN_PW}" -H 'Content-Type: application/json' -X POST \
|
||||||
|
"${BASE}/api/v1/orgs" -d "{\"username\":\"${ORG}\"}" -o /dev/null 2>/dev/null || true
|
||||||
|
curl -fsS -u "${ADMIN_USER}:${ADMIN_PW}" -H 'Content-Type: application/json' -X POST \
|
||||||
|
"${BASE}/api/v1/orgs/${ORG}/repos" -d "{\"name\":\"${REPO}\",\"private\":false}" -o /dev/null 2>/dev/null || true
|
||||||
|
|
||||||
|
# Push current HEAD -> the bootstrap source's main.
|
||||||
|
git -C "$REPO_ROOT" push "http://${ADMIN_USER}:${ADMIN_PW}@localhost:${HTTP_PORT}/${ORG}/${REPO}.git" HEAD:main
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
Gitea (bootstrap source) at http://${HOST_NAT_IP}:${HTTP_PORT}/ data: ${DATA_DIR}
|
Gitea bootstrap source ready (${DATA_DIR}).
|
||||||
|
UI (host): ${BASE}/${ORG}/${REPO}
|
||||||
One-time setup (manual — keeps creds out of this script):
|
Flux GitRepository (cluster): http://${HOST_NAT_IP}:${HTTP_PORT}/${ORG}/${REPO}.git (clusters/dev)
|
||||||
1. Create an admin user:
|
Admin creds (host, 0600): ${ADMIN_CRED_FILE}
|
||||||
${ENGINE} exec -u git ${NAME} gitea admin user create \\
|
Prerequisite: firewalld must allow VM->host:${HTTP_PORT} —
|
||||||
--username <admin> --password <pw> --email <you@example> --admin
|
ansible-playbook infra/ansible/playbooks/host-prereqs.yml --ask-become-pass
|
||||||
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://<admin>:<pw>@${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
|
EOF
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
# Host (hypervisor/workstation) prerequisites for the local dev/test cluster — IaC so the cluster
|
||||||
|
# can be destroyed & rebuilt with NO remembered manual commands (R-ENV-01, R-PLAT-04).
|
||||||
|
#
|
||||||
|
# Runs on the HOST itself (localhost), NOT the cluster nodes. Needs host privilege escalation:
|
||||||
|
# ansible-playbook playbooks/host-prereqs.yml --ask-become-pass
|
||||||
|
# (or configure passwordless sudo / a become password for fully unattended rebuilds).
|
||||||
|
#
|
||||||
|
# Idempotent: safe to re-run; only changes what isn't already in the desired state. Uses
|
||||||
|
# firewall-cmd directly (no extra Ansible collection dependency).
|
||||||
|
- name: Configure host prerequisites for the local dev cluster
|
||||||
|
hosts: localhost
|
||||||
|
connection: local
|
||||||
|
become: true
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
# The bootstrap Gitea (bootstrap/gitea/) runs on the host; the in-cluster Flux must reach it
|
||||||
|
# over the k3s-dev NAT gateway. firewalld's `libvirt` zone (which owns virbrN) drops
|
||||||
|
# VM->host:<port> by default, so this must be opened or Flux cannot fetch the GitOps source.
|
||||||
|
gitea_bootstrap_port: 3000
|
||||||
|
libvirt_firewalld_zone: libvirt
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check whether the Gitea port is already allowed on the libvirt zone
|
||||||
|
ansible.builtin.command: "firewall-cmd --zone={{ libvirt_firewalld_zone }} --query-port={{ gitea_bootstrap_port }}/tcp"
|
||||||
|
register: gitea_port_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Allow the bootstrap-Gitea port from the cluster VMs (permanent + runtime)
|
||||||
|
ansible.builtin.command: "{{ item }}"
|
||||||
|
loop:
|
||||||
|
- "firewall-cmd --zone={{ libvirt_firewalld_zone }} --add-port={{ gitea_bootstrap_port }}/tcp --permanent"
|
||||||
|
- "firewall-cmd --zone={{ libvirt_firewalld_zone }} --add-port={{ gitea_bootstrap_port }}/tcp"
|
||||||
|
when: "'yes' not in gitea_port_check.stdout"
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
# Tighter alternative (documented, not default): scope to the cluster subnet with a rich rule
|
||||||
|
# firewall-cmd --zone=libvirt --add-rich-rule='rule family=ipv4 source address=10.73.0.0/24 port port=3000 protocol=tcp accept' [--permanent]
|
||||||
Reference in new issue
Block a user