Set environment variables
Plain values, secrets and links — per environment, per app, or per target — and how they reach the container
Goal. api reads LOG_LEVEL and a secret API_KEY from its environment, with the
secret never written to pier.yaml.
A plain value
pier vars set LOG_LEVEL=info --app api→ Updated pier.yaml
Changes:
+ create env_var "LOG_LEVEL" in prod (plain)
OK Set LOG_LEVEL on api in prod
--app api scopes the variable to the app. Without it, the variable is set on the
environment and every app and site in it sees it; --app api/canary scopes it to one
target. A narrower scope wins over a wider one with the same key.
A secret
pier vars set API_KEY --secret --secret-value 'sk_live_9f2e4c…' --app api→ Updated pier.yaml
Changes:
+ create env_var "API_KEY" in prod (secret)
OK Set API_KEY on api in prod (secret)
The declaration (API_KEY: { secret: true }) is written to pier.yaml; the value is
stored in the platform's vault only. --secret-value - reads the value from stdin;
pier vars import --file .env --secret loads several at once.
Check what is set
pier vars
KEY VALUE SECRET ENV UPDATED
API_KEY ******** yes prod just now
LOG_LEVEL info prod just now
pier vars reveal API_KEYAPI_KEY=sk_live_9f2e4c…
Roll it into the container
A variable change is recorded as a new environment version; the running container keeps
its old environment until the next deploy. pier deploy api releases it without a
rebuild: the plan says deployed inline and counts the pending variables.
pier deploy api→ Comparing prod environment against platform state...
Changes:
~ update app "api" in prod
env_version: 0 → 2 (env var — next deploy)
Deploy:
app "api" deploy (deployed inline)
Env vars:
app "api" 2 pending
OK Applied 1 config change(s) to prod
→ Waiting for infrastructure provisioning...
OK Infrastructure ready
OK Summary: 1 deployed
pier ssh api -- env | grep -E '^(LOG_LEVEL|API_KEY)='API_KEY=sk_live_9f2e4c…
LOG_LEVEL=info
What changed
apps:
- name: api
build_context: ./api
env:
API_KEY:
secret: true
LOG_LEVEL:
value: infoThe file can be committed: it holds no secret value. Applying it from another checkout produces the same declaration, and the container receives the same vault value.
Variations
- Link a resource instead of pasting its URL:
pier vars set DATABASE_URL --from postgres.main.url --app api— Add Postgres to an app. - Edit the file and apply: the
env:block acceptsvalue,secret: true,from, andrequired: false;pier applyconverges it. - Remove:
pier vars rm LOG_LEVEL --app api. - Per environment:
-e stagingon any of these commands targets that environment only; environments never share a variable.