Skip to content
DockBoard
Browse the documentation
DEPLOYING

Environment variables and secrets

Set configuration per application, share it across a project with variable sets, and keep secrets out of Git.

Configuration that changes between environments — a database URL, an API token, a feature flag — belongs in environment variables, not in the repository. DockBoard stores them encrypted and injects them at container start.

Per application

The Environment tab on an application. Add keys and values, save, redeploy. Values are encrypted at rest and are never returned in a deployment log or a build output.

A change takes effect on the next deployment, not immediately. A running container’s environment cannot be edited in place — that is Docker, not DockBoard. Save, then redeploy.

Shared across a project

Six applications that all need the same REDIS_URL should not carry six copies of it. A project variable set is defined once and reaches every application in the project.

A set is either project-wide or scoped to one environment. That gives you the shape you actually want: one DATABASE_URL for staging, another for production, under the same key name.

Which value wins

Three layers, narrowest last. Later beats earlier:

TEXT
project-wide set        REDIS_URL=redis://shared:6379
  ↓ beaten by
environment set         REDIS_URL=redis://staging:6379
  ↓ beaten by
the application itself  REDIS_URL=redis://localhost:6379

The dashboard shows, for every key an application will actually receive, which layer it came from. That is the answer to “why is this variable not what I set” without having to reason about the order yourself.

Use the project layer for what is genuinely shared and the application layer for exceptions. A key overridden in every application is a key that belongs in the application layer only — the shared value is then a decoy that reads as authoritative and never applies.

Variables your repository already carries

A deployment from Git does not ignore the .env files committed in the repository — a project that boots locally on its committed defaults should boot here too. They are read from the clone and merged beneath everything set in DockBoard, so nothing in the repository can quietly displace a value you set in the dashboard.

Within one folder, five names are read in this order, each beating the ones before it:

TEXT
.env.example   →   .env.local.example   →   .env.production   →   .env   →   .env.local
.env.example is read on purpose, at the lowest priority: a repository that ships only a template still deploys on the first try. But when nothing else defines a key, that placeholder becomes the production value — so the build log names every key supplied only by a template, and flags the ones that still look unedited. JWT_SECRET=change_me in a public repository is a public secret.

Monorepos: two folders, not one

When an application lives in a sub-folder of a monorepo, the five names above are read twice: once at the clone root, once in the application’s own sub-folder. The sub-folder wins.

That is what makes a monorepo root .env behave the way its authors intended — shared defaults for every package, each package free to override what concerns it. Nothing is configured to obtain this; it applies as soon as the application has a sub-folder path.

The complete order

Five layers, for a monorepo application deployed from Git in a project that shares variables. Later beats earlier, without exception:

TEXT
1  monorepo root .env*        committed, shared by every package
2  sub-folder .env*           committed, belongs to this application
3  project-wide set           DockBoard, every environment
4  environment set            DockBoard, one environment
5  the application itself     DockBoard, this application

The dividing line is between 2 and 3: everything committed to the repository sits below everything set in DockBoard. A DATABASE_URL in a committed .env is a local-development default; the one in your project set is the real one, and it wins on every deployment.

Layers 1 and 2 exist only for a deployment that clones a repository. An application deployed from a Docker image, a marketplace template or a PHP site has no clone to read, so it has layers 3 to 5 only.
The Environment tab shows the application’s own variables (layer 5) plus what it inherits from the project (layers 3 and 4), with the origin of each. It does not list what the repository supplies — those values only exist once the repository is cloned, which happens during the deployment. A key you cannot find in the tab and yet observe in the container comes from a committed .env; the build log names them.
Both deployment modes apply this identically. A repository baked on your platform host and the same repository built by an agent on a remote server read the same files, in the same order, and produce the same values.

How secrets are handled

  • Values are encrypted at rest with the instance encryption key, not stored as plain columns.
  • Reading or writing them needs apps:env — a permission that is not part of the read-only role. Someone who can see your application does not automatically see its secrets. See roles.
  • Editing the shared project set is gated on the same permission as the per-application tab. It holds production secrets exactly as the app tab does, so it must not be the cheaper door.
  • An API key reaches them only with the project:apps:env scope, which you can decline to grant while still granting deploy rights.
A variable is not a vault. Anything in the environment is readable by the process — and by anyone who can open a shell in the container (apps:exec). If a value must not be readable by the people who operate the application, it does not belong in an environment variable at all.

Variables that DockBoard fills in for you

A managed database exposes a connection string you can paste straight into a variable, already pointing at the project network name rather than at a public address. That is the intended path: applications reach their database over the private network, and the database is never published.

Preview environments copy their source application’s variables, so a preview points at the same database as the branch it was cloned from. That is deliberate — a review environment with no data usually fails to boot — but it means a preview can write to real data.
Environment variables and secrets — DockBoard