hearth/kubernetes/forgejo/deployment.yaml
Eric Garcia e78000831e Initial commit: Port infrastructure from coherence-mcp
Hearth is the infrastructure home for the letemcook ecosystem.

Ported from coherence-mcp/infra:
- Terraform modules (VPC, EKS, IAM, NLB, S3, storage)
- Kubernetes manifests (Forgejo, ingress, cert-manager, karpenter)
- Deployment scripts (phased rollout)

Status: Not deployed. EKS cluster needs to be provisioned.

Next steps:
1. Bootstrap terraform backend
2. Deploy phase 1 (foundation)
3. Deploy phase 2 (core services including Forgejo)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:06:13 -05:00

263 lines
8.1 KiB
YAML

# 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