webpage: the four git-syncs read Gitea in-cluster; sidecars retry forever (--max-failures=-1); gate 6 keeps the --repo values identical
gates / gates (push) Successful in 7m42s

On 2026-10-19 09:24 the public path to Gitea failed once and the sidecar exited (max-failures defaults to 0).
Anonymous in-cluster fetch proven first (main and installer-v1.34.0 resolve to the public hashes).
This commit is contained in:
2026-10-19 11:38:44 +02:00
parent 5d3cb5c132
commit fd75003e17
5 changed files with 41 additions and 5 deletions
+3 -1
View File
@@ -29,5 +29,7 @@ ArgoCD's source of truth is the **manifest in git**:
`main`, and `/scripts/` from the tag `installer-v<SCRIPT_VERSION>`. Changing either `--ref` changes
what real machines download — the init container **and** the sidecar both carry it, and both must
move together. `hostinstall_gates.py` gate 6 fails if the manifest stops naming an `installer-v…`
tag or if the website stops tracking `main`. The full publish/rollback procedure is the R-110 fence
tag or if the website stops tracking `main`. All four git-sync containers (two sidecars, two init containers) read
Gitea **in-cluster** (`http://gitea.gitea-system.svc.cluster.local:3000/…`, since 2026-10-19) and must name the same
repo — gate 6 fails if they differ; the sidecars carry `--max-failures=-1` (retry, never exit). The full publish/rollback procedure is the R-110 fence
in the repo core `CLAUDE.md`.
@@ -271,6 +271,13 @@ app. Controller down → the gated app answers an error, never the app. Measured
tunnel. Since controller v0.286.0 it sits ALONE on the `felhom-tunnel` network at the fixed address `172.16.253.2`
(traefik at `.3`), so traefik can believe forwarded headers from it and from nothing else (§5). Geo-restriction WAF
is **hub-enforced** (the hub holds the CF API token; the controller only reports geo desired-state).
- **[DESIGN] The website's content comes from Gitea IN-CLUSTER** (2026-10-19). The `felhom-webpage` pod pulls
`website/` (from `main`) and `scripts/` (from the `installer-v…` tag, R-110) with four git-syncs that read
`http://gitea.gitea-system.svc.cluster.local:3000/admin/felhom.eu.git` — plain HTTP, safe only because it never
leaves the cluster (the hub's own Gitea client does the same). No internet hop: the pod can start, and keep its copy
fresh, during an internet outage. The two sidecars run with `--max-failures=-1`, so an unreachable Gitea is retried,
not a restart. **This ties the website to the DooPlex cluster:** moved elsewhere, it must read the public HTTPS
address again. `scripts/hostinstall_gates.py` gate 6 keeps the four `--repo` values identical.
---
+12 -4
View File
@@ -296,14 +296,21 @@ spec:
# ── The WEBSITE sync — tracks `main`, unchanged cadence ──────────────────────────────
# Deliberately still a branch: the site is content, and a typo fix must reach felhom.eu in
# thirty seconds without cutting a release. Only /scripts/ moved to a tag (R-110).
#
# All four git-syncs read Gitea IN-CLUSTER (plain HTTP, never leaves the cluster — the hub's own Gitea
# client does the same): no internet hop, so the pod can start during an internet outage (2026-10-19 09:24
# the public path failed once and the sidecar restarted). If the website ever leaves the DooPlex cluster,
# this must go back to https://gitea.dooplex.hu/admin/felhom.eu.git. `hostinstall_gates.py` gate 6 fails
# if the four `--repo` values differ.
- name: git-sync
image: registry.k8s.io/git-sync/git-sync:v4.4.0
args:
- --repo=https://gitea.dooplex.hu/admin/felhom.eu.git
- --repo=http://gitea.gitea-system.svc.cluster.local:3000/admin/felhom.eu.git
- --ref=main
- --root=/git
- --link=current
- --period=30s
- --max-failures=-1 # an outage must not restart the sidecar (git-sync v4.4.0 main.go L922: <0 = retry forever)
# Only sync the website subdirectory
- --sparse-checkout-file=/etc/git-sync/sparse-checkout
volumeMounts:
@@ -336,11 +343,12 @@ spec:
- name: git-sync-scripts
image: registry.k8s.io/git-sync/git-sync:v4.4.0
args:
- --repo=https://gitea.dooplex.hu/admin/felhom.eu.git
- --repo=http://gitea.gitea-system.svc.cluster.local:3000/admin/felhom.eu.git
- --ref=installer-v1.34.0
- --root=/git-scripts
- --link=current
- --period=30s
- --max-failures=-1 # an outage must not restart the sidecar (git-sync v4.4.0 main.go L922: <0 = retry forever)
- --sparse-checkout-file=/etc/git-sync-scripts/sparse-checkout
volumeMounts:
- name: git-data-scripts
@@ -365,7 +373,7 @@ spec:
- name: git-sync-init
image: registry.k8s.io/git-sync/git-sync:v4.4.0
args:
- --repo=https://gitea.dooplex.hu/admin/felhom.eu.git
- --repo=http://gitea.gitea-system.svc.cluster.local:3000/admin/felhom.eu.git
- --ref=main
- --root=/git
- --link=current
@@ -381,7 +389,7 @@ spec:
- name: git-sync-scripts-init
image: registry.k8s.io/git-sync/git-sync:v4.4.0
args:
- --repo=https://gitea.dooplex.hu/admin/felhom.eu.git
- --repo=http://gitea.gitea-system.svc.cluster.local:3000/admin/felhom.eu.git
- --ref=installer-v1.34.0
- --root=/git-scripts
- --link=current
+10
View File
@@ -1,3 +1,13 @@
## 2026-10-19 — the website's git-syncs read Gitea in-cluster and retry forever (`manifests/webpage.yaml`, gate 6)
On 2026-10-19 09:24 the public path to Gitea failed once; git-sync v4.4.0 (`--max-failures` defaults to 0) exited
(`too many failures, aborting … failCount:1`) and the sidecar restarted. Visitors saw nothing, but a pod starting
during an outage could not seed its pages at all. All four git-sync containers now read
`http://gitea.gitea-system.svc.cluster.local:3000/admin/felhom.eu.git` (anonymous fetch proven first: `main` and
`installer-v1.34.0` resolve in-cluster to the same hashes as the public address); the two sidecars carry
`--max-failures=-1`. `hostinstall_gates.py` gate 6 now also fails when the four `--repo` values differ (red-proved:
one changed → FAIL, restored → OK). Refs unchanged; `nginx-config-rev` unchanged.
## 2026-10-18 — CI workflow: the failure mail links the public run page, by run id (R-1135)
`.gitea/workflows/gates.yml`, the alarm step: the mail's run link is now `https://gitea.dooplex.hu/<repo>/actions/runs/<run id>`.
+9
View File
@@ -216,6 +216,15 @@ if wp is not None:
else:
fail("manifests/webpage.yaml no longer tracks main for the website — pinning the SITE to "
"the installer tag turns every copy edit into a release")
# All four git-sync containers (two sidecars, two init containers) must read the SAME repo: they moved to
# the in-cluster Gitea address together (2026-10-19), and an init container left on another URL seeds the
# pod from a different source than the sidecar that keeps it fresh.
repos = re.findall(r'--repo=(\S+)', wp)
if len(repos) == 4 and len(set(repos)) == 1:
ok("manifest: all four git-syncs read the same repo (%s)" % repos[0])
else:
fail("manifests/webpage.yaml: the git-sync `--repo` values differ or are not four (%s) — the "
"sidecars and init containers must read one repo" % ", ".join(repos))
# ── R-185: every path that RESOLVES the backup target must also grant on it ──────────────────
#