os.getenv() just like any other environment variable. Secrets can be scoped to specific environments (e.g., different API keys for staging vs production) and are separate from the platform environment variables that fal injects automatically.
Setting Secrets
You can set secrets from the Dashboard, the CLI, or the Python SDK.Dashboard
Navigate to Dashboard > Secrets to create, edit, and delete secrets. Select the environment (e.g., main, staging) from the dropdown, then add your key-value pairs. Values are encrypted and never displayed after creation.CLI
--env flag:
Python SDK
Accessing Secrets at Runtime
Secrets are available as standard environment variables inside your app. Useos.getenv() to read them in setup(), endpoint handlers, or anywhere else in your runner code.
Secrets are injected when a runner starts. If you update a secret, running runners keep the old value. Only new runners (from a new deploy or scale-up) pick up the updated value. To force all runners to use the new value, redeploy your app with
fal deploy.Scoping Secrets to an App
By default, every secret in a deploy’s environment is injected into the app. When an app only needs a couple of them, you can declare an allowlist with thesecrets class attribute so the runner receives only the secrets you name — nothing else from your account is exposed. Any account can use the attribute; it just needs a recent fal SDK (see the version note below).
In other words, the two account modes differ on a single point — what an app that says nothing gets. Expose-by-default (the standard setting) gives such an app every secret in the environment; withhold-by-default gives it none — in both cases subject to each secret’s own exposure setting, described next. Because an explicit
secrets = [...] (or []) takes priority over the account setting, an app that declares its secrets behaves identically on either kind of account — so a switch to withhold-by-default never changes what a fully-declared app receives, and only affects apps that omit the attribute.
There is one refinement to the omitted row: each secret also carries its own exposure setting, which takes precedence over the account default. A secret stored with fal secrets set NAME=VALUE --not-exposed-by-default is withheld from apps that omit the attribute even on an expose-by-default account, while a secret stored as exposed (which is what a current fal secrets set does without the flag) is injected into such apps even on a withhold-by-default account. An explicit allowlist (or []) ignores this setting entirely. In practice this matters most on withhold-by-default accounts: a plain fal secrets set marks the secret exposed, so pass --not-exposed-by-default when setting secrets (or declare an allowlist in every app) if you rely on the account default to withhold them.
Withhold-by-default is configured by fal on a per-account basis (it isn’t self-serve) — contact fal if you’d like your account switched to it. The secrets attribute itself works regardless of which mode your account is in.
Per-app secrets require fal SDK v1.72.3 or newer. On older SDK versions the
secrets attribute is ignored and the app falls back to the omitted behavior above (the first row of the table). Check your version with fal --version and upgrade with pip install --upgrade fal.Secrets During Build
For security, secrets are not available as environment variables during the image build stage. The built image is cached and may be shared across environments, so injecting secrets into the build would risk leaking them. Instead, use the${} substitution syntax in your requirements list. fal replaces ${SECRET_NAME} with the secret value at build time without exposing it in the cached image.
Docker Build Secrets
If you use a custom container image, you can pass build-time secrets via thesecrets parameter on ContainerImage. These are mounted as Docker build secrets (via --mount=type=secret) and are available inside your Dockerfile during the build but not persisted in the final image.
Secrets Per Environment
Secrets can be scoped to specific environments, letting you use different credentials for development, staging, and production. When you deploy to an environment, the runner receives the secrets set for that environment.Managing Secrets
Listing
List your secrets to see their names, environments, and creation dates. Values are never displayed.
To list secrets for a specific environment: