PR #1888 (TBD-A30) fixed catalyst-system HTTPRoutes for multi-zone Sovereigns whose Cilium Gateway renames HTTPS listeners from `https` to `https-<sanitised-zone>` (e.g. `https-omani-works`, `https-omani-homes`) when more than one parent zone is enabled. Every public HTTPRoute pinned to `sectionName: https` got `Accepted=False NoMatchingListener` and the hosted service 404'd / connection-refused. That fix only touched products/catalyst/chart. Per-blueprint HTTPRoutes shipped the same `sectionName: https` default in values.yaml, so on a multi-zone Sovereign every blueprint route — gitea, grafana, harbor, keycloak, newapi, openbao, powerdns, stalwart-tenant — silently failed to attach. TBD-A40 / issue #1902. Sweep verbatim: $ git grep -nE 'sectionName:[[:space:]]+(https|"https")[[:space:]]*$' \ platform/*/chart/ products/ clusters/ core/ 2>/dev/null \ | grep -v 'platform/gateway-api/chart/templates' platform/gitea/chart/values.yaml:168: sectionName: https platform/grafana/chart/values.yaml:124: sectionName: https platform/harbor/chart/values.yaml:437: sectionName: https platform/keycloak/chart/values.yaml:482: sectionName: https platform/newapi/chart/values.yaml:721: sectionName: https platform/openbao/chart/values.yaml:72: sectionName: https platform/powerdns/chart/values.yaml:407: sectionName: https platform/stalwart-tenant/chart/values.yaml:297: sectionName: https products/catalyst/bootstrap/api/internal/handler/sme_tenant_gitops.go:802: sectionName: https Fix (Option C — omit sectionName, same as PR #1888): - 8 blueprint values.yaml defaults flipped from `sectionName: https` to `sectionName: ""`. The chart templates already guard with `{{- with .Values.gateway.parentRef.sectionName }}`, so a blank value drops the field entirely and Cilium Gateway matches by hostname filter. - platform/newapi/chart/templates/httproute.yaml was the outlier: it used `default "https" $parent.sectionName` which fell back to `https` even when values.yaml said empty. Rewritten to `{{- with $parent.sectionName }}` so empty drops the field — same pattern as the other 7 blueprints. - products/catalyst/bootstrap/api/internal/handler/sme_tenant_gitops.go renders a per-tenant bp-keycloak HelmRelease and injected `sectionName: https` into spec.values. Flipped to `sectionName: ""` so the bp-keycloak chart's `{{- with }}` guard drops the field. Validation (real `helm template`, default values, gateway enabled, no sectionName override) — Principle #15: gitea : sectionName lines in rendered output = 0 grafana : sectionName lines in rendered output = 0 harbor : sectionName lines in rendered output = 0 keycloak : sectionName lines in rendered output = 0 openbao : sectionName lines in rendered output = 0 powerdns : sectionName lines in rendered output = 0 newapi : sectionName lines in rendered output = 0 stalwart-tenant : sectionName lines in rendered output = 0 Override path preserved — `--set ...parentRef.sectionName=https-omani-works` on each chart renders `sectionName: "https-omani-works"` correctly, so operators on single-zone clusters or non-Cilium gateways can still pin explicitly via bootstrap-kit overlay. helm lint clean on all 8 blueprint charts (newapi cnpg-cluster.yaml lint error is pre-existing on origin/main, unrelated to this fix). Chart bumps (each blueprint also bumps blueprint.yaml spec.version per #817 lockstep): bp-gitea 1.2.7 -> 1.2.8 bp-grafana 1.0.1 -> 1.0.2 bp-harbor 1.2.17 -> 1.2.18 bp-keycloak 1.4.5 -> 1.4.6 bp-newapi 1.4.22 -> 1.4.23 bp-openbao 1.2.16 -> 1.2.17 bp-powerdns 1.2.3 -> 1.2.4 bp-stalwart-tenant 0.1.2 -> 0.1.3 Refs TBD-A40. Co-authored-by: hatiyildiz <hatice.yildiz@openova.io> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| chart | ||
| blueprint.yaml | ||
| README.md | ||
Gitea
Per-Sovereign Git server for Catalyst. Hosts the public Blueprint catalog mirror, Org-private Blueprints, and per-Environment Gitea repos.
Status: Accepted | Updated: 2026-04-27
Catalyst role: Per-Sovereign supporting service in the Catalyst control plane (one Gitea per Sovereign on the management cluster). See
docs/PLATFORM-TECH-STACK.md§2.3 anddocs/ARCHITECTURE.md§3.
Overview
Gitea provides self-hosted Git with CI/CD capabilities:
- Internal Git repository hosting (per-Sovereign).
- Gitea Actions (GitHub Actions compatible).
- HA via intra-cluster replicas (not cross-region mirror — see Multi-Region section below).
- CNPG PostgreSQL backend.
Architecture
flowchart TB
subgraph Gitea["Gitea"]
Web[Web UI]
Git[Git Server]
Actions[Gitea Actions]
end
subgraph Backend["Backend"]
CNPG[CNPG Postgres]
SeaweedFS[SeaweedFS Storage]
end
subgraph Integrations
Flux[Flux CD]
Console[Catalyst console]
end
Web --> CNPG
Git --> CNPG
Actions --> SeaweedFS
Flux -->|"Clone"| Git
Console -->|"Discover"| Git
Multi-Region Strategy
Catalyst runs one Gitea per Sovereign on the management cluster. Cross-region resilience comes from intra-cluster HA (multiple replicas + CNPG primary-replica), not cross-region bidirectional mirror.
flowchart TB
subgraph Mgt["Management cluster (per Sovereign)"]
G[Gitea — N replicas, HA]
PG[CNPG primary]
PGR[CNPG read-replica]
G --> PG
PG -.->|"WAL streaming"| PGR
end
subgraph Region1["Workload region 1"]
F1[Per-vcluster Flux]
end
subgraph Region2["Workload region 2"]
F2[Per-vcluster Flux]
end
G --> F1
G --> F2
Why not cross-region bidirectional mirror?
- Single source of truth simplifies the merge story (the Sovereign-wide Catalyst console writes once, all Flux instances pull from one place).
- Bidirectional mirror would create write-conflict semantics that complicate EnvironmentPolicy enforcement (which requires PR approvals to be authoritative on the destination repo).
- Workload region failures don't affect Gitea — Flux is read-mostly during outages and the management cluster is the primary failure domain to harden.
If the Sovereign needs Gitea continuity across a full management-cluster failure, the relevant pattern is a DR replica of the management cluster — not Gitea mirroring inside one Sovereign.
Configuration
Gitea Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea
namespace: gitea
spec:
replicas: 1
template:
spec:
containers:
- name: gitea
image: gitea/gitea:1.21
env:
- name: GITEA__database__DB_TYPE
value: postgres
- name: GITEA__database__HOST
value: gitea-postgres-rw.databases.svc:5432
- name: GITEA__storage__STORAGE_TYPE
value: seaweedfs
- name: GITEA__storage__SEAWEEDFS_ENDPOINT
value: seaweedfs.storage.svc:8333
Mirror Configuration
# app.ini
[mirror]
ENABLED = true
DISABLE_NEW_PULL = false
DISABLE_NEW_PUSH = false
DEFAULT_INTERVAL = 1m
Gitea Actions
GitHub Actions compatible CI/CD:
# .gitea/workflows/ci.yaml
name: CI
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: make build
- name: Test
run: make test
Actions Runner
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea-runner
namespace: gitea
spec:
replicas: 2
template:
spec:
containers:
- name: runner
image: gitea/act_runner:latest
env:
- name: GITEA_INSTANCE_URL
value: https://gitea.<location-code>.<sovereign-domain>
- name: GITEA_RUNNER_REGISTRATION_TOKEN
valueFrom:
secretKeyRef:
name: gitea-runner-token
key: token
Integration Points
| Integration | Purpose |
|---|---|
| Flux CD | GitOps source repository |
| Catalyst console | Repository discovery, templates |
| External Secrets | Token management |
| CNPG | PostgreSQL database |
| SeaweedFS | LFS and Actions storage |
Backup
Gitea data is backed up via:
- CNPG for PostgreSQL (WAL streaming to async standby; backed up via Velero to SeaweedFS + cloud archival).
- SeaweedFS replication for LFS/Actions storage.
- Velero scheduled backups of the gitea namespace.
Part of OpenOva