dibbla secrets
Create, read, and delete secrets — globally for the whole org or scoped to a single deployment. Values can be passed as arguments or piped from stdin.
dibbla secrets manages the secret store on the Dibbla platform. Secrets come in three scopes, and the narrowest one that matches wins:
- Global — available to every deployment in the org. Omit
--deployment. - Per-deployment — only injected into a single app. Set
--deployment <alias>. - Per-service — only injected into one service of a multi-service app. Add
--service <name>alongside--deployment.
Secrets are injected into deployments at runtime as environment variables. The CLI never logs values; set and get print only the secret’s content (or nothing).
To load a whole .env file at once instead of calling set per key, use secrets import.
dibbla secrets list
| Flag | Purpose |
|---|---|
-d, --deployment <alias> | List secrets attached to one deployment. Omit for global secrets. |
-s, --service <name> | Narrow to one service. Requires -d. |
$dibbla secrets list 🌱 Retrieving secrets... Found 2 secret(s) (global): NAME DEPLOYMENT SERVICE UPDATED ---- ----------- ------- ------ DATABASE_URL_MAIN (global) (all) 2026-04-14 10:23:01 STRIPE_KEY (global) (all) 2026-04-28 12:14:55
$dibbla secrets list --deployment my-api 🌱 Retrieving secrets... Found 2 secret(s) (deployment 'my-api'): NAME DEPLOYMENT SERVICE UPDATED ---- ----------- ------- ------ DATABASE_URL_TODO my-api (all) 2026-04-28 13:01:12 WEBHOOK_SIGNING_SECRET my-api web 2026-04-25 09:42:18
dibbla secrets set
Create or update a secret. The value comes from the second positional argument or, if omitted, from stdin — useful when you don’t want the value in shell history.
| Flag | Purpose |
|---|---|
<name> (positional, required) | Secret name. Conventionally SCREAMING_SNAKE_CASE. |
[value] (positional) | Secret value. If omitted, read from stdin. |
-d, --deployment <alias> | Attach the secret to a single deployment. Omit for global. |
-s, --service <name> | Scope to one service of a multi-service app. Requires -d. |
$dibbla secrets set STRIPE_KEY sk_live_... 🌱 Setting secret 'STRIPE_KEY'... ✅ Secret 'STRIPE_KEY' set Secret: STRIPE_KEY
# Avoid leaving the value in shell history $echo "$STRIPE_KEY" | dibbla secrets set STRIPE_KEY # Or read from a file $dibbla secrets set TLS_CERT < cert.pem
$dibbla secrets set WEBHOOK_SIGNING_SECRET whsec_... --deployment my-api 🌱 Setting secret 'WEBHOOK_SIGNING_SECRET'... ✅ Secret 'WEBHOOK_SIGNING_SECRET' set Secret: WEBHOOK_SIGNING_SECRET Deployment: my-api
When you pass a secret as a positional argument, the full command is stored in your shell’s history file. Pipe via stdin (or read from a file) for anything more sensitive than a placeholder.
dibbla secrets import
Bulk-load every KEY=value from a .env-style file into the secret store in one shot — without a redeploy. This is the alternative to a while read loop around secrets set, and it keeps values out of your shell history.
| Flag | Purpose |
|---|---|
<file> (positional, required) | A .env-style file. See .env file format below. |
-e, --env KEY=value | Override a single key on top of the file. Repeatable. |
-d, --deployment <alias> | Import into one deployment. Omit for global secrets. |
-s, --service <name> | Scope to a single service. Requires -d. |
--dry-run | List the keys that would be set. No values, no network calls. |
The file is the base layer and -e KEY=value flags override individual keys. If a key appears in more than one -e flag, the last one wins. This is the same env precedence dibbla run --env-file uses.
$dibbla secrets import ../secrets/.env.prod --deployment my-api 🌱 Importing 3 secret(s) into deployment my-api... ✅ imported 3 secret(s) into deployment my-api: API_KEY, DATABASE_URL, STRIPE_KEY
# File is the base layer; -e wins for that one key $dibbla secrets import ../secrets/.env.prod \ --deployment my-api \ -e STRIPE_KEY=sk_live_rotated
$dibbla secrets import .env --deployment my-api --dry-run 🌱 Dry run — would import 3 secret(s) into deployment my-api: API_KEY DATABASE_URL STRIPE_KEY No secrets were written (--dry-run).
$dibbla secrets import .env --deployment my-api ❌ Invalid secret name(s): 1BAD, my.key Names must match ^[a-zA-Z][a-zA-Z0-9_]{0,127}$ Nothing was imported.
Every key is validated before anything is sent. Names must match ^[a-zA-Z][a-zA-Z0-9_]{0,127}$ — start with a letter, then letters, digits, and underscores. If any key in the file is invalid, the command names the offending keys, exits non-zero, and imports nothing; you never end up with half a file applied.
Values are never printed. Output is key names and a count, on both the success and the failure path.
Re-running is safe. The server upserts each secret, so an import is idempotent. If a write fails partway, the command stops, tells you which key failed and how many succeeded, and you can simply re-run it.
secrets import reads the file client-side and sends the values over the
authenticated API — the file itself is never uploaded. But a .env sitting in
the directory you deploy is a separate problem: it is a pre-deploy guardrail
blocker and is stripped from Dibbla-managed VCS. Keep the file somewhere
else (dibbla secrets import ../secrets/.env.prod) or list it in
.dibblaignore.
.env file format
The same parser backs secrets import, dibbla deploy --env-file, dibbla apps update --env-file, and dibbla run --env-file.
| Line | Result |
|---|---|
KEY=value | The basic form. |
export KEY=value | Accepted — export is ignored. |
# comment | Whole-line comments are skipped, as are blank lines. |
KEY=value # note | Trailing comments are stripped. |
KEY= | An empty string, not “unset”. |
KEY=a=b=c | Split on the first =, so the value is a=b=c. |
KEY="has spaces" | Quotes are stripped. Double-quoted values may span lines. |
KEY="pre $OTHER post" | $VAR and ${VAR} are expanded — in double-quoted and unquoted values alike. |
KEY='literal ${OTHER}' | Single quotes are literal — nothing is expanded. |
Expansion applies to uppercase names only, and it does not care about double quotes:
PASSWORD=p$ASSW0RDandPASSWORD="p$ASSW0RD"both import as justp—$ASSW0RDis an undefined variable and expands to nothing.PASSWORD="p$assw0rd"survives intact, because$assw0rdis lowercase.
That asymmetry is the trap: a value works, one character becomes a capital,
and it silently truncates. Single-quote anything containing a $ and stop
thinking about it — PASSWORD='p$ASSW0RD'.
A - in a name (MY-KEY=x) is a parse error and fails the whole file.
dibbla secrets get
Print a secret’s value. Output is the raw value with no labels — pipeable.
| Flag | Purpose |
|---|---|
<name> (positional, required) | Secret name. |
-d, --deployment <alias> | Read a deployment-scoped secret. |
$dibbla secrets get DATABASE_URL postgres://user:[email protected]:30432/main?sslmode=require # Use it in another command $psql $(dibbla secrets get DATABASE_URL)
dibbla secrets delete
Remove a secret. Apps that reference it will lose the env var on their next start.
| Flag | Purpose |
|---|---|
<name> (positional, required) | Secret name. |
-d, --deployment <alias> | Delete a deployment-scoped secret. |
-y, --yes | Skip the confirmation prompt. |
$dibbla secrets delete STRIPE_KEY --yes 🗑️ Attempting to delete secret 'STRIPE_KEY' (global)... ✅ Secret 'STRIPE_KEY' deleted
See also
dibbla db—db createautomatically creates aDATABASE_URLsecret.dibbla deploy— deployments inherit global and matching scoped secrets at runtime, anddeploy --env-fileseeds env vars from the same kind of file.dibbla run— the same file-then-flags precedence, for pipeline steps.