openova/platform/gitea
e3mrah abf01b6f21
feat(platform): Gateway API migration audit (#387) (#401)
Migrates every minimal-Sovereign-set blueprint chart from
networking.k8s.io/v1.Ingress to gateway.networking.k8s.io/v1.HTTPRoute,
replacing the legacy Traefik-on-Sovereigns assumption with the canonical
Cilium + Envoy + Gateway API path per ADR-0001 §9.4 and the WBS §2
correction note (#388).

The single per-Sovereign Gateway is added as additional documents in
the existing bootstrap-kit slot clusters/_template/bootstrap-kit/01-cilium.yaml
(NOT a new top-level slot), since Cilium owns the GatewayClass. It
includes:

  - Certificate `sovereign-wildcard-tls` requesting `*.${SOVEREIGN_FQDN}`
    from `letsencrypt-dns01-prod` (cert-manager + #373 webhook)
  - Gateway `cilium-gateway` in `kube-system` with HTTPS (443, TLS
    terminate) + HTTP (80) listeners, allowedRoutes.namespaces.from=All

Per-blueprint HTTPRoute templates (canonical seam: each wrapper chart's
existing `templates/` directory):

  | Blueprint           | Host pattern                    | Backend port |
  |---------------------|---------------------------------|--------------|
  | bp-keycloak         | auth.<sov>                      | 80           |
  | bp-gitea            | git.<sov>                       | 3000         |
  | bp-openbao          | bao.<sov>                       | 8200         |
  | bp-grafana          | grafana.<sov>                   | 80           |
  | bp-harbor           | registry.<sov>                  | 80           |
  | bp-powerdns         | pdns.<sov>/api  (dual-mode)     | 8081         |
  | bp-catalyst-platform| console.<sov>, api.<sov>         | 80, 8080     |

bp-powerdns supports both Ingress (contabo legacy) and HTTPRoute
(Sovereign) simultaneously — the per-Sovereign overlay sets
`api.gateway.enabled=true` while leaving `api.enabled=true`. The
Ingress object is harmless on Cilium clusters with no Traefik. This
preserves contabo's existing pdns.openova.io flow per ADR-0001 §9.4.

bp-harbor flips `expose.type` from `ingress` to `clusterIP` in
platform/harbor/chart/values.yaml so the upstream chart no longer
emits its own Ingress; the HTTPRoute is the sole HTTP exposure.
TLS terminates at the Gateway (wildcard cert) rather than per-host
Certificates inside the chart.

bp-catalyst-platform's `templates/httproute.yaml` is NOT excluded by
.helmignore (unlike templates/ingress.yaml + templates/ingress-console-tls.yaml,
which remain contabo-only legacy demo infra). The contabo path keeps
serving console.openova.io/sovereign via Traefik unchanged.

Bootstrap-kit slot updates (per-Sovereign hostname interpolation):

  - 08-openbao.yaml      → gateway.host: bao.${SOVEREIGN_FQDN}
  - 09-keycloak.yaml     → gateway.host: auth.${SOVEREIGN_FQDN}
  - 10-gitea.yaml        → gateway.host: gitea.${SOVEREIGN_FQDN}
  - 11-powerdns.yaml     → api.host: pdns.${SOVEREIGN_FQDN}, api.gateway.enabled: true
  - 19-harbor.yaml       → gateway.host: registry.${SOVEREIGN_FQDN}
  - 25-grafana.yaml      → gateway.host: grafana.${SOVEREIGN_FQDN}

Server-side dry-run validation against the live Cilium Gateway API
CRDs on contabo: every HTTPRoute and the per-Sovereign Gateway
+ Certificate apply cleanly via `kubectl apply --dry-run=server`.

Contabo unaffected: clusters/contabo-mkt/* not modified. The legacy
SME ingresses (console-nova, marketplace, admin, axon, talentmesh,
stalwart, ...) continue to serve via Traefik as before. powerdns
on contabo remains on the Ingress path (api.gateway.enabled defaults
to false at the chart level).

Closes #387.

Co-authored-by: hatiyildiz <269457768+hatiyildiz@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 16:19:30 +04:00
..
chart feat(platform): Gateway API migration audit (#387) (#401) 2026-05-01 16:19:30 +04:00
blueprint.yaml fix(bp-gitea): override postgresql to bitnamilegacy (Bitnami evacuated docker.io tags) (#231) 2026-04-30 08:27:49 +02:00
README.md docs(seaweedfs+guacamole): replace MinIO with SeaweedFS as unified S3 encapsulation; add Guacamole to bp-relay 2026-04-28 10:23:46 +02:00

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 and docs/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