Config and secrets

config 'config/punk.yml';

Loads YAML configuration and applies it where the keyword sits - put it first, and the routes after it can rely on what it registered.

Blocks that register for real

A block that mirrors a DSL keyword is applied as that keyword, so deployment configuration needs no code change:

views:                       # -> views Stencil => {...}  Stencil    template_dir: root/templates    wrapper: layout.tmpl
database:                    # -> database dsn => ...  dsn:      dbi:Pg:dbname=myapp  password: { $env: DB_PASSWORD
models: [ Book ]             # -> model 'Book'
plugins:                     # -> plugin 'RequestId' => {...}  RequestId
static:                      # -> static '/static' => 'root/static'  /static: root/static

Everything else in the file is yours, through $app->config.

Layers

Three files, each overriding the last:

  1. punk.yml - the base
  2. punk.$PUNK_ENV.yml - per environment (punk.production.yml)
  3. punk.local.yml - gitignored, per machine
config 'config/punk.yml', env => 'production';

Secrets

Secrets never belong in the file. A value written as a reference is resolved at boot from outside it:

database  password: { $env: DB_PASSWORD }      # from the environmentsession  secret: { $file: /run/secrets/key }  # from a fileapi  token: { $exec: [vault, read, t] }   # from a command

$app->config shows [redacted] in their place; the real value is reachable only by dotted path:

my $password = secret 'database.password';

A plaintext value under a secret-shaped key (password, secret, token, ...) warns by default; strict mode refuses to start:

config 'config/punk.yml', secrets => 'strict';

Checking before production does

punk config check

resolves the whole configuration and every secret, and says what failed and why - at deploy time, not at 3am.

From Perl only

An application that declares everything in Perl never touches YAML - YAML::XS is loaded only when the config keyword is used.