Add Forgejo deployment manifests for Argo CD GitOps

Migrate all Forgejo deployment resources from cluster to Git repository:
- Forgejo Deployment with PostgreSQL backend
- Forgejo Service and Ingress with TLS
- Forgejo PersistentVolumeClaim (5Gi)
- PostgreSQL StatefulSet and Service
- Backup CronJob (daily at 03:00 UTC, 14-day retention)

All existing PVCs (forgejo-data, postgres-data-forgejo-postgres-0) and
Pocket-ID SSO configuration are preserved. No data loss expected.

The Argo CD Application (app-forgejo.yaml) is already configured to
sync from apps/forgejo/ path in this repository.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
CTO Agent 2026-07-12 13:55:47 +00:00
parent 2ae7e30041
commit 08030791c1
7 changed files with 279 additions and 0 deletions

View file

@ -0,0 +1,80 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: forgejo-backup
namespace: backup
labels:
app: forgejo-backup
spec:
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 7
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: forgejo-backup
image: postgres:16-alpine
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -lc
- |
set -euo pipefail
ts=$(date -u +%Y%m%dT%H%M%SZ)
BACKUP_DIR="/data/forgejo-${ts}"
mkdir -p "${BACKUP_DIR}"
echo "[${ts}] Starting Forgejo backup..."
# Backup PostgreSQL database
echo "[$(date -u +%H:%M:%S)] Dumping PostgreSQL database..."
PGPASSWORD="${POSTGRES_PASSWORD}" pg_dump \
-h forgejo-postgres.forgejo.svc.cluster.local \
-U "${POSTGRES_USER}" \
-d "${POSTGRES_DB}" \
-F c \
-f "${BACKUP_DIR}/forgejo-db.dump"
echo "[$(date -u +%H:%M:%S)] Database backup complete: $(ls -lh ${BACKUP_DIR}/forgejo-db.dump | awk '{print $5}')"
# Create backup manifest
echo "backup_timestamp=${ts}" > "${BACKUP_DIR}/manifest.txt"
echo "type=postgresql_custom_dump" >> "${BACKUP_DIR}/manifest.txt"
echo "database=forgejo" >> "${BACKUP_DIR}/manifest.txt"
echo "restore_cmd=PGPASSWORD=<pass> pg_restore -h <host> -U forgejo -d forgejo -F c forgejo-db.dump" >> "${BACKUP_DIR}/manifest.txt"
# Cleanup old backups (keep 14 days)
find /data -maxdepth 1 -type d -name "forgejo-*" -mtime +14 -exec rm -rf {} + 2>/dev/null || true
echo "[$(date -u +%H:%M:%S)] Backup complete. Files:"
ls -lh "${BACKUP_DIR}/"
echo "[$(date -u +%H:%M:%S)] All backups in storage:"
ls -1 /data | grep "forgejo-"
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: forgejo-backup-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: forgejo-backup-secret
key: POSTGRES_PASSWORD
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: forgejo-backup-secret
key: POSTGRES_DB
volumeMounts:
- name: backup-data
mountPath: /data
volumes:
- name: backup-data
persistentVolumeClaim:
claimName: platform-backup-data

View file

@ -0,0 +1,82 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: forgejo
namespace: forgejo
spec:
replicas: 1
selector:
matchLabels:
app: forgejo
template:
metadata:
labels:
app: forgejo
spec:
initContainers:
- name: init-permissions
image: busybox:latest
command:
- sh
- -c
- chown -R 1000:1000 /var/lib/gitea && chmod -R 755 /var/lib/gitea
volumeMounts:
- name: data
mountPath: /var/lib/gitea
containers:
- name: forgejo
image: codeberg.org/forgejo/forgejo:10-rootless
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 3000
protocol: TCP
- name: ssh
containerPort: 22
protocol: TCP
env:
- name: USER_UID
value: "1000"
- name: USER_GID
value: "1000"
- name: FORGEJO__database__DB_TYPE
value: postgres
- name: FORGEJO__database__HOST
value: forgejo-postgres:5432
- name: FORGEJO__database__NAME
valueFrom:
secretKeyRef:
name: forgejo-postgres-secret
key: POSTGRES_DB
- name: FORGEJO__database__USER
valueFrom:
secretKeyRef:
name: forgejo-postgres-secret
key: POSTGRES_USER
- name: FORGEJO__database__PASSWD
valueFrom:
secretKeyRef:
name: forgejo-postgres-secret
key: POSTGRES_PASSWORD
- name: FORGEJO__server__DOMAIN
value: forgejo.basicstack.de
- name: FORGEJO__server__ROOT_URL
value: https://forgejo.basicstack.de
- name: FORGEJO__server__SSH_DOMAIN
value: forgejo.basicstack.de
- name: FORGEJO__service__DISABLE_REGISTRATION
value: "true"
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: "1"
memory: 2Gi
volumeMounts:
- name: data
mountPath: /var/lib/gitea
volumes:
- name: data
persistentVolumeClaim:
claimName: forgejo-data

View file

@ -0,0 +1,26 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: forgejo
namespace: forgejo
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.basicstack.de
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: forgejo
port:
number: 3000
tls:
- hosts:
- forgejo.basicstack.de
secretName: forgejo-tls

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: forgejo-postgres
namespace: forgejo
spec:
type: ClusterIP
selector:
app: forgejo-postgres
ports:
- port: 5432
targetPort: 5432
protocol: TCP

View file

@ -0,0 +1,48 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: forgejo-postgres
namespace: forgejo
spec:
serviceName: forgejo-postgres
replicas: 1
selector:
matchLabels:
app: forgejo-postgres
template:
metadata:
labels:
app: forgejo-postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
imagePullPolicy: IfNotPresent
ports:
- name: postgres
containerPort: 5432
protocol: TCP
envFrom:
- secretRef:
name: forgejo-postgres-secret
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
subPath: pgdata
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: hcloud-volumes-encrypted
resources:
requests:
storage: 10Gi

View file

@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: forgejo-data
namespace: forgejo
spec:
accessModes:
- ReadWriteOnce
storageClassName: hcloud-volumes-encrypted
resources:
requests:
storage: 5Gi

View file

@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: forgejo
namespace: forgejo
spec:
type: ClusterIP
selector:
app: forgejo
ports:
- name: http
port: 3000
targetPort: 3000
protocol: TCP
- name: ssh
port: 22
targetPort: 2222
protocol: TCP