The env block
Every app needs configuration — a port to listen on, an API key for a third-party service, a secret for signing sessions. In a Launchfile, the env block declares all of this in one place.
Each variable can have a default value, be marked as required, include a human-readable description, use a generator for automatic creation, or be flagged as sensitive so it's masked in logs.
Build it up
env:
PORT:
default: "3000"required when the app can't start without it. The description tells the deployer what to provide. Nothing invents a value for you: if you don't supply one, the deploy stops and names the variable.env:
PORT:
default: "3000"
API_KEY:
required: true
description: "Third-party API key"generator: secret field declares that a cryptographic random value should be created at deploy time — always 32 random bytes, hex-encoded (64 characters). Marking it sensitive keeps it out of logs.env:
PORT:
default: "3000"
API_KEY:
required: true
description: "Third-party API key"
SESSION_SECRET:
generator: secret
sensitive: truesecrets block. Reference secrets with ${secrets.app-key} and apply pipe transforms like |base64, which re-encodes the secret's underlying 32 bytes — exactly the key length Laravel-style apps expect.secrets:
app-key:
generator: secret
env:
PORT:
default: "3000"
APP_KEY: "base64:${secrets.app-key|base64}"Secrets vs env
There are two ways to generate secrets in a Launchfile:
- Inline in env: Add
generator: secretdirectly to an env var. Simple and self-contained. - Secrets block: Define named secrets at the top level, then reference them with
${secrets.name}in env. Useful when one secret feeds multiple env vars, or when you need transforms.
For most apps, the inline approach is all you need. Reach for the secrets block when you need to reuse or transform a generated value.
env:
SESSION_SECRET:
generator: secret
sensitive: truesecrets:
session-key:
generator: secret
env:
SESSION_SECRET: "${secrets.session-key}"Where a value comes from decides how the platform treats it later:
- Generated values (
generator: secret) are created once and then preserved — a redeploy never regenerates them, because that would invalidate sessions and encrypted data. - Expression defaults (like
$app.url) are kept up to date by the platform — if your app's domain changes, the value follows, unless you've overridden it. - Literal defaults are just starting values — the platform or deployer can override them per environment.
- Values you supply (required or optional, with no default) are yours alone — the platform never writes or changes them. A
required:value you have not supplied stops the deploy and names the variable; no provider invents one for you.
A required: variable with no default:, no generator:, and no resource binding is a value you supply. Supply it through the launching environment:
API_KEY=sk-live-... launchfile upLeave it out and the deploy stops before anything starts, naming the component and the variable:
Cannot launch: 1 required environment variable had no value.
- default: API_KEY (sensitive)That is deliberate. A substituted placeholder would satisfy the app's own presence check and push the failure out to the first login, the first query, or the first send — long past the point where you could diagnose it.
Some apps won't take a full URL — their config expects the address split into separate fields: a host here, an SSL flag there. The $app.* family covers both shapes:
env:
PUBLIC_URL: $app.url # the single-string case — prefer this
CMD_DOMAIN: $app.authority # public host[:port], port omitted when default
CMD_PROTOCOL_USESSL: $app.tls # "true" or "false" — for literal SSL on/off flags$app.authority, $app.scheme, and $app.tls are all derived from $app.url, so any provider that can resolve the URL can resolve the pieces. Reach for them only when the app genuinely needs the address split — $app.url stays the default.
In the wild
Firefly III is a personal finance manager with one of the more interesting Launchfiles in the catalog. It uses a secrets block with a |base64 pipe transform, references $app.url for its public URL, and wires Postgres connection details individually.
version: launch/v1
name: firefly-iii
description: "Personal finance manager with budgeting and reporting"
repository: https://github.com/firefly-iii/firefly-iii
website: https://firefly-iii.org
logo: https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/public/v1/images/logo.svg
image: fireflyiii/core:latest
provides:
- protocol: http
port: 8080
exposed: true
requires:
- type: postgres
set_env:
DB_CONNECTION: "pgsql"
DB_HOST: $host
DB_PORT: $port
DB_DATABASE: $name
DB_USERNAME: $user
DB_PASSWORD: $password
secrets:
app-key:
generator: secret
env:
APP_KEY: "base64:${secrets.app-key|base64}"
APP_URL:
default: $app.url
description: "Public URL Firefly III is reachable on (used in emails, OAuth, links)"
health: /login
storage:
uploads:
path: /var/www/html/storage/upload
persistent: true
restart: alwayssecrets:- Defines a named secret that gets generated once and reused.
APP_KEY:- References the generated secret with a |base64 pipe transform — the app expects a base64-encoded key.
APP_URL:- Uses $app.url — a built-in expression that resolves to the app's public URL.
set_env:- Wires Postgres credentials individually instead of using a single $url — because Firefly expects separate DB_HOST, DB_PORT, etc.
storage:- Persists the upload directory so user data survives redeployments.
Try it: npx launchfile up firefly-iii to launch this app locally.View in catalog
Check your understanding
- The
envblock declares all environment variables with optionaldefault,required,description,generator, andsensitivefields. generator: secretauto-creates a cryptographic random value at deploy time — 32 bytes, hex-encoded (64 characters), on every provider.- The
secretsblock defines reusable, named secrets referenced via${secrets.name}expressions. - Pipe transforms like
|base64let you encode or transform values inline. - The
$app.*properties resolve to the app's own public address —$app.urlas one string, or$app.authority/$app.scheme/$app.tlswhen the app wants it in pieces.