feat(template): optional fnox-encrypted production secrets - #2114
Open
davidpoblador wants to merge 1 commit into
Open
feat(template): optional fnox-encrypted production secrets#2114davidpoblador wants to merge 1 commit into
davidpoblador wants to merge 1 commit into
Conversation
Answering `age_recipient` scaffolds a fnox.toml and a compose.secrets.yml
overlay, and points deploy-latest at `fnox exec`, so production secrets are
age-encrypted in a committable file and decrypted only at deploy. Leaving
it blank keeps the existing plaintext .env flow.
Secrets go in the overlay rather than compose.prod.yml because CI builds
with `docker buildx bake -f compose.prod.yml`, which interpolates the whole
file and not only its build sections — a ${VAR:?} guard there fails every
build, since a runner has no secrets. This was found the hard way in a
downstream project whose release was tagged but never built.
The deploy also passes --env-file /dev/null, so Compose cannot quietly
interpolate a local .env and a deploy outside fnox exec fails loudly rather
than starting with blank credentials.
compose.prod.yml and cicd.justfile become .j2 so they can vary on the
answer; the one `{{ HOST }}` in the recipe is escaped as just syntax.
Verified by generating both variants: with a recipient, bake succeeds with
no secrets, the deploy renders, and an unset secret fails loudly; without
one, the .env flow is byte-identical to before.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QnxqibhS4XvDJF3abxcdPT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Carries back what a downstream project (
alltuner/radio) hit while migrating its secrets, so the next project generated from this template does not repeat it.What
A new
age_recipientanswer. Provide one and the project scaffolds:fnox.toml— age-encrypted secrets, safe to commitcompose.secrets.yml— deploy-only overlay declaring the secret environmentdeploy-latestrunning underfnox execLeave it blank and the existing plaintext
.envflow is generated unchanged.The trap this encodes
Secrets go in the overlay, not
compose.prod.yml, because CI builds with:Bake interpolates the entire file, not only its
build:sections. A${VAR:?}guard there fails every CI build, since a runner has no secrets. Downstream this tagged a release that was then never built, and it is invisible locally because the bake step only runs on release.The deploy also passes
--env-file /dev/null, so Compose cannot quietly interpolate a local.env. Without that the guards are satisfied by whatever file happens to be lying around, and a deploy outsidefnox execsilently uses stale values instead of failing.Mechanics
compose.prod.ymland.justfiles/cicd.justfilebecome.j2so they can vary on the answer. The single{{ HOST }}in the recipe is escaped, since that is just syntax rather than copier's.Verified
Generated a project both ways:
age_recipientfnox.toml,compose.secrets.ymlenv_fileincompose.prod.ymlbakewith no secretsNo stray Jinja in either output.