Phase: CI — State Backup CronJob
Goal: Both Terraform state secrets backed up daily to MinIO. Documented restore procedure. Safety net before CI pipeline goes live.
Owner: Dev agent
Repo:
forgejo_admin/pal-e-platformDepends on: None — independently executable
Why
DORA impact: Directly improves MTTR. If state is corrupted or lost during a bad apply, recovery without backups means manual state reconstruction — hours of work. With daily backups to MinIO, recovery is a restore command. This is the safety net that makes Phase 6.4 (apply-on-merge) safe to deploy.
Scope
1. MinIO bucket + IAM. Create
tf-state-backups bucket via Terraform. Create MinIO IAM user tf-backup with policy scoped to the bucket. Deploy credentials as a k8s Secret in tofu-state namespace.2. CronJob. Kubernetes CronJob in
tofu-state namespace that:- Runs daily at 02:00 UTC
- Reads
tfstate-default-pal-e-platformandtfstate-default-pal-e-servicessecrets - Base64-decodes the
tfstatekey from each - Uploads to
s3://tf-state-backups/{repo}-{date}.jsonvia MinIO (using mc or curl) - Retains last 30 days (delete older backups in the same script)
3. Deploy via Terraform. All resources (bucket, IAM, Secret, CronJob) defined in
terraform/main.tf.Deliverables
- PR #39 merged (2026-03-14) —
Closes #36 - 9 TF resources: MinIO bucket
tf-state-backups, IAM usertf-backup+ policy + attachment, k8s Secret, ServiceAccount, Role + RoleBinding (scoped to 2 state secrets), CronJob - CronJob: daily 02:00 UTC, reads state secrets, base64-decodes, uploads to MinIO, prunes >30 days
- RBAC:
resource_namesconstraint limits access to onlytfstate-default-pal-e-platformandtfstate-default-pal-e-services - QA nits: runtime mc download (external dep), bitnami/kubectl:1.31 pin needs tracking, no force_destroy on bucket (consistent with existing patterns)
Related
phase-pal-e-platform-ci-hardening— parent phase (CI Pipeline & Team Hardening)plan-pal-e-platform— grandparent plan (Platform Hardening)