From 75698636c63fbbf18eb924890c45e6d8d890ac75 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 3 Jul 2026 21:28:32 +0200 Subject: [PATCH] Deploy Forgejo on railiance01 using gitea-charts/gitea 12.5.0 Pin chart to 12.5.0 because 12.6+ calls `gitea config edit-ini`, which Forgejo 11 lacks. Ingress targets forgejo-gitea-http (Helm release naming). Smoke test uses GET for /v2/ registry challenge (HEAD returns 405). --- Makefile | 67 ++++++++++++++++++++- docs/forgejo-on-railiance01.md | 80 +++++++++++++++++++++++++ helm/forgejo-registry-values.yaml | 14 +++++ helm/forgejo-secrets.sops.yaml.template | 15 +++++ helm/forgejo-values.yaml | 47 +++++++++++++++ manifests/forgejo-ingress.yaml | 45 ++++++++++++++ manifests/forgejo-ssh-nodeport.yaml | 21 +++++++ tools/forgejo-smoke.sh | 9 +++ 8 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 docs/forgejo-on-railiance01.md create mode 100644 helm/forgejo-registry-values.yaml create mode 100644 helm/forgejo-secrets.sops.yaml.template create mode 100644 helm/forgejo-values.yaml create mode 100644 manifests/forgejo-ingress.yaml create mode 100644 manifests/forgejo-ssh-nodeport.yaml create mode 100755 tools/forgejo-smoke.sh diff --git a/Makefile b/Makefile index 8fd33a1..6a5ea46 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,24 @@ REUSE_CERTIFICATE ?= reuse-surface-tls RAILIANCE01_KUBECONFIG ?= $(HOME)/.kube/config-hosteurope INTER_HUB_KUBECONFIG ?= $(RAILIANCE01_KUBECONFIG) REUSE_KUBECONFIG ?= $(RAILIANCE01_KUBECONFIG) +FORGEJO_KUBECONFIG ?= $(RAILIANCE01_KUBECONFIG) +FORGEJO_RELEASE ?= forgejo +FORGEJO_NAMESPACE ?= forgejo +FORGEJO_CHART ?= gitea-charts/gitea +# Forgejo 11.x (Gitea 1.22) lacks `gitea config edit-ini`; chart 12.6+ requires Gitea 1.26+. +FORGEJO_CHART_VERSION ?= 12.5.0 +FORGEJO_VALUES ?= helm/forgejo-values.yaml +FORGEJO_REGISTRY_VALUES ?= helm/forgejo-registry-values.yaml +FORGEJO_SECRETS ?= helm/forgejo-secrets.sops.yaml +FORGEJO_INGRESS ?= manifests/forgejo-ingress.yaml +FORGEJO_SSH_NODEPORT ?= manifests/forgejo-ssh-nodeport.yaml +FORGEJO_BASE_URL ?= https://forgejo.coulomb.social +FORGEJO_DB_CLUSTER ?= forgejo-db +FORGEJO_DB_NAMESPACE ?= databases INTER_HUB_IMAGE_REF = $(INTER_HUB_IMAGE_REPOSITORY):$(INTER_HUB_IMAGE_TAG) INTER_HUB_IMAGE_SET_ARG = $(if $(strip $(INTER_HUB_IMAGE_TAG)),--set image.tag=$(INTER_HUB_IMAGE_TAG),) -SOPS_SENTINEL ?= +SOPS_SENTINEL ?= $(FORGEJO_SECRETS) DRY_RUN_CREATE_NAMESPACES ?= false ##@ Operator checks @@ -153,6 +167,55 @@ inter-hub-smoke: ## Verify public inter-hub v2 route and OpenAPI surface after r inter-hub-logs: check-railiance01-kubeconfig ## Tail inter-hub app logs from Railiance01 KUBECONFIG="$(INTER_HUB_KUBECONFIG)" kubectl logs -n $(INTER_HUB_NAMESPACE) -l app=$(INTER_HUB_RELEASE) -f --tail=50 +##@ Forgejo (forgejo.coulomb.social) + +forgejo-dry-run: check-railiance01-kubeconfig check-sops ## helm template render for Forgejo + KUBECONFIG="$(FORGEJO_KUBECONFIG)" helm template $(FORGEJO_RELEASE) $(FORGEJO_CHART) \ + --version $(FORGEJO_CHART_VERSION) \ + --namespace $(FORGEJO_NAMESPACE) \ + -f $(FORGEJO_VALUES) \ + -f $(FORGEJO_REGISTRY_VALUES) \ + -f <(sops -d $(FORGEJO_SECRETS)) + +forgejo-server-dry-run: check-railiance01-kubeconfig check-sops ## Helm server dry-run Forgejo upgrade + KUBECONFIG="$(FORGEJO_KUBECONFIG)" helm upgrade --install $(FORGEJO_RELEASE) $(FORGEJO_CHART) \ + --version $(FORGEJO_CHART_VERSION) \ + --namespace $(FORGEJO_NAMESPACE) --create-namespace \ + -f $(FORGEJO_VALUES) \ + -f $(FORGEJO_REGISTRY_VALUES) \ + -f <(sops -d $(FORGEJO_SECRETS)) \ + --dry-run=server --timeout 5m + +forgejo-deploy: check-railiance01-kubeconfig check-sops ## Deploy / upgrade Forgejo on railiance01 + KUBECONFIG="$(FORGEJO_KUBECONFIG)" helm repo add gitea-charts https://dl.gitea.com/charts/ --force-update + KUBECONFIG="$(FORGEJO_KUBECONFIG)" helm upgrade --install $(FORGEJO_RELEASE) $(FORGEJO_CHART) \ + --version $(FORGEJO_CHART_VERSION) \ + --namespace $(FORGEJO_NAMESPACE) --create-namespace \ + -f $(FORGEJO_VALUES) \ + -f $(FORGEJO_REGISTRY_VALUES) \ + -f <(sops -d $(FORGEJO_SECRETS)) \ + --wait --timeout 10m + +forgejo-ingress-deploy: check-railiance01-kubeconfig ## Apply Forgejo HTTPS ingress + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl apply -f $(FORGEJO_INGRESS) + +forgejo-ssh-nodeport-deploy: check-railiance01-kubeconfig ## Apply Forgejo SSH NodePort (30022) + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl apply -f $(FORGEJO_SSH_NODEPORT) + +forgejo-status: check-railiance01-kubeconfig ## Show Forgejo pods, svc, ingress, cert, database + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl get pods,svc,ingress,certificate,pvc -n $(FORGEJO_NAMESPACE) --ignore-not-found + @if KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl cnpg status $(FORGEJO_DB_CLUSTER) -n $(FORGEJO_DB_NAMESPACE) >/dev/null 2>&1; then \ + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl cnpg status $(FORGEJO_DB_CLUSTER) -n $(FORGEJO_DB_NAMESPACE); \ + else \ + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl get cluster $(FORGEJO_DB_CLUSTER) -n $(FORGEJO_DB_NAMESPACE) --ignore-not-found; \ + fi + +forgejo-smoke: ## Verify Forgejo web and OCI registry challenge + FORGEJO_BASE_URL="$(FORGEJO_BASE_URL)" tools/forgejo-smoke.sh + +forgejo-logs: check-railiance01-kubeconfig ## Tail Forgejo application logs + KUBECONFIG="$(FORGEJO_KUBECONFIG)" kubectl logs -n $(FORGEJO_NAMESPACE) -l app.kubernetes.io/instance=$(FORGEJO_RELEASE) -f --tail=50 + ##@ reuse-surface (reuse.coulomb.social) reuse-dry-run: check-railiance01-kubeconfig ## helm template render (no apply) for reuse-surface @@ -183,4 +246,4 @@ help: ## Show this help /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } \ /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(MAKEFILE_LIST) -.PHONY: check-tools check-sops k8s-server-dry-run apps-pg-status check-railiance01-kubeconfig check-inter-hub-image-tag check-inter-hub-image vergabe-dry-run vergabe-deploy vergabe-ingress-deploy vergabe-status vergabe-migrate vergabe-seed vergabe-superuser vergabe-logs vergabe-db-url-secret inter-hub-render-baseline inter-hub-dry-run inter-hub-server-dry-run inter-hub-deploy inter-hub-status inter-hub-release-info inter-hub-smoke inter-hub-logs reuse-dry-run reuse-deploy reuse-status reuse-smoke reuse-logs help +.PHONY: check-tools check-sops k8s-server-dry-run apps-pg-status check-railiance01-kubeconfig check-inter-hub-image-tag check-inter-hub-image vergabe-dry-run vergabe-deploy vergabe-ingress-deploy vergabe-status vergabe-migrate vergabe-seed vergabe-superuser vergabe-logs vergabe-db-url-secret forgejo-dry-run forgejo-server-dry-run forgejo-deploy forgejo-ingress-deploy forgejo-ssh-nodeport-deploy forgejo-status forgejo-smoke forgejo-logs inter-hub-render-baseline inter-hub-dry-run inter-hub-server-dry-run inter-hub-deploy inter-hub-status inter-hub-release-info inter-hub-smoke inter-hub-logs reuse-dry-run reuse-deploy reuse-status reuse-smoke reuse-logs help diff --git a/docs/forgejo-on-railiance01.md b/docs/forgejo-on-railiance01.md new file mode 100644 index 0000000..d5750b4 --- /dev/null +++ b/docs/forgejo-on-railiance01.md @@ -0,0 +1,80 @@ +# Forgejo on railiance01 + +Production source forge at **`https://forgejo.coulomb.social`**. + +Mirrors the coulombcore Gitea pattern (`railiance-forge`) but targets +**railiance01** using the same OAS split as other S5 apps (`inter-hub`, +`reuse-surface`). + +## Layer ownership + +| Layer | Repo | Concern | +| --- | --- | --- | +| S3 | `railiance-platform` | `forgejo-db` CNPG cluster + network policies | +| S5 | `railiance-apps` | Helm release, ingress, operator Makefile | +| S2 | `railiance-cluster` | Traefik, cert-manager, cnpg operator | + +Hostname decision: `the-custodian/docs/forgejo-production-decisions.md`. + +## Hosts + +| Item | Value | +| --- | --- | +| Server | railiance01 `92.205.62.239` | +| Namespace | `forgejo` | +| Helm release | `forgejo` | +| HTTP service | `forgejo-gitea-http` (chart naming; ingress must target this) | +| Chart | `gitea-charts/gitea` **12.5.0** (Forgejo-compatible; 12.6+ needs Gitea 1.26 `config edit-ini`) | +| Image | `code.forgejo.org/forgejo/forgejo:11.0.3` | +| Database | `forgejo-db-rw.databases.svc.cluster.local:5432` | +| Kubeconfig | `~/.kube/config-hosteurope` | + +## Bootstrap (first deploy) + +### 1. Database credentials (platform) + +```bash +cd ~/railiance-platform +# One-time: create and SOPS-encrypt helm/forgejo-db-secret.sops.yaml from template +KUBECONFIG=~/.kube/config-hosteurope make forgejo-db-deploy +KUBECONFIG=~/.kube/config-hosteurope make forgejo-db-status +``` + +### 2. Application secrets (apps) + +```bash +cd ~/railiance-apps +# Encrypt helm/forgejo-secrets.sops.yaml from template (DB PASSWD must match platform secret) +make check-sops +``` + +### 3. Deploy Forgejo + +```bash +cd ~/railiance-apps +make forgejo-dry-run +make forgejo-deploy +make forgejo-ingress-deploy +make forgejo-ssh-nodeport-deploy # optional; git+ssh via nodePort 30022 +make forgejo-status +make forgejo-smoke +``` + +## Day-2 operator targets + +```bash +make forgejo-status +make forgejo-logs +make forgejo-smoke +``` + +## Coexistence with Gitea + +Gitea on coulombcore remains canonical until `RAIL-HO-WP-0005` migration drills +and cutover pass. Do not repoint repo remotes until Wave 1 cutover is approved. + +## Related + +- Gitea reference: `~/railiance-forge/Makefile` (`gitea-deploy`) +- Drain plan: `the-custodian/docs/coulombcore-drain-placement-plan.md` Wave 1 +- Onboarding checklist: `docs/s5-app-onboarding-checklist.md` \ No newline at end of file diff --git a/helm/forgejo-registry-values.yaml b/helm/forgejo-registry-values.yaml new file mode 100644 index 0000000..c4d27c1 --- /dev/null +++ b/helm/forgejo-registry-values.yaml @@ -0,0 +1,14 @@ +# Public endpoint and package registry settings for Forgejo on railiance01. +service: + http: + type: ClusterIP + +gitea: + config: + packages: + ENABLED: true + LIMIT_SIZE_CONTAINER: -1 + repository: + DISABLED_REPO_UNITS: "" + server: + ROOT_URL: "https://forgejo.coulomb.social/" \ No newline at end of file diff --git a/helm/forgejo-secrets.sops.yaml.template b/helm/forgejo-secrets.sops.yaml.template new file mode 100644 index 0000000..80a77e7 --- /dev/null +++ b/helm/forgejo-secrets.sops.yaml.template @@ -0,0 +1,15 @@ +# Encrypt as helm/forgejo-secrets.sops.yaml before production deploy. +# Contains database PASSWD and admin password consumed by the gitea chart. +# +# gitea: +# admin: +# password: +# config: +# database: +# PASSWD: +gitea: + admin: + password: REPLACE_WITH_ADMIN_PASSWORD + config: + database: + PASSWD: REPLACE_WITH_DB_PASSWORD \ No newline at end of file diff --git a/helm/forgejo-values.yaml b/helm/forgejo-values.yaml new file mode 100644 index 0000000..a49b08d --- /dev/null +++ b/helm/forgejo-values.yaml @@ -0,0 +1,47 @@ +# Non-secret Forgejo Helm values (gitea-charts/gitea chart + Forgejo image). +# Layer helm/forgejo-secrets.sops.yaml for database password and admin credentials. +service: + http: + type: ClusterIP + +image: + registry: code.forgejo.org + repository: forgejo/forgejo + tag: "11.0.3" + rootless: true + +persistence: + enabled: true + size: 10Gi + +postgresql: + enabled: false + +postgresql-ha: + enabled: false + +redis-cluster: + enabled: false + +valkey-cluster: + enabled: false + +gitea: + admin: + username: forgejo_admin + email: admin@coulomb.social + passwordMode: initialOnlyRequireReset + config: + database: + DB_TYPE: postgres + HOST: forgejo-db-rw.databases.svc.cluster.local:5432 + NAME: forgejo + USER: forgejo + server: + DOMAIN: forgejo.coulomb.social + SSH_DOMAIN: forgejo.coulomb.social + SSH_PORT: 22 + SSH_LISTEN_PORT: 2222 + DISABLE_SSH: false + service: + DISABLE_REGISTRATION: true \ No newline at end of file diff --git a/manifests/forgejo-ingress.yaml b/manifests/forgejo-ingress.yaml new file mode 100644 index 0000000..8d2a52c --- /dev/null +++ b/manifests/forgejo-ingress.yaml @@ -0,0 +1,45 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: forgejo + namespace: forgejo + labels: + app.kubernetes.io/name: forgejo + app.kubernetes.io/instance: forgejo + app.kubernetes.io/part-of: railiance-apps + railiance/component: forgejo-public-endpoint + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + ingressClassName: traefik + rules: + - host: forgejo.coulomb.social + http: + paths: + - path: /api/packages + pathType: Prefix + backend: + service: + name: forgejo-gitea-http + port: + number: 3000 + - path: /v2 + pathType: Prefix + backend: + service: + name: forgejo-gitea-http + port: + number: 3000 + - path: / + pathType: Prefix + backend: + service: + name: forgejo-gitea-http + port: + number: 3000 + tls: + - hosts: + - forgejo.coulomb.social + secretName: forgejo-tls \ No newline at end of file diff --git a/manifests/forgejo-ssh-nodeport.yaml b/manifests/forgejo-ssh-nodeport.yaml new file mode 100644 index 0000000..42998e2 --- /dev/null +++ b/manifests/forgejo-ssh-nodeport.yaml @@ -0,0 +1,21 @@ +# Git/SSH access for Forgejo (NodePort pattern mirrors coulombcore Gitea). +apiVersion: v1 +kind: Service +metadata: + name: forgejo-ssh-nodeport + namespace: forgejo + labels: + app.kubernetes.io/name: forgejo + app.kubernetes.io/instance: forgejo + app.kubernetes.io/part-of: railiance-apps +spec: + type: NodePort + selector: + app.kubernetes.io/instance: forgejo + app.kubernetes.io/name: gitea + ports: + - name: ssh + port: 22 + targetPort: 2222 + nodePort: 30022 + protocol: TCP \ No newline at end of file diff --git a/tools/forgejo-smoke.sh b/tools/forgejo-smoke.sh new file mode 100755 index 0000000..582680e --- /dev/null +++ b/tools/forgejo-smoke.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +BASE_URL="${FORGEJO_BASE_URL:-https://forgejo.coulomb.social}" + +curl -fsS "${BASE_URL}/" -o /dev/null -w "root_http=%{http_code}\n" +# HEAD returns 405 on Forgejo/Gitea; GET returns 401 + Docker-Distribution-Api-Version. +curl -sSI -X GET "${BASE_URL}/v2/" | awk 'BEGIN{code=""; ok=0} /^HTTP/{code=$2} /^[Dd]ocker-[Dd]istribution-[Aa]pi-[Vv]ersion:/{ok=1; print "registry_challenge=ok"} END{if (code=="" || !ok) exit 1; if (code!="401" && code!="200") {print "registry_http=" code; exit 1} else {print "registry_http=" code}}' +echo "forgejo smoke ok: ${BASE_URL}" \ No newline at end of file