feat(backups): include the Terraform state in every backup run (#220 step 3) #222

Merged
jfraeys merged 1 commit from jfraeys/feat/state-snapshot-backup into main 2026-10-16 12:01:52 -04:00
Owner

The state object had no backup of its own (#220). infra-state-snapshot.sh lists the backend bucket, downloads each workspace's state (env://infra/terraform.tfstate) with curl --aws-sigv4 into /var/lib/infra-backups/terraform-state/.tfstate (0600), validates it as JSON, and the existing restic run then carries it to the primary and the secondary repo. Failure marks the dumps component failed, so the backup reports DEGRADED.

Checked: a run against the real bucket into a temp dir (6 workspaces, files 0600, deleted afterwards); a raw ':' in the key fails the signature (403) while %3A works, and the script and its test encode it; test-state-snapshot.sh (8 cases with a fake curl, added to lint.yml); the env template renders correctly with the flag on, off and with an empty bucket; ansible syntax check of services.yml.

Not checked: the script on the real services host (needs a deploy), and the new curl version there (Debian 12 ships 7.88, which supports --aws-sigv4).
Enabled for production services only via backups_state_snapshot_enabled in inventory/host_vars/services.yml; staging and DR hosts skip it. Roles change: staging, promotion, then ./infra deploy --tags backups --limit services (not on the new OVH node before cutover).

Part of #220.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ

The state object had no backup of its own (#220). infra-state-snapshot.sh lists the backend bucket, downloads each workspace's state (env:/<ws>/infra/terraform.tfstate) with curl --aws-sigv4 into /var/lib/infra-backups/terraform-state/<ws>.tfstate (0600), validates it as JSON, and the existing restic run then carries it to the primary and the secondary repo. Failure marks the dumps component failed, so the backup reports DEGRADED. Checked: a run against the real bucket into a temp dir (6 workspaces, files 0600, deleted afterwards); a raw ':' in the key fails the signature (403) while %3A works, and the script and its test encode it; test-state-snapshot.sh (8 cases with a fake curl, added to lint.yml); the env template renders correctly with the flag on, off and with an empty bucket; ansible syntax check of services.yml. Not checked: the script on the real services host (needs a deploy), and the new curl version there (Debian 12 ships 7.88, which supports --aws-sigv4). Enabled for production services only via backups_state_snapshot_enabled in inventory/host_vars/services.yml; staging and DR hosts skip it. Roles change: staging, promotion, then ./infra deploy --tags backups --limit services (not on the new OVH node before cutover). Part of #220. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
feat(backups): copy the Terraform state objects into the backup run (#220 step 3)
All checks were successful
Lint / lint (pull_request) Successful in 1m55s
Secret scan / scan (pull_request) Successful in 15s
6431fe30ef
infra-state-snapshot.sh fetches every workspace's state from the backend bucket
(curl --aws-sigv4, ':' sent as %3A; verified against the real bucket) into
/var/lib/infra-backups/terraform-state, so restic carries it to both repos. A
failure degrades the dumps component. Enabled for production services only
(backups_state_snapshot_enabled in host_vars/services.yml).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jfraeys/infra!222
No description provided.