Dibbla Docs Get started Guides Workflows Changelog
Open Console
Guides

Secrets and local development

Values live in Dibbla, names live in the code. .env.example lists what the app needs, dibbla env pull fetches its settings and the names of its secrets, you fill in development values, and nothing secret ever reaches git.

Your app’s settings and secrets live in Dibbla and are handed to it when it runs. This page is about the other direction: running the app on your own computer, with its settings and with development values of your own for its secrets, without any of them ever landing in git.

The model in three sentences

Values live in Dibbla, names live in the code. A file called .env.example in the repository lists the variables the app needs — just the names, one comment each, no values — and it is the one .env file the platform keeps in the app’s history. dibbla env pull writes a .env.local on your machine with every plain variable’s value and every secret’s name — Dibbla never hands out a secret’s value, so you fill in a development value of your own — and that file never goes back: .gitignore, the platform’s filter and the push hook all refuse it.

Think of a safe and a row of keyholes. The safe is Dibbla, and it opens only into the running app; .env.example is the row of keyholes, so anyone who opens the code can see what fits. env pull copies the settings that were never locked away and leaves an empty line for each key in the safe. On this computer you use keys of your own: a test key, a sandbox account, a local database.

.env.example — the names

# .env.example — committed. Names and a comment each, never a value.
STRIPE_KEY=          # Stripe secret key for payments
DATABASE_URL_MAIN=   # created by `dibbla db create main`; Dibbla fills it in
SMTP_PASSWORD=       # for the mail we send

Every Dibbla template ships one, and the platform keeps .env.example (and .env.sample) in the app’s repository while it strips every other .env* file. That is what makes a dibbla clone on a new computer self-describing: the list of what the app needs comes with the code.

dibbla env pull — the settings, and the secrets by name

In a folder linked to the app (one you got from dibbla clone or dibbla link), or anywhere with --deployment <alias>:

$dibbla env pull
✅ .env.local: 4 variable(s) from Dibbla (app my-app) — 1 inline, 3 platform
   3 secret(s) by name only — Dibbla never hands out a secret's value; fill in development values (0 already set here)
   added .env.local to .gitignore so git never sees it
   This file lives only on this machine.
# one service of a multi-service app
$dibbla env pull -d my-app --service worker
# rewrite the file instead of updating it in place
$dibbla env pull --replace
# into the current shell, no file written
$eval "$(dibbla env pull --stdout)"
# names, values and which layer each came from — secrets by name
$dibbla env pull --json

What you get is the running app’s environment, resolved the same way. Every plain variable comes with its value: the ones set with deploy -e or in dibbla.yaml, and the DIBBLA_* the platform injects for the app’s alias and its siblings. Every secret comes as an empty line under a comment of its own — the ones you set, and the ones the platform created, DATABASE_URL_* for your databases and STORAGE_* for your buckets:

# Secrets: Dibbla never hands out a secret's value. Set a development value for each one here.
# DATABASE_URL_MAIN: for a connection of your own, use "$(dibbla db connect main -q)" in the start command — it carries your API token, so not in this file
DATABASE_URL_MAIN=
SMTP_PASSWORD=
STRIPE_KEY=

Fill each one in with a development value — a Stripe test key, a sandbox mail account, a local database — and start the app the way its Dockerfile or README does, for example docker build -t my-app . && docker run --rm -p 3000:3000 --env-file .env.local my-app.

Run env pull again whenever the app’s settings change. An existing .env.local is updated in place: the variables Dibbla knows are refreshed, and any line you added yourself — a local port, a comment — stays. A secret line you filled in is never overwritten, not even by --replace. If your .env.local came from a pull made before secrets became write-only, those lines hold the app’s real secrets; env pull names them, and you should replace them with development values.

env pull also names the plain variables whose name or value looks like a secret. Those are readable by anyone who can read the app’s configuration, so they belong in the secret store: dibbla env promote NAME turns each into a secret for the whole app, with a new value you enter on a Dibbla page — see env promote.

Reading the environment takes the deploy roles: owners, admins and developers. A viewer is refused, and env pull says so.

Adding a new secret

The value goes into Dibbla first, the name into the code, and then the empty line comes back down: dibbla secrets set STRIPE_KEY -d my-app (paste the value at the prompt) or dibbla secrets request STRIPE_KEY -d my-app for a link, add STRIPE_KEY= with a comment to .env.example, run dibbla env pull, and fill in a development value. Never give a value its only home in .env.local — the file does not travel, so the deployed app would start without it.

If .env.local ends up in a commit

It will not get far. .gitignore is the first lock — env pull adds the .env.local line if it is missing and tells you. Should the file be committed anyway, dibbla deploy filters it out of the app’s history and reports the path, and a git push is refused before anything lands:

remote: push denied for refs/heads/main: .env.local holds secrets and cannot be pushed to Dibbla.
remote: Secrets belong in dibbla secrets (dibbla secrets set NAME value -d <app>); the file should be listed in .gitignore.
remote: Take it out of the commit (git rm --cached .env.local && git commit --amend --no-edit), keep the names in .env.example
remote: and fetch the values with dibbla env pull

Do what it says — and leave the value off secrets set: it asks for it at a hidden prompt. The app’s own secrets are still safe in Dibbla; only the copy in your commit was the problem.

Using the app’s real data from your computer

Dibbla has one environment per app, and a pulled .env.local does not reach into it on its own: the database and bucket lines arrive empty. You decide, per line, whether a local run works on a copy of its own or on the app’s real data.

  • A database of your own. Run a Postgres on your machine and put its URL on the DATABASE_URL_* line. A local run can then delete whatever it likes.
  • The app’s real database. dibbla db connect <name> -q gives you a connection of your own through Dibbla’s database proxy, signed in as you. Its password is your own API token, so set it in the start command rather than in the file: docker run --env-file .env.local -e DATABASE_URL_MAIN="$(dibbla db connect main -q)" …, or export it before npm run dev. That is the same data the deployed app uses — a local run that deletes rows deletes them for real.
  • Buckets. Point the STORAGE_* lines at a local S3-compatible store such as MinIO, or run without the bucket. The app’s own bucket keys are secrets and are not handed out — see storage credentials.

A code agent asked to set up a local environment should say which of these it is doing before it starts the app.

Say this to your code agent

Have a code agent set up the app to run on this computer.

Set up a local development environment for this app.

A well-informed agent reads .env.example, runs dibbla env pull, and tells you in a sentence or two that the settings came from Dibbla and live only on this computer, and that each secret arrived empty and needs a development value — a test key, never the app’s real one. It offers a local database, or — if you want the app’s real data — dibbla db connect, and then says plainly that the app runs against the same database as the real one. It starts the app the way its Dockerfile or template does. It never asks you to paste a key into the chat. You never need to mention git, secrets or environment variables.

See also