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
+72
View File
@@ -0,0 +1,72 @@
---
# Standalone Redis via the ot-container-kit redis-operator that's already
# deployed as infra (argocd-apps/infrastructure/redis-operator.yaml) but
# currently unused - GitLab's Redis is a hand-rolled StatefulSet instead
# (apps/gitlab/manifests/redis-cluster.yaml), not this operator. This is the
# first real consumer of it in the repo.
#
# NOTE: verify this CR against `kubectl explain redis.spec` (or the chart's
# CRD source) for the redis-operator 0.15.0 actually deployed before first
# apply - the ot-container-kit CRD schema has shifted across versions and
# this wasn't checked against a live cluster.
apiVersion: generators.external-secrets.io/v1alpha1
kind: Password
metadata:
name: nextcloud-redis-password
namespace: nextcloud
spec:
length: 32
digits: 5
symbols: 0
noUpper: false
allowRepeat: true
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: nextcloud-redis-password
namespace: nextcloud
spec:
refreshInterval: "0" # generate once, don't rotate (Redis CR reads this at pod start only)
target:
name: redis-nextcloud-secret
creationPolicy: Owner
template:
data:
password: "{{ .password }}"
dataFrom:
- sourceRef:
generatorRef:
apiVersion: generators.external-secrets.io/v1alpha1
kind: Password
name: nextcloud-redis-password
---
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: Redis
metadata:
name: redis-nextcloud
namespace: nextcloud
spec:
kubernetesConfig:
image: quay.io/opstree/redis:v7.0.12
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 25m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
redisExporter:
enabled: false
redisSecret:
name: redis-nextcloud-secret
key: password
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: rook-ceph-block
resources:
requests:
storage: 2Gi