Add VPS warm-standby/backup site (Phase 0-1b)

Foundation for a DR/backup path using an always-on VPS as a second
ArgoCD-managed cluster, plus DB/backup standardization work that fell
out of it:

- vps-standby ArgoCD cluster destination + AppProject, MinIO backup
  receiver, VPS bootstrap script (k3s, Netbird, cert-manager)
- Dual-site DNS failover watcher + home-IP DDNS CronJob, Cloudflare
  token moved out of git into Vault+ExternalSecret
- Nextcloud migrated from ad-hoc MariaDB to CNPG + redis-operator
  (matches n8n/Authentik/GitLab's backup-native pattern)
- Authentik's CNPG manifests moved into the actual ArgoCD-synced
  manifests/ path (were present but never wired into the sync path)
- Vault raft-snapshot CronJob, CNPG barmanObjectStore backups
  (Authentik/n8n/Nextcloud), Nextcloud file-PVC restic sync - all
  targeting the new VPS MinIO receiver

See VPS Warm-Standby plan doc for full design rationale.
This commit is contained in:
Scooby Husky
2026-08-17 14:59:26 -05:00
parent 5163403e24
commit 7990f1fa47
25 changed files with 1161 additions and 139 deletions
@@ -0,0 +1,71 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-authentik
namespace: authentik
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:16
instances: 2
# Resource limits to prevent OOM
resources:
requests:
memory: "512Mi"
cpu: "25m"
limits:
memory: "2Gi"
cpu: "250m"
# Spread replicas across different nodes
affinity:
topologyKey: kubernetes.io/hostname
storage:
size: 5Gi
storageClass: rook-ceph-block
primaryUpdateStrategy: unsupervised
# PostgreSQL configuration for better performance
postgresql:
parameters:
max_connections: "200"
shared_buffers: "512MB"
effective_cache_size: "1536MB"
maintenance_work_mem: "128MB"
checkpoint_completion_target: "0.9"
wal_buffers: "16MB"
default_statistics_target: "100"
random_page_cost: "1.1"
effective_io_concurrency: "200"
work_mem: "2621kB"
min_wal_size: "1GB"
max_wal_size: "4GB"
bootstrap:
initdb:
database: app
owner: app
# Backup to the VPS MinIO backup receiver (Phase 1b). VPS_MINIO_ENDPOINT
# placeholder matches infrastructure/vault/manifests/raft-snapshot-cronjob.yaml -
# replace with the VPS's actual Netbird address once bootstrapped.
backup:
barmanObjectStore:
destinationPath: s3://cnpg-backups/pg-authentik
endpointURL: http://vps-minio.netbird.internal:30900
s3Credentials:
accessKeyId:
name: vps-minio-secret
key: accesskey
secretAccessKey:
name: vps-minio-secret
key: secretkey
wal:
compression: gzip
maxParallel: 2
retentionPolicy: "30d"
monitoring:
enablePodMonitor: true
@@ -0,0 +1,16 @@
---
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: cnpg-postgres
namespace: authentik
labels:
release: prometheus
spec:
selector:
matchLabels:
cnpg.io/cluster: pg-authentik
podMetricsEndpoints:
- port: metrics
path: /metrics
interval: 30s
@@ -0,0 +1,39 @@
---
apiVersion: generators.external-secrets.io/v1alpha1
kind: Password
metadata:
name: authentik-cnpg-secret
namespace: authentik
spec:
length: 42
digits: 5
symbols: 5
symbolCharacters: "-_$@"
noUpper: false
allowRepeat: true
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: authentik-cnpg-secret
namespace: authentik
spec:
# how often to rotate the DB password
refreshInterval: "24h"
target:
# This will merge the generated password into the existing pg-authentik-app secret
name: pg-authentik-app
creationPolicy: Merge
template:
metadata:
labels:
cnpg.io/reload: "true"
data:
# Override the password field with our ESO-generated password
password: "{{ .password }}"
dataFrom:
- sourceRef:
generatorRef:
apiVersion: generators.external-secrets.io/v1alpha1
kind: Password
name: authentik-cnpg-secret
@@ -0,0 +1,26 @@
---
# VPS MinIO credentials for CNPG's barmanObjectStore backup target.
# Same Vault source as infrastructure/vault/manifests/raft-snapshot-cronjob.yaml
# (secret/vps-minio-credentials) - populated once, manually, after VPS bootstrap.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: vps-minio-credentials
namespace: authentik
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: vault-backend
target:
name: vps-minio-secret
creationPolicy: Owner
data:
- secretKey: accesskey
remoteRef:
key: vps-minio-credentials
property: access-key
- secretKey: secretkey
remoteRef:
key: vps-minio-credentials
property: secret-key