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
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# rotate-cloudflare-token.sh - Rotate the Cloudflare DNS-01 token out of git and into Vault
#
# infrastructure/cert-manager/manifests/secret-cf-token.yaml used to contain a live
# Cloudflare API token committed in plaintext. It's now an ExternalSecret pulling
# from Vault at secret/cloudflare-dns-token#token - this script populates that path.
#
# This does NOT create or revoke the Cloudflare token itself - that's a manual step
# in the Cloudflare dashboard, deliberately not automated here since it's a live,
# outward-facing credential change:
#
# 1. Cloudflare dashboard -> My Profile -> API Tokens -> Create Token
# Scope: Zone:DNS:Edit, restricted to the kube.huskypup.net zone only
# 2. Run this script with the new token
# 3. Confirm cert-manager can still issue certs (kubectl get certificaterequests -A)
# 4. THEN go back to Cloudflare and revoke the old token
# (the one that was committed in git - assume it's compromised)
#
# Usage:
# ./scripts/rotate-cloudflare-token.sh <new-cloudflare-token>
#
# Prerequisites:
# - Vault initialized and unsealed
# - kubectl configured for the home cluster
set -euo pipefail
NEW_TOKEN="${1:?Usage: $0 <new-cloudflare-token>}"
echo "=== Cloudflare DNS-01 Token Rotation ==="
echo "Storing new token in Vault at secret/cloudflare-dns-token..."
ROOT_TOKEN=$(kubectl -n vault get secret vault-init-keys -o jsonpath='{.data.VAULT_ROOT_TOKEN}' | base64 -d)
kubectl exec -n vault vault-0 -- env "VAULT_TOKEN=${ROOT_TOKEN}" \
vault kv put secret/cloudflare-dns-token token="${NEW_TOKEN}"
echo "Forcing ExternalSecret refresh..."
kubectl -n cert-manager annotate externalsecret cloudflare-token-secret \
force-sync="$(date +%s)" --overwrite
echo ""
echo "=== Done ==="
echo "Next:"
echo " 1. Verify: kubectl -n cert-manager get secret cloudflare-token-secret -o jsonpath='{.data.cloudflare-token}' | base64 -d"
echo " 2. Verify a cert still renews cleanly (or delete one Certificate to force a test issuance)"
echo " 3. Revoke the OLD token in the Cloudflare dashboard once confirmed working"