Variables and secrets

Your app reads its settings from its environment. Alf has two kinds:

Both are stored encrypted. PORT is always set for you.

Changing them

Open the service's Variables & secrets tab, edit, and Save changes. Nothing restarts yet: a banner lists what changed ("STRIPE_KEY (secret) added · LOG_LEVEL changed") with Deploy changes and Discard. Deploying restarts the containers with the new values (the same image or commit, no rebuild).

So you can change several things and send them out together. Project cards show "changes to deploy" while some are waiting.

From the command line: alf env set KEY=value sets and deploys in one go (--stage leaves it waiting), alf env push sets a .env file's lines on the service (passwords and keys as secrets, asking first), alf env pull writes the variables to a .env file, and alf run -- <command> runs your code on your machine with them, its databases connected.

What other deploys do with waiting changes

Every deployment says what it did with them, in the Deployments tab and in what the deploy command and agents get back:

DeployWaiting changes
Deploy button, pushed code, an agent's deploygo live with it ("Deployed with 2 staged changes…"), unless you ask to keep them staged (--keep-staged)
A rollback, a settings changestay staged ("…still staged and NOT in this deployment")
A candidaterun in the candidate, and go live when it's promoted

Pasting a .env file

Paste a .env file adds its KEY=value lines as variables. Move anything sensitive to secrets afterwards.

Connecting services

Use the project network's names in your values:

REDIS_URL=redis://cache:6379

Values are taken as they are (one variable can't refer to another), so a connection string with a password goes in as a whole secret:

DATABASE_URL=postgres://app:the-password@db:5432/app   (a secret)

Pointing at another service

A variable can point at another service in the same project instead of repeating its value:

DATABASE_URL = postgres://app:${{db.PASSWORD}}@${{db.HOST}}:${{db.PORT}}/app

db is the other service's address part. The point is that the password lives in one place: change it on the database, deploy the app, and the app has the new one — nobody has to remember the second copy.

Alongside whatever that service has set, four things about it are always readable:

HOSTits name inside the project
PORTthe port it listens on
URLhttps://… if it's public, otherwise http://host:port inside the project
NAMEwhat it's called

A service can point at itself for those four — that's how it learns its own address (${{web.URL}}) — but not at its own variables.

Two things worth knowing. A reference resolves to what the other service has stored, and no further: if that value is itself a reference, it's left alone. And a reference to a service that isn't in the project is refused when you save it, rather than turning up in the container as the text you typed.