Local generated secrets
Let fed create development passwords, signing keys, and other values that should be stable on one checkout without being committed to Git.
Generate a secret
Declare a type: secret parameter. With no source and no
generate command, fed creates a cryptographically random 32-character
alphanumeric value:
parameters:
DB_PASSWORD:
type: secret
services:
database:
image: postgres:16
environment:
POSTGRES_PASSWORD: '{{DB_PASSWORD}}'
The first fed start that needs the value generates it. In an interactive
terminal, fed shows the names it will generate and asks for confirmation. In CI and other
non-interactive contexts it proceeds without prompting.
Where values are stored
Generated values are written to .fed/secrets.generated.env and reused on
later starts. Fed creates .fed/ when needed and manages
.fed/.gitignore so the generated file is ignored by Git. Secret files are written
atomically with mode 0600.
A value already present in the generated file is not replaced merely because fed starts
again. To intentionally create a new value, remove that variable's line and run
fed start.
.fed/secrets.generated.env. If
.fed/.gitignore is changed so the file is commit-eligible, fed refuses to
write generated secrets there.Custom generation
Use generate when a value needs a particular format. The command runs through
sh -c; its trimmed stdout becomes the value. Stderr is hidden on success and
included in the error if the command fails. When the command interpolates
{{...}} values, the resolved command and its stderr are
suppressed so a failure can't leak another secret.
parameters:
SESSION_SECRET:
type: secret
generate: "openssl rand -hex 32"
Because this parameter is also type: secret, the command runs only when a
value needs to be created. Its result is persisted. By contrast, a parameter with
generate but without type: secret is a computed parameter: fed
reruns it on every start and does not persist it.
Derived secrets
References in a generator create dependencies. Fed orders the commands and rejects dependency cycles:
parameters:
SIGNING_PRIVATE_KEY:
type: secret
generate: "openssl genpkey -algorithm ED25519"
SIGNING_PUBLIC_KEY:
type: secret
generate: "printf '%s' '{{SIGNING_PRIVATE_KEY}}' | openssl pkey -pubout"
If fed creates a missing input secret, it also regenerates persisted secrets that depend on that input during the same run. This prevents a derived public key, certificate, or token from getting out of sync with newly generated source material.
Local overrides
The generated secrets file is loaded before files in env_file, so a normal
environment file can override a generated value for one machine:
env_file:
- .env
- .env.local
If one of those files already supplies the secret, fed uses that value instead of generating a new one. Keep every file containing secrets out of Git.
Generated or manual?
Use generated secrets for values whose actual contents do not matter and which fed can safely create: local database passwords, session secrets, encryption keys, and test signing keys.
Use source: manual when the value comes from an external system, such as an
API key or OAuth client secret:
parameters:
STRIPE_SECRET_KEY:
type: secret
source: manual
description: "From https://dashboard.stripe.com/apikeys"
Fed never generates a manual secret. Supply it through an env_file, or use
Team secrets to share development credentials through
Service Federation Cloud.
Constraints
Secret parameters cannot declare default or either
constraints. Put secret material outside the committed config.