Guide 7 of 12

Configuration and credentials

Two sources, in order: an encrypted credentials file if one exists, then environment variables, which always win. No globals, no init(): config.Load() returns a struct once, at startup, and every field is validated then, so a missing setting is a refusal to boot rather than a nil a request trips over an hour later.

The environment variables

Named after the app: a service called blog reads BLOG_*.

VariableWhat it selects
<NAME>_ENVA closed set: development, test or production. Selects behaviour.
<NAME>_CREDENTIALSAny name; selects which credentials file to read. Defaults to <NAME>_ENV.
<NAME>_MASTER_KEYThe decryption key, handed in by a deployment so no key file has to exist in the image.
<NAME>_ADDRThe listen address, default :8080.
<NAME>_DATABASE_URLThe database. Development and test default to the compose stack on :5440; production has no default and must be given.
<NAME>_LOG_LEVELdebug, info, warn or error.
<NAME>_MIGRATE_AT_BOOTtrue by default; set to false only for a deployment that migrates from one place on purpose.

(There is also <NAME>_SHUTDOWN_GRACE, how long the server waits for in-flight requests on SIGTERM, and <NAME>_CONFIG_DIR for running the binary from somewhere other than the app root. Both have sensible defaults.)

<NAME>_ENV and <NAME>_CREDENTIALS are deliberately separate. <NAME>_ENV is a closed set with no "staging" member on purpose, because every behavioural switch in the app reads it, and a typo there should fail loudly rather than fall through to production behaviour silently. A staging deployment is:

BLOG_ENV=production BLOG_CREDENTIALS=staging

production strictness, staging secrets, which is what "staging" means here: not a third environment, but production behaviour reading a different credentials file.

The credentials files

The Rails pattern: committed ciphertext, a key that is never committed.

config/credentials.yml.enc            + config/master.key              development
config/credentials/staging.yml.enc    + config/credentials/staging.key
config/credentials/production.yml.enc + config/credentials/production.key

Each file is flat, one section named after the app, whose keys give the environment-variable names: blog.addr is overridden by BLOG_ADDR, so a value can move between the file and the environment without renaming anything.

bogie credentials:edit
bogie credentials:edit -e production
make credentials ENV=staging

bogie credentials:edit opens development's file with its key; -e production (or make credentials ENV=production) opens that environment's own file, making it and its key the first time. A key opens only the file it was made for: development's key can never read production's file.

Test never reads a credentials file. It runs from defaults and the environment only, so tests need nobody's secrets and can never accidentally open the development database.

In a container

The encrypted files travel in the image; the keys never do. At runtime the key for whichever credentials file is selected arrives as <NAME>_MASTER_KEY, read directly with no file to write and no permissions to get wrong. See Deploying for where that value comes from.