feat: deploy Forgejo self-hosted git server
- Add ZFS NFS datasets: media-pool/git (50G) and media-pool/git-db (10G) - Add nfs-git and nfs-git-db NFS subdir provisioner Helm values - Deploy Forgejo 10 (StatefulSet) + PostgreSQL 16 (StatefulSet) in infrastructure namespace - StorageClasses: nfs-git (repos/LFS, 50Gi) and nfs-git-db (postgres, 10Gi) - Ingress: git.vandachevici.ro with TLS via cert-manager - SSH NodePort 30022 for git clone ssh://git@host:30022/user/repo.git - Authentik OIDC provider configured (client ID: ZdnrHgyfUncSIPPrOe1o7UAA42N7BMhUHXjQVw4Y) - Add 'git' subdomain to dns-updater configmap Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
29440b68a9
commit
88540b6ded
4 changed files with 420 additions and 0 deletions
14
deployment/helm/nfs-provisioners/values-git-db.yaml
Normal file
14
deployment/helm/nfs-provisioners/values-git-db.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
nfs:
|
||||||
|
mountOptions:
|
||||||
|
- soft
|
||||||
|
- timeo=30
|
||||||
|
path: /media-pool/git-db
|
||||||
|
server: 192.168.2.193
|
||||||
|
storageClass:
|
||||||
|
allowVolumeExpansion: true
|
||||||
|
archiveOnDelete: true
|
||||||
|
defaultClass: false
|
||||||
|
mountOptions:
|
||||||
|
- soft
|
||||||
|
- timeo=30
|
||||||
|
name: nfs-git-db
|
||||||
14
deployment/helm/nfs-provisioners/values-git.yaml
Normal file
14
deployment/helm/nfs-provisioners/values-git.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
nfs:
|
||||||
|
mountOptions:
|
||||||
|
- soft
|
||||||
|
- timeo=30
|
||||||
|
path: /media-pool/git
|
||||||
|
server: 192.168.2.193
|
||||||
|
storageClass:
|
||||||
|
allowVolumeExpansion: true
|
||||||
|
archiveOnDelete: true
|
||||||
|
defaultClass: false
|
||||||
|
mountOptions:
|
||||||
|
- soft
|
||||||
|
- timeo=30
|
||||||
|
name: nfs-git
|
||||||
72
deployment/infrastructure/dns-updater.yaml
Normal file
72
deployment/infrastructure/dns-updater.yaml
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
annotations: {}
|
||||||
|
name: dns-updater-config
|
||||||
|
namespace: infrastructure
|
||||||
|
data:
|
||||||
|
DOMAIN: vandachevici.ro
|
||||||
|
NAME: photos;backup;media;chat;openttd;excalidraw;prv;drive;grafana;paperclip;proxmox;parts;dns;games;git
|
||||||
|
REMOVE_DUPLICATES: 'true'
|
||||||
|
SLEEP_INTERVAL: '60'
|
||||||
|
---
|
||||||
|
# NOTE: Secret 'dns-updater-secret' must be created manually:
|
||||||
|
# kubectl create secret generic dns-updater-secret \
|
||||||
|
# --from-literal=digitalocean-token=<YOUR_TOKEN> \
|
||||||
|
# -n infrastructure
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
annotations: {}
|
||||||
|
labels:
|
||||||
|
app: dns-updater
|
||||||
|
name: dns-updater
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: dns-updater
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: dns-updater
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
- name: DIGITALOCEAN_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: digitalocean-token
|
||||||
|
name: dns-updater-secret
|
||||||
|
- name: DOMAIN
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: DOMAIN
|
||||||
|
name: dns-updater-config
|
||||||
|
- name: NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: NAME
|
||||||
|
name: dns-updater-config
|
||||||
|
- name: SLEEP_INTERVAL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: SLEEP_INTERVAL
|
||||||
|
name: dns-updater-config
|
||||||
|
- name: REMOVE_DUPLICATES
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: REMOVE_DUPLICATES
|
||||||
|
name: dns-updater-config
|
||||||
|
image: tunix/digitalocean-dyndns:latest
|
||||||
|
name: dns-updater
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
restartPolicy: Always
|
||||||
320
deployment/infrastructure/forgejo.yaml
Normal file
320
deployment/infrastructure/forgejo.yaml
Normal file
|
|
@ -0,0 +1,320 @@
|
||||||
|
---
|
||||||
|
# Forgejo git server + PostgreSQL database
|
||||||
|
# Domain: git.vandachevici.ro
|
||||||
|
# Auth: Authentik OIDC (configured post-deploy via admin UI)
|
||||||
|
# Storage: NFS on HP ProLiant (media-pool/git, media-pool/git-db)
|
||||||
|
# SSH: NodePort 30022 (clone with: git clone ssh://git@<host>:30022/<user>/<repo>.git)
|
||||||
|
#
|
||||||
|
# Initial deploy steps after applying:
|
||||||
|
# 1. Create Authentik OIDC provider (see plan.md todo: authentik-oidc)
|
||||||
|
# 2. In Forgejo admin: Site Administration → Authentication Sources → Add OAuth2 Source
|
||||||
|
# - Provider: OpenID Connect
|
||||||
|
# - Name: authentik
|
||||||
|
# - Client ID/Secret: from Authentik
|
||||||
|
# - OpenID Discovery URL: https://auth.vandachevici.ro/application/o/forgejo/.well-known/openid-configuration
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: forgejo-db-secret
|
||||||
|
namespace: infrastructure
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
POSTGRES_DB: forgejo
|
||||||
|
POSTGRES_USER: forgejo
|
||||||
|
POSTGRES_PASSWORD: Hg9mKnRpQwXvTz2Ld8cJsY4bAeUfN6
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: forgejo-secret
|
||||||
|
namespace: infrastructure
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# Random secret key for Forgejo session/cookie signing
|
||||||
|
# Generate with: openssl rand -hex 32
|
||||||
|
secret-key: 5f323a291b24ba0d83c5df56569eeeb44e5eda0bcfc9f3d9601d5ab46f5f3754
|
||||||
|
|
||||||
|
---
|
||||||
|
# PostgreSQL for Forgejo
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: forgejo-db-pvc
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 10Gi
|
||||||
|
storageClassName: nfs-git-db
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: forgejo-db
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: forgejo-db
|
||||||
|
serviceName: forgejo-db
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: forgejo-db
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:16-alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
name: postgres
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: forgejo-db-secret
|
||||||
|
key: POSTGRES_DB
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: forgejo-db-secret
|
||||||
|
key: POSTGRES_USER
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: forgejo-db-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
|
- name: PGDATA
|
||||||
|
value: /var/lib/postgresql/data/pgdata
|
||||||
|
volumeMounts:
|
||||||
|
- name: db-data
|
||||||
|
mountPath: /var/lib/postgresql/data
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- pg_isready
|
||||||
|
- -U
|
||||||
|
- forgejo
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- pg_isready
|
||||||
|
- -U
|
||||||
|
- forgejo
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
volumes:
|
||||||
|
- name: db-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: forgejo-db-pvc
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: forgejo-db
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: forgejo-db
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
port: 5432
|
||||||
|
targetPort: 5432
|
||||||
|
|
||||||
|
---
|
||||||
|
# Forgejo git server
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: forgejo-data-pvc
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 50Gi
|
||||||
|
storageClassName: nfs-git
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: forgejo
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: forgejo
|
||||||
|
serviceName: forgejo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: forgejo
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: wait-for-db
|
||||||
|
image: busybox:1.36
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
until nc -z forgejo-db 5432; do
|
||||||
|
echo "Waiting for PostgreSQL..."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "PostgreSQL is ready"
|
||||||
|
containers:
|
||||||
|
- name: forgejo
|
||||||
|
image: codeberg.org/forgejo/forgejo:10
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
name: http
|
||||||
|
- containerPort: 22
|
||||||
|
name: ssh
|
||||||
|
env:
|
||||||
|
- name: FORGEJO__database__DB_TYPE
|
||||||
|
value: postgres
|
||||||
|
- name: FORGEJO__database__HOST
|
||||||
|
value: forgejo-db:5432
|
||||||
|
- name: FORGEJO__database__NAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: forgejo-db-secret
|
||||||
|
key: POSTGRES_DB
|
||||||
|
- name: FORGEJO__database__USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: forgejo-db-secret
|
||||||
|
key: POSTGRES_USER
|
||||||
|
- name: FORGEJO__database__PASSWD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: forgejo-db-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
|
- name: FORGEJO__server__DOMAIN
|
||||||
|
value: git.vandachevici.ro
|
||||||
|
- name: FORGEJO__server__ROOT_URL
|
||||||
|
value: https://git.vandachevici.ro
|
||||||
|
- name: FORGEJO__server__SSH_DOMAIN
|
||||||
|
value: git.vandachevici.ro
|
||||||
|
- name: FORGEJO__server__SSH_PORT
|
||||||
|
value: "30022"
|
||||||
|
- name: FORGEJO__server__SSH_LISTEN_PORT
|
||||||
|
value: "22"
|
||||||
|
- name: FORGEJO__security__SECRET_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: forgejo-secret
|
||||||
|
key: secret-key
|
||||||
|
- name: FORGEJO__service__DISABLE_REGISTRATION
|
||||||
|
value: "false"
|
||||||
|
- name: FORGEJO__service__REQUIRE_SIGNIN_VIEW
|
||||||
|
value: "false"
|
||||||
|
volumeMounts:
|
||||||
|
- name: forgejo-data
|
||||||
|
mountPath: /data
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 3000
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 15
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 3000
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 512Mi
|
||||||
|
volumes:
|
||||||
|
- name: forgejo-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: forgejo-data-pvc
|
||||||
|
|
||||||
|
---
|
||||||
|
# ClusterIP for HTTP (used by ingress)
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: forgejo
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: forgejo
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 3000
|
||||||
|
targetPort: 3000
|
||||||
|
|
||||||
|
---
|
||||||
|
# NodePort for SSH git access (git clone ssh://git@git.vandachevici.ro:30022/user/repo.git)
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: forgejo-ssh
|
||||||
|
namespace: infrastructure
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: forgejo
|
||||||
|
ports:
|
||||||
|
- name: ssh
|
||||||
|
port: 22
|
||||||
|
targetPort: 22
|
||||||
|
nodePort: 30022
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: forgejo
|
||||||
|
namespace: infrastructure
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: git.vandachevici.ro
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: forgejo
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- git.vandachevici.ro
|
||||||
|
secretName: forgejo-tls
|
||||||
Loading…
Add table
Reference in a new issue