# Forgejo Deployment # RFC 0040: Self-Hosted Core Services # RFC 0049: Service Database Unification - CockroachDB backend # ADR 0004: Set It and Forget It - auto-scaling via HPA # ADR 0005: Full-stack self-hosting # # Spike 2026-01-19: Forgejo v9 works with CockroachDB after setting # sql.defaults.serial_normalization = 'sql_sequence' to fix XORM SERIAL handling. # Requires extended startup probes for initial 230-table migration. # # Integrated with Keycloak SSO apiVersion: apps/v1 kind: Deployment metadata: name: forgejo namespace: forgejo labels: app.kubernetes.io/name: forgejo app.kubernetes.io/part-of: core-services spec: replicas: 1 # Single replica due to ReadWriteOnce storage; HA requires EFS or Redis queue selector: matchLabels: app: forgejo strategy: type: Recreate # Required for single replica with RWO storage (LevelDB queue lock) template: metadata: labels: app: forgejo app.kubernetes.io/name: forgejo annotations: prometheus.io/scrape: "true" prometheus.io/port: "3000" prometheus.io/path: "/metrics" spec: serviceAccountName: forgejo terminationGracePeriodSeconds: 60 # Spread pods across AZs for HA affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app: forgejo topologyKey: topology.kubernetes.io/zone # Forgejo needs elevated permissions for initial setup (chown, su-exec) # After initial setup, consider using a custom image with pre-set permissions securityContext: fsGroup: 1000 runAsUser: 0 initContainers: # Wait for CockroachDB to be ready - name: wait-for-db image: postgres:16-alpine command: - /bin/sh - -c - | until pg_isready -h cockroachdb-public.cockroachdb.svc.cluster.local -p 26257; do echo "Waiting for CockroachDB..." sleep 5 done echo "CockroachDB is ready!" # Fix ssh directory permissions for git user - name: fix-permissions image: alpine:3.19 command: - /bin/sh - -c - | # Ensure ssh directory exists with correct permissions mkdir -p /data/git/.ssh chown -R 1000:1000 /data/git chmod 770 /data/git/.ssh echo "Permissions fixed" volumeMounts: - name: data mountPath: /data containers: - name: forgejo image: codeberg.org/forgejo/forgejo:9 imagePullPolicy: IfNotPresent env: # Database configuration (CockroachDB) - name: FORGEJO__database__DB_TYPE value: "postgres" - name: FORGEJO__database__HOST value: "cockroachdb-public.cockroachdb.svc.cluster.local:26257" - name: FORGEJO__database__NAME valueFrom: secretKeyRef: name: forgejo-cockroachdb key: database - name: FORGEJO__database__USER valueFrom: secretKeyRef: name: forgejo-cockroachdb key: username - name: FORGEJO__database__PASSWD valueFrom: secretKeyRef: name: forgejo-cockroachdb key: password - name: FORGEJO__database__SSL_MODE value: "require" - name: FORGEJO__database__CHARSET value: "utf8" # Server configuration - name: FORGEJO__server__DOMAIN value: "git.beyondtheuniverse.superviber.com" - name: FORGEJO__server__ROOT_URL value: "https://git.beyondtheuniverse.superviber.com" - name: FORGEJO__server__SSH_DOMAIN value: "git.beyondtheuniverse.superviber.com" - name: FORGEJO__server__SSH_PORT value: "22" - name: FORGEJO__server__LFS_START_SERVER value: "true" - name: FORGEJO__server__OFFLINE_MODE value: "false" # Security settings - name: FORGEJO__security__INSTALL_LOCK value: "true" - name: FORGEJO__security__SECRET_KEY valueFrom: secretKeyRef: name: forgejo-secrets key: secret-key - name: FORGEJO__security__INTERNAL_TOKEN valueFrom: secretKeyRef: name: forgejo-secrets key: internal-token # OAuth2 configuration (Keycloak SSO) - name: FORGEJO__oauth2__ENABLED value: "true" - name: FORGEJO__oauth2__JWT_SECRET valueFrom: secretKeyRef: name: forgejo-oauth key: jwt-secret # Session configuration (for HA) - name: FORGEJO__session__PROVIDER value: "db" - name: FORGEJO__session__PROVIDER_CONFIG value: "" # Cache configuration - name: FORGEJO__cache__ENABLED value: "true" - name: FORGEJO__cache__ADAPTER value: "memory" # Queue configuration - name: FORGEJO__queue__TYPE value: "level" - name: FORGEJO__queue__DATADIR value: "/data/queues" # Repository settings - name: FORGEJO__repository__ROOT value: "/data/git/repositories" - name: FORGEJO__repository__DEFAULT_BRANCH value: "main" # LFS settings - name: FORGEJO__lfs__PATH value: "/data/lfs" # Logging - name: FORGEJO__log__MODE value: "console" - name: FORGEJO__log__LEVEL value: "Info" # Metrics - name: FORGEJO__metrics__ENABLED value: "true" - name: FORGEJO__metrics__TOKEN valueFrom: secretKeyRef: name: forgejo-secrets key: metrics-token # Service settings - name: FORGEJO__service__DISABLE_REGISTRATION value: "true" - name: FORGEJO__service__REQUIRE_SIGNIN_VIEW value: "false" ports: - name: http containerPort: 3000 protocol: TCP - name: ssh containerPort: 22 protocol: TCP resources: requests: cpu: 200m memory: 256Mi limits: cpu: 1000m memory: 1Gi # Forgejo needs CHOWN, SETGID, SETUID capabilities for initial setup securityContext: capabilities: add: - CHOWN - SETGID - SETUID - FOWNER volumeMounts: - name: data mountPath: /data # Health probes - extended for CockroachDB migration time startupProbe: httpGet: path: /api/healthz port: 3000 initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 60 # Allow up to 10 minutes for initial migration readinessProbe: httpGet: path: /api/healthz port: 3000 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 livenessProbe: httpGet: path: /api/healthz port: 3000 initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 10 failureThreshold: 3 volumes: - name: data persistentVolumeClaim: claimName: forgejo-data