Skip to main content

Secrets done right

Beginner ⏱ 8 min secrets · config · production

You will build: an app whose config contains zero credentials — and a deploy that fails loudly if a secret is missing, instead of shipping a broken pipeline.

${secret:NAME} → resolved at deploy

Prerequisites​

  • Any app with a sink or credentialed connector.

1 · Store a secret locally​

pulse secret set ALERT_WEBHOOK https://hooks.example.com/T000/B000/xxxx

Stored in the CLI's local secret store (file mode 0600). List and remove with pulse secret list · pulse secret rm NAME.

2 · Reference it — never paste it​

sink:
kind: webhook
url: ${secret:ALERT_WEBHOOK}

Two reference forms exist: ${secret:NAME} (CLI secret store) and ${env:VAR} (environment variable). The scaffolder already emits these for credential fields — follow its lead.

3 · See the guard in action​

pulse secret rm ALERT_WEBHOOK
pulse deploy .

Deploy aborts with a named error: the reference ${secret:ALERT_WEBHOOK} cannot be resolved. A config with a hole in it never reaches the runtime.

4 · Restore and deploy clean​

pulse secret set ALERT_WEBHOOK https://hooks.example.com/T000/B000/xxxx
pulse deploy .

What just happened​

Secrets are resolved at deploy time, from outside the file. The YAML you commit to git carries references, never values — so the same file is safe in a PR, and the same app deploys against dev or prod credentials by changing what the references resolve to, not the file itself.

Troubleshooting​

Where does the secret store live?

pulse secret path shows you. It's a local file with owner-only permissions (0600) — per developer, per machine.

Next​