Environment variables
Set, unset, list, encryption
How it works, with exact details
Environment variables are how you give your app secrets and settings — API keys, database URLs — without putting them in your code. Percher encrypts them at rest (AES-256-GCM) and injects them when your app starts. Changes take effect on the next deploy — run percher publish to apply immediately.
Import a whole .env file at once
--from-env-file sets every KEY=VALUE line from a .env-format file in one call (comments, quotes, and export prefixes handled; the file is only read when you pass the flag). The dashboard env editor has the same flow — "Paste a .env file" previews what will be set, with conflict badges, before anything is saved.
Different values for preview and live (deploy scopes)
Unscoped vars (the default) apply everywhere. --scope preview applies a var only to preview deploys and overrides the unscoped value there — --scope live does the reverse. Point previews at a staging database with percher env set DATABASE_URL=... --scope preview and live keeps its own value. Unset is scope-specific, and the env-requirement gate resolves against the deploy type, so a preview-only key never satisfies a live deploy. Three keys can't be scoped: SITE_PASSWORD (the login gate reads one password per app) and the PocketBase admin credentials (platform-managed).
Expose a key at build time (NEXT_PUBLIC_*, [build] pass_env)
Keys matching a public prefix (NEXT_PUBLIC_*, VITE_*, …) are forwarded to the build automatically and baked into the client bundle — the env editor marks them "build + runtime". Everything else is only available at runtime, which is correct for secrets but breaks frameworks that expect a non-prefix value at build time. Opt those in per-key via [build] pass_env in percher.toml:
For Dockerfile-based projects (runtime = "docker") Percher does not mount build secrets yet: pass_env values arrive as --build-arg. A value read through ARG is recorded in that stage's build history and cache; ENV puts it in the image. Keep it in a build stage that is not the final stage and never ENV it, or use runtime node/bun/python, where Percher mounts non-public keys as BuildKit secrets and never writes them into the image. A build step that prints or saves a value still ships it.
Call external APIs from your app (outbound HTTPS)
Apps run on an internal Docker network and reach the public internet through a forward HTTP proxy that Percher injects automatically:
Bun and Node 22.21+ / 24+ use the proxy automatically — fetch("https://api.exa.ai/...") just works. Python (requests/httpx/urllib) and Go (http.DefaultTransport) also honor HTTPS_PROXY natively. For Node 20 (and the 21 / 23 lines) wire up undici manually at app startup:
Direct outbound is blocked by design — apps can't scan internal hosts or hit cloud metadata. If a smoke probe sees ENETUNREACH on 1.1.1.1:443, that's the symptom of the runtime not using the proxy, not a missing-egress problem.
There is no host allowlist, but proxied HTTPS is port 443 only — a URL with an explicit non-standard port (https://host:8443) gets a 403 straight from the proxy. Plain http:// fetches are unrestricted by port.