feat(secrets): retire .env - SOPS vault is the single source of truth (P4) #38

Merged
jfraeys merged 2 commits from jfraeys/feat/p4-dotenv-into-vault into main 2026-10-10 10:17:07 -04:00
Owner

P4 reframed: .env is retired, the SOPS vault is the single source of truth (all 69 keys moved; secrets and shared config alike; per-machine values like ANSIBLE_PRIVATE_KEY_FILE are exported in the shell).

  • Vault: +67 keys from .env, no existing key changed, 2 recipients kept, all values encrypted. OVH_OBJECT_STORAGE_ACCESS_KEY_ID/SECRET differed between .env and the vault (drift); the vault copy was kept, as it already won everywhere.
  • Readers: setup, deploy-services.sh, backup-terraform.sh, rotate-ovh-s3-credentials.sh, recover-secondary-repo.sh now read the vault. common_vault_load_env exports OS_/OVH_/DOMAIN/DESEC_/ZEDMAIL_/AUTHELIA_SMTP_SENDER|IDENTIFIER too.
  • Writers: the OVH and Cloudflare wizards write through scripts/vault-set.py (stdin, atomic, round-trip verified); shared scripts/lib/sopsvault.py also backs provision-ci-state-key.py. Scripts re-run under .venv when the default python3 has no PyYAML.
  • Verified: with .env moved aside, ./setup --workspace linode-staging -- plan succeeds (3 to add); effective env identical for 67/69 keys.

Not verified: a full staging deploy, and the wizards end to end (interactive, they write real credentials). recover-secondary-repo.sh still refuses to run under SOPS (separate, pre-existing).

Merge note: after merging, delete the local .env (it holds plaintext secrets and is no longer read).

🤖 Generated with Claude Code

P4 reframed: `.env` is retired, the SOPS vault is the single source of truth (all 69 keys moved; secrets and shared config alike; per-machine values like ANSIBLE_PRIVATE_KEY_FILE are exported in the shell). - Vault: +67 keys from .env, no existing key changed, 2 recipients kept, all values encrypted. OVH_OBJECT_STORAGE_ACCESS_KEY_ID/SECRET differed between .env and the vault (drift); the vault copy was kept, as it already won everywhere. - Readers: setup, deploy-services.sh, backup-terraform.sh, rotate-ovh-s3-credentials.sh, recover-secondary-repo.sh now read the vault. common_vault_load_env exports OS_/OVH_/DOMAIN/DESEC_/ZEDMAIL_/AUTHELIA_SMTP_SENDER|IDENTIFIER too. - Writers: the OVH and Cloudflare wizards write through scripts/vault-set.py (stdin, atomic, round-trip verified); shared scripts/lib/sopsvault.py also backs provision-ci-state-key.py. Scripts re-run under .venv when the default python3 has no PyYAML. - Verified: with .env moved aside, `./setup --workspace linode-staging -- plan` succeeds (3 to add); effective env identical for 67/69 keys. Not verified: a full staging deploy, and the wizards end to end (interactive, they write real credentials). recover-secondary-repo.sh still refuses to run under SOPS (separate, pre-existing). Merge note: after merging, delete the local .env (it holds plaintext secrets and is no longer read). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Adds scripts/migrate-dotenv-to-vault.py and applies it: 67 .env keys moved
into secrets/vault.sops.yml under their existing names (the roles already
read VAR with the env as fallback, so vault values need no role changes).
OVH_OBJECT_STORAGE_ACCESS_KEY_ID/SECRET_ACCESS_KEY differed between .env and
the vault; the vault copy was kept (it already wins everywhere). .env still
exists and is still read; removing it is the next change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
feat(secrets): retire .env - the SOPS vault is the single source of truth
All checks were successful
Lint / lint (pull_request) Successful in 1m56s
8c4c5813b7
setup, deploy-services.sh, backup-terraform.sh, rotate-ovh-s3-credentials.sh
and recover-secondary-repo.sh no longer read .env; they use the vault.
common_vault_load_env now also exports the OS_/OVH_/DOMAIN/DESEC_/ZEDMAIL_/
AUTHELIA_SMTP_SENDER|IDENTIFIER names Terraform and config.sh read from the
environment. The OVH and Cloudflare setup wizards read/write the vault through
the new scripts/vault-set.py (stdin, atomic, verified) instead of .env.
provision-ci-state-key.py shares scripts/lib/sopsvault.py. The spent
migration script is removed. Docs and .env.example (now a name catalog) updated.

Verified: effective environment identical for 67/69 keys with .env gone (the
other two are the stale OVH_OBJECT_STORAGE_* values, vault wins as before), and
`./setup --workspace linode-staging -- plan` succeeds with .env moved aside.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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!38
No description provided.