From 61abb3764eba1e70111f588cb460eb232d9740b7 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 9 Oct 2026 19:55:29 +0000 Subject: [PATCH] Document repository privacy and secret rotation after a key leak docs/security.md now explains why the repository must be private (the mailbox list; ciphertexts living in git history forever) and that after a key leak the secrets themselves must be rotated, with the steps. just init reminds to keep the repository private. Closes #18 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01G22o7QQ17GRtkCqpJNFr9B --- docs/security.md | 25 +++++++++++++++++++++++-- scripts/init.sh | 3 +++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/security.md b/docs/security.md index e0ab859..32a4f62 100644 --- a/docs/security.md +++ b/docs/security.md @@ -95,8 +95,29 @@ misdirected message. plaintext on purpose: they are needed to generate DNS records and `known_hosts`. -If your age key leaks, generate a new one, update `.sops.yaml`, run -`sops updatekeys secrets/*`, and rotate the mailbox passwords and DKIM keys. +### Keep the repository private + +- `settings.nix` lists every mailbox, alias and forward. In a public + repository that is a ready-made target list for spam, phishing and + password guessing. Host this repository privately. +- The secrets are encrypted, but only as strong as the age keys, forever: + every old ciphertext stays in git history. Publishing the repository (or + having it leak) means relying on those keys never leaking later. + +### After a key leaks, rotate the secrets, not just the keys + +Removing a recipient from `.sops.yaml` and running `sops updatekeys` only +protects *future* commits; earlier commits stay decryptable with the old +key. If your age key or the server's host key leaks: + +1. Generate a new key and replace it in `.sops.yaml`; for the server key, + also replace `secrets/ssh_host_ed25519_key*` (as `scripts/init.sh` does) + and reinstall. +2. `sops updatekeys secrets/*`. +3. Rotate every secret: mailbox passwords (`just passwd`), DKIM keys + (`just add-domain ` with a new selector, deploy, then delete the + old selector), relay and backup credentials, the Terraform state + passphrase, and any provider API tokens stored in the secrets. ## Not covered diff --git a/scripts/init.sh b/scripts/init.sh index 1d4653c..6e4a00c 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -64,6 +64,9 @@ done cat < 2. Commit .sops.yaml, secrets/ and dkim/ (everything there is encrypted or public).