Add k8s Gitea deployment (HA-shaped, migration target for git.unkin.net)
Stand up the forge on k8s to replace the Puppet VM. Deployed HA-shaped to match what the VM already runs (multi-replica on shared storage + external DB/cache): official Gitea chart 12.6.0 (app 1.26.2) at 2 replicas on RWX CephFS, CNPG Postgres with S3 backup, standalone Valkey for cache/session/queue, Authentik OIDC, Actions disabled and the container registry moved to artifactapi. Serves a temporary git2.k8s.syd1.au.unkin.net host; cutover is staged (see the doc). - add apps/base/gitea (namespace, CNPG cluster+backup+pooler, Valkey, VaultAuth, VaultStaticSecrets, Gateway, HTTPRoute) - add apps/overlays/au-syd1/gitea (chart 12.6.0 via helm-through-kustomize + values, drop the chart test Pod) - register gitea in the platform ApplicationSet and AppProject - add docs/gitea-migration.md staged cutover plan Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
---
|
||||
# Ceph RGW (S3) backup target for the gitea CNPG cluster, provisioned by the
|
||||
# in-estate cephrgw-operator. One dedicated bucket + owner user per cluster.
|
||||
apiVersion: ceph.unkin.net/v1alpha1
|
||||
kind: ObjectStoreUser
|
||||
metadata:
|
||||
name: cnpg-gitea-backup
|
||||
namespace: gitea
|
||||
spec:
|
||||
displayName: "CNPG backup owner (gitea)"
|
||||
# RGW users are global; keep the uid namespace-qualified so it never collides.
|
||||
uid: cnpg-gitea-backup
|
||||
maxBuckets: 5
|
||||
# Operator writes AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (+ RGW_UID,
|
||||
# S3_ENDPOINT) into this Secret; the Cluster's barmanObjectStore consumes it.
|
||||
secretName: cnpg-gitea-backup-s3
|
||||
retainOnDelete: true
|
||||
---
|
||||
apiVersion: ceph.unkin.net/v1alpha1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: cnpg-gitea
|
||||
namespace: gitea
|
||||
spec:
|
||||
bucketName: cnpg-gitea
|
||||
ownerRef: cnpg-gitea-backup
|
||||
versioning: false
|
||||
tags:
|
||||
app: gitea
|
||||
purpose: cnpg-backup
|
||||
retainOnDelete: true
|
||||
---
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: ScheduledBackup
|
||||
metadata:
|
||||
name: cnpg-gitea-nightly
|
||||
namespace: gitea
|
||||
spec:
|
||||
# 6-field CNPG cron (seconds first). 04:00 — next free slot after netbox
|
||||
# (03:40), keeping the estate's 20-minute stagger.
|
||||
schedule: "0 0 4 * * *"
|
||||
immediate: false
|
||||
backupOwnerReference: self
|
||||
method: barmanObjectStore
|
||||
cluster:
|
||||
name: gitea-postgres
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
# Postgres for the k8s Gitea (replaces the Patroni-shared DB the VM uses). Gitea
|
||||
# already runs on Postgres, so cutover is a plain pg dump/restore (no engine
|
||||
# conversion). App-user creds come from the postgres-credentials Vault secret.
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: gitea-postgres
|
||||
namespace: gitea
|
||||
spec:
|
||||
affinity:
|
||||
podAntiAffinityType: preferred
|
||||
backup:
|
||||
# 30-day retention. Enforced by CNPG against the object store on each
|
||||
# successful base backup.
|
||||
retentionPolicy: 30d
|
||||
barmanObjectStore:
|
||||
# Dedicated per-cluster Ceph RGW bucket (cephrgw-operator provisions it).
|
||||
destinationPath: s3://cnpg-gitea
|
||||
endpointURL: https://s3.ceph.unkin.net
|
||||
# radosgw serves a Vault-PKI cert; trust the internal CA (reflected into
|
||||
# every namespace as the vault-ca-cert Secret).
|
||||
endpointCA:
|
||||
name: vault-ca-cert
|
||||
key: ca.crt
|
||||
# Keys minted by the ObjectStoreUser in cnpg_backup.yaml; never hardcoded.
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: cnpg-gitea-backup-s3
|
||||
key: AWS_ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: cnpg-gitea-backup-s3
|
||||
key: AWS_SECRET_ACCESS_KEY
|
||||
# Path prefix within the bucket; keep stable across restores (see docs).
|
||||
serverName: gitea
|
||||
data:
|
||||
compression: bzip2
|
||||
jobs: 2
|
||||
wal:
|
||||
compression: zstd
|
||||
maxParallel: 2
|
||||
bootstrap:
|
||||
initdb:
|
||||
database: gitea
|
||||
encoding: UTF8
|
||||
localeCType: C
|
||||
localeCollate: C
|
||||
owner: gitea
|
||||
secret:
|
||||
name: postgres-credentials
|
||||
enablePDB: true
|
||||
enableSuperuserAccess: false
|
||||
failoverDelay: 0
|
||||
imageName: ghcr.io/cloudnative-pg/postgresql:18.1-system-trixie
|
||||
instances: 2
|
||||
logLevel: info
|
||||
monitoring:
|
||||
customQueriesConfigMap:
|
||||
- key: queries
|
||||
name: cnpg-default-monitoring
|
||||
disableDefaultQueries: false
|
||||
enablePodMonitor: false
|
||||
postgresql:
|
||||
parameters:
|
||||
max_connections: "200"
|
||||
shared_buffers: 256MB
|
||||
primaryUpdateMethod: restart
|
||||
primaryUpdateStrategy: unsupervised
|
||||
replicationSlots:
|
||||
highAvailability:
|
||||
enabled: true
|
||||
slotPrefix: _cnpg_
|
||||
synchronizeReplicas:
|
||||
enabled: true
|
||||
updateInterval: 30
|
||||
resources:
|
||||
limits:
|
||||
cpu: "2"
|
||||
memory: 2Gi
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
smartShutdownTimeout: 180
|
||||
startDelay: 3600
|
||||
stopDelay: 1800
|
||||
storage:
|
||||
resizeInUseVolumes: true
|
||||
size: 20Gi
|
||||
storageClass: cephrbd-fast-delete
|
||||
switchoverDelay: 3600
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
# pgbouncer in front of the primary. Gitea opens a connection per request and
|
||||
# benefits from pooling under multiple app replicas. Session mode keeps Gitea's
|
||||
# occasional session-scoped state (advisory locks, LISTEN/NOTIFY) working.
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Pooler
|
||||
metadata:
|
||||
name: gitea-postgres-pooler-rw
|
||||
namespace: gitea
|
||||
spec:
|
||||
cluster:
|
||||
name: gitea-postgres
|
||||
instances: 2
|
||||
pgbouncer:
|
||||
parameters:
|
||||
default_pool_size: "50"
|
||||
max_client_conn: "200"
|
||||
paused: false
|
||||
poolMode: session
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: pooler-rw
|
||||
spec:
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- pooler-rw
|
||||
topologyKey: kubernetes.io/hostname
|
||||
containers: []
|
||||
type: rw
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
# HTTPS front for the k8s Gitea. Temporary validation hostname
|
||||
# git2.k8s.syd1.au.unkin.net; the git.unkin.net SAN is added at cutover (see
|
||||
# docs/gitea-migration.md). SSH is exposed separately as an L4 LoadBalancer
|
||||
# (ssh-service.yaml) since Gateway API here terminates HTTP(S) only.
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: gitea
|
||||
namespace: gitea
|
||||
labels:
|
||||
app.kubernetes.io/name: gitea
|
||||
app.kubernetes.io/instance: gitea
|
||||
traefik.io/instance: internal
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: vault-issuer
|
||||
cert-manager.io/common-name: git2.k8s.syd1.au.unkin.net
|
||||
cert-manager.io/private-key-size: "4096"
|
||||
external-dns.alpha.kubernetes.io/hostname: git2.k8s.syd1.au.unkin.net
|
||||
external-dns.alpha.kubernetes.io/target: 198.18.200.4
|
||||
spec:
|
||||
gatewayClassName: traefik-internal
|
||||
listeners:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: HTTP
|
||||
hostname: git2.k8s.syd1.au.unkin.net
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: Same
|
||||
- name: https
|
||||
port: 443
|
||||
protocol: HTTPS
|
||||
hostname: git2.k8s.syd1.au.unkin.net
|
||||
allowedRoutes:
|
||||
namespaces:
|
||||
from: Same
|
||||
tls:
|
||||
mode: Terminate
|
||||
certificateRefs:
|
||||
- group: ""
|
||||
kind: Secret
|
||||
name: gitea-tls
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: gitea-http-redirect
|
||||
namespace: gitea
|
||||
labels:
|
||||
app.kubernetes.io/name: gitea
|
||||
app.kubernetes.io/instance: gitea
|
||||
spec:
|
||||
hostnames:
|
||||
- git2.k8s.syd1.au.unkin.net
|
||||
parentRefs:
|
||||
- group: gateway.networking.k8s.io
|
||||
kind: Gateway
|
||||
name: gitea
|
||||
sectionName: http
|
||||
rules:
|
||||
- filters:
|
||||
- type: RequestRedirect
|
||||
requestRedirect:
|
||||
scheme: https
|
||||
statusCode: 301
|
||||
matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: gitea
|
||||
namespace: gitea
|
||||
labels:
|
||||
app.kubernetes.io/name: gitea
|
||||
app.kubernetes.io/instance: gitea
|
||||
spec:
|
||||
hostnames:
|
||||
- git2.k8s.syd1.au.unkin.net
|
||||
parentRefs:
|
||||
- group: gateway.networking.k8s.io
|
||||
kind: Gateway
|
||||
name: gitea
|
||||
sectionName: https
|
||||
rules:
|
||||
- backendRefs:
|
||||
- group: ""
|
||||
kind: Service
|
||||
name: gitea-http
|
||||
port: 3000
|
||||
weight: 1
|
||||
matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- cnpg_cluster.yaml
|
||||
- cnpg_backup.yaml
|
||||
- cnpg_pooler.yaml
|
||||
- valkey-deployment.yaml
|
||||
- valkey-pvc.yaml
|
||||
- valkey-service.yaml
|
||||
- vaultauth.yaml
|
||||
- vaultstaticsecret.yaml
|
||||
- gateway.yaml
|
||||
- httproute.yaml
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: gitea
|
||||
name: gitea
|
||||
@@ -0,0 +1,89 @@
|
||||
---
|
||||
# Standalone Valkey (Redis-compatible) for Gitea's session store, cache and
|
||||
# queue. The Gitea chart bundles a redis-cluster subchart, but we run our own
|
||||
# standalone Valkey here: it keeps image control in-estate (valkey/valkey,
|
||||
# already allowlisted through the artifactapi dockerhub mirror) and matches the
|
||||
# standalone-cache pattern used by litellm/netbox. One instance serves three
|
||||
# logical DBs: DB 0 = session, DB 1 = cache, DB 2 = queue. AOF persistence is
|
||||
# enabled so queued actions/webhook deliveries survive a restart.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: gitea-valkey
|
||||
namespace: gitea
|
||||
labels:
|
||||
app.kubernetes.io/name: gitea
|
||||
app.kubernetes.io/component: valkey
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: gitea-valkey
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: gitea-valkey
|
||||
app.kubernetes.io/name: gitea
|
||||
app.kubernetes.io/component: valkey
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 999
|
||||
containers:
|
||||
- name: valkey
|
||||
image: valkey/valkey:8-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- valkey-server
|
||||
- --appendonly
|
||||
- "yes"
|
||||
- --save
|
||||
- "60"
|
||||
- "1"
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
name: valkey
|
||||
protocol: TCP
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- valkey-cli
|
||||
- ping
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- valkey-cli
|
||||
- ping
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: data
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: gitea-valkey-data
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: gitea-valkey-data
|
||||
namespace: gitea
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
storageClassName: cephrbd-fast-delete
|
||||
volumeMode: Filesystem
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gitea-valkey
|
||||
namespace: gitea
|
||||
labels:
|
||||
app.kubernetes.io/name: gitea
|
||||
app.kubernetes.io/component: valkey
|
||||
spec:
|
||||
internalTrafficPolicy: Cluster
|
||||
ports:
|
||||
- name: valkey
|
||||
port: 6379
|
||||
protocol: TCP
|
||||
targetPort: valkey
|
||||
selector:
|
||||
app: gitea-valkey
|
||||
sessionAffinity: None
|
||||
type: ClusterIP
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultAuth
|
||||
metadata:
|
||||
name: default
|
||||
namespace: gitea
|
||||
spec:
|
||||
allowedNamespaces:
|
||||
- gitea
|
||||
kubernetes:
|
||||
audiences:
|
||||
- vault
|
||||
role: default
|
||||
serviceAccount: default
|
||||
tokenExpirationSeconds: 600
|
||||
method: kubernetes
|
||||
mount: k8s/au/syd1
|
||||
vaultConnectionRef: vso-system/default
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
# CNPG app-user credentials (keys: username, password). Consumed by the Cluster
|
||||
# bootstrap (initdb.secret) AND by Gitea (gitea.config.database.PASSWD via the
|
||||
# chart's existingSecret wiring). One-time Vault seed — see the PR description.
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: postgres-credentials
|
||||
namespace: gitea
|
||||
spec:
|
||||
destination:
|
||||
create: true
|
||||
name: postgres-credentials
|
||||
overwrite: true
|
||||
hmacSecretData: true
|
||||
mount: kv
|
||||
path: kubernetes/namespace/gitea/default/postgres-credentials
|
||||
refreshAfter: 5m
|
||||
type: kv-v2
|
||||
vaultAuthRef: default
|
||||
---
|
||||
# Initial Gitea admin (keys: username, password, email). Applied by the chart's
|
||||
# init job on first boot (gitea.admin.existingSecret). Local fallback account
|
||||
# that survives the Authentik OIDC cutover. One-time Vault seed.
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: gitea-admin
|
||||
namespace: gitea
|
||||
spec:
|
||||
destination:
|
||||
create: true
|
||||
name: gitea-admin
|
||||
overwrite: true
|
||||
hmacSecretData: true
|
||||
mount: kv
|
||||
path: kubernetes/namespace/gitea/default/gitea-admin
|
||||
refreshAfter: 5m
|
||||
type: kv-v2
|
||||
vaultAuthRef: default
|
||||
---
|
||||
# Gitea internal secrets (keys: SECRET_KEY, INTERNAL_TOKEN). Pinned here rather
|
||||
# than chart-generated so all replicas share identical values AND so the data
|
||||
# cutover can replace them with the VM's app.ini values (SECRET_KEY encrypts
|
||||
# 2FA/mirror/oauth secrets in the DB — it MUST match the restored database).
|
||||
# One-time Vault seed.
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: gitea-inner
|
||||
namespace: gitea
|
||||
spec:
|
||||
destination:
|
||||
create: true
|
||||
name: gitea-inner
|
||||
overwrite: true
|
||||
hmacSecretData: true
|
||||
mount: kv
|
||||
path: kubernetes/namespace/gitea/default/gitea-inner
|
||||
refreshAfter: 5m
|
||||
type: kv-v2
|
||||
vaultAuthRef: default
|
||||
---
|
||||
# Authentik OIDC client secret (key: client_secret). Read by the
|
||||
# terraform-authentik provider runner (policy already grants
|
||||
# kv/.../namespace/+/default/oauth-credentials) AND mounted into Gitea to
|
||||
# register the OIDC login source. One-time Vault seed.
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: oauth-credentials
|
||||
namespace: gitea
|
||||
spec:
|
||||
destination:
|
||||
create: true
|
||||
name: oauth-credentials
|
||||
overwrite: true
|
||||
hmacSecretData: true
|
||||
mount: kv
|
||||
path: kubernetes/namespace/gitea/default/oauth-credentials
|
||||
refreshAfter: 5m
|
||||
type: kv-v2
|
||||
vaultAuthRef: default
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../../base/gitea
|
||||
|
||||
helmCharts:
|
||||
- name: gitea
|
||||
repo: oci://docker.gitea.com/charts
|
||||
version: "12.6.0"
|
||||
releaseName: gitea
|
||||
namespace: gitea
|
||||
valuesFile: values.yaml
|
||||
|
||||
# The chart renders a `helm.sh/hook: test` connection Pod (busybox). We deploy
|
||||
# via kustomize+ArgoCD (not `helm test`), so drop it rather than leave an orphan
|
||||
# Pod pulling an unallowlisted image.
|
||||
patches:
|
||||
- target:
|
||||
version: v1
|
||||
kind: Pod
|
||||
name: gitea-test-connection
|
||||
patch: |-
|
||||
$patch: delete
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: gitea-test-connection
|
||||
@@ -0,0 +1,169 @@
|
||||
# Gitea helm-gitea chart 12.6.0 (appVersion 1.26.1), app pinned to 1.26.2 to
|
||||
# match the VM being replaced. HA-shaped: 2 replicas on shared RWX CephFS, with
|
||||
# Postgres (CNPG), cache/session/queue (Valkey), and OIDC all externalised —
|
||||
# exactly the shape the chart's docs/ha-setup.md requires for replicaCount > 1.
|
||||
replicaCount: 2
|
||||
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: gitea/gitea
|
||||
tag: "1.26.2" # chart appends "-rootless" because rootless: true below
|
||||
rootless: true
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# All bundled stateful subcharts OFF — we run CNPG Postgres + standalone Valkey.
|
||||
postgresql-ha:
|
||||
enabled: false
|
||||
postgresql:
|
||||
enabled: false
|
||||
valkey-cluster:
|
||||
enabled: false
|
||||
valkey:
|
||||
enabled: false
|
||||
|
||||
# Shared repo/LFS/attachment storage. RWX is mandatory for >1 replica so every
|
||||
# pod sees the same /data (repos, lfs, avatars, attachments).
|
||||
persistence:
|
||||
enabled: true
|
||||
create: true
|
||||
mount: true
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
storageClass: cephfs-raid6-delete
|
||||
size: 20Gi
|
||||
|
||||
service:
|
||||
http:
|
||||
type: ClusterIP
|
||||
port: 3000
|
||||
# git-over-ssh. Each replica runs Gitea's built-in Go SSH server (rootless,
|
||||
# listens 2222); the LoadBalancer fans connections across pods. Dedicated
|
||||
# PureLB VIP + its own DNS name for the validation phase (see the migration
|
||||
# doc for the git.unkin.net:2222 unification decision at cutover).
|
||||
ssh:
|
||||
type: LoadBalancer
|
||||
port: 2222
|
||||
loadBalancerIP: 198.18.200.10
|
||||
externalTrafficPolicy: Local
|
||||
annotations:
|
||||
purelb.io/addresses: 198.18.200.10
|
||||
purelb.io/service-group: common
|
||||
external-dns.alpha.kubernetes.io/hostname: git2-ssh.k8s.syd1.au.unkin.net
|
||||
external-dns.alpha.kubernetes.io/target: 198.18.200.10
|
||||
|
||||
# Gateway API (HTTPRoute in the base) fronts HTTP; the chart Ingress is unused.
|
||||
ingress:
|
||||
enabled: false
|
||||
|
||||
# Rolling replicas on slow shared storage: keep one old pod up and give new pods
|
||||
# generous startup headroom so migrations on boot don't trip the probes.
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: "100%"
|
||||
maxUnavailable: 0
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: "500m"
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: "2"
|
||||
memory: 2Gi
|
||||
|
||||
gitea:
|
||||
# Local admin fallback (survives the OIDC cutover). Secret keys: username,
|
||||
# password. Seeded in Vault -> synced to the gitea-admin Secret by VSO.
|
||||
admin:
|
||||
existingSecret: gitea-admin
|
||||
email: "benvin@unkin.net"
|
||||
passwordMode: keepUpdated
|
||||
|
||||
# DB password (and Gitea internal secrets) injected as env from VSO Secrets,
|
||||
# never rendered into app.ini in git. GITEA__<section>__<KEY> maps to app.ini.
|
||||
additionalConfigFromEnvs:
|
||||
- name: GITEA__database__PASSWD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-credentials
|
||||
key: password
|
||||
- name: GITEA__security__SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-inner
|
||||
key: SECRET_KEY
|
||||
- name: GITEA__security__INTERNAL_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-inner
|
||||
key: INTERNAL_TOKEN
|
||||
|
||||
# Authentik OIDC login source, registered declaratively on boot. existingSecret
|
||||
# must carry keys `key` (client id) and `secret` (client secret) — seeded at the
|
||||
# same Vault path terraform-authentik reads client_secret from.
|
||||
oauth:
|
||||
- name: "authentik"
|
||||
provider: "openidConnect"
|
||||
existingSecret: oauth-credentials
|
||||
autoDiscoverUrl: "https://identity.k8s.syd1.au.unkin.net/application/o/gitea/.well-known/openid-configuration"
|
||||
|
||||
config:
|
||||
server:
|
||||
DOMAIN: git2.k8s.syd1.au.unkin.net
|
||||
ROOT_URL: https://git2.k8s.syd1.au.unkin.net/
|
||||
SSH_DOMAIN: git2-ssh.k8s.syd1.au.unkin.net
|
||||
SSH_PORT: 2222 # advertised in clone URLs
|
||||
SSH_LISTEN_PORT: 2222 # rootless in-container listener
|
||||
START_SSH_SERVER: true
|
||||
LFS_START_SERVER: true
|
||||
|
||||
database:
|
||||
DB_TYPE: postgres
|
||||
HOST: gitea-postgres-pooler-rw:5432
|
||||
NAME: gitea
|
||||
USER: gitea
|
||||
SSL_MODE: disable
|
||||
|
||||
# Standalone Valkey: session on db 0, cache on db 1, queue on db 2.
|
||||
session:
|
||||
PROVIDER: redis
|
||||
PROVIDER_CONFIG: "redis://gitea-valkey:6379/0"
|
||||
cache:
|
||||
ENABLED: true
|
||||
ADAPTER: redis
|
||||
HOST: "redis://gitea-valkey:6379/1"
|
||||
queue:
|
||||
TYPE: redis
|
||||
CONN_STR: "redis://gitea-valkey:6379/2"
|
||||
|
||||
# DB-backed issue indexer is replica-safe on shared storage (matches the VM);
|
||||
# avoids the on-disk bleve indexer that HA can't share.
|
||||
indexer:
|
||||
ISSUE_INDEXER_TYPE: db
|
||||
REPO_INDEXER_ENABLED: false
|
||||
|
||||
# CI stays on Woodpecker — Gitea Actions disabled.
|
||||
actions:
|
||||
ENABLED: false
|
||||
|
||||
repository:
|
||||
DEFAULT_BRANCH: main
|
||||
DEFAULT_PRIVATE: last
|
||||
|
||||
# OIDC auto-registration + account linking so existing local users (benvin,
|
||||
# bots) link to their Authentik identity by matching username on first login.
|
||||
service:
|
||||
ENABLE_AUTO_REGISTRATION: true
|
||||
oauth2_client:
|
||||
ENABLE_AUTO_REGISTRATION: true
|
||||
ACCOUNT_LINKING: auto
|
||||
USERNAME: preferred_username
|
||||
UPDATE_AVATAR: true
|
||||
|
||||
# Startup headroom for migrations on RWX storage across a rolling update.
|
||||
startupProbe:
|
||||
enabled: true
|
||||
livenessProbe:
|
||||
enabled: true
|
||||
readinessProbe:
|
||||
enabled: true
|
||||
Reference in New Issue
Block a user