Secrets
Keep API keys and credentials out of your code
API keys, database passwords and private keys don't belong in source code. Encore.py lets you declare a secret in code and give it a value outside it: on your machine, or in Encore Cloud for each environment.
Declaring a secret
Declare a secret as a module-level variable, with the type of its value, str or bytes:
billing/secrets.pyfrom encore.secrets import Secret
stripe_key = Secret[str]("StripeKey")
Read the value with .value where you need it:
billing/payments.pyimport httpx
from billing.secrets import stripe_key
async def charge(customer_id: str, amount: int) -> None:
async with httpx.AsyncClient() as client:
await client.post(
"https://api.stripe.com/v1/charges",
headers={"Authorization": f"Bearer {stripe_key.value}"},
data={"customer": customer_id, "amount": amount, "currency": "usd"},
)
A few rules apply, because Encore reads secret declarations from the source:
- Declare secrets at module level, not inside functions or classes.
- The name must be a string literal and an identifier: a letter or underscore, then letters, digits and underscores.
- The type argument is required.
Secret[str]decodes the value as UTF-8 andSecret[bytes]returns it unchanged. A variable annotation alone doesn't count:key: Secret[str] = Secret("Key")raisesTypeErrorwhen you read.value. - Use the secret by reading
.value(or.name). Encore records which services read which secrets from these accesses, so it rejects passing the secret object around as a value. Pass the value instead.
Reading .value raises KeyError if the secret has no value in the current environment. The value is looked up on first read and cached.
Secret scopes
The class you declare a secret with decides who it belongs to:
from encore.secrets import GlobalSecret, Secret, SharedSecret
api_key = Secret[str]("ApiKey") # this service's own
signing_key = SharedSecret[bytes]("SigningKey") # shared by several services
sentry_dsn = GlobalSecret[str]("SentryDSN") # e.g. for library code outside services
Service secrets have a namespace of their own, separate from shared and global secrets, so a service's ApiKey and a shared ApiKey are different secrets, and neither falls back to the other. Shared and global secrets use the same namespace. Declare each shared or global secret once in the app, and import the declaration wherever you need it.
Setting secret values
Use encore secret set. It reads the value from stdin, so you can pipe it in, or it prompts for it without echoing when run in a terminal.
On your machine
By default, encore secret set writes a value for your machine only:
$ encore secret set SigningKey # a shared or global secret$ encore secret set --service billing ApiKey # the billing service's own secret$ encore secret set billing.ApiKey # the same thing
Run encore secret set with no name to be asked for each declared secret that has no value on your machine.
These values are stored in .secrets.local.toml in your app's root, next to encore.app. The file is meant to be gitignored. You can also edit it directly:
.secrets.local.toml[shared]
SigningKey = "local-signing-key"
[services.billing]
ApiKey = "sk_test_123"
[shared] holds shared and global secrets, and [services.<name>] holds each service's own. Values are plain strings.
A running service keeps the values it started with. When a value it uses changes, encore run reports the service as stale until it restarts.
In Encore Cloud
To store a value in Encore Cloud, name the environment types or environments it's for:
$ encore secret set --type production SigningKey$ encore secret set --type development,preview,local SigningKey$ encore secret set --env staging SigningKey
The environment types are production (prod), development (dev), preview (pr) and local. A value set for a named environment with --env takes precedence over the value for its type. For an app linked to Encore Cloud, values for the local type reach every developer's encore run and encore test; a value in .secrets.local.toml overrides them on your machine.
You can also manage values in the Encore Cloud dashboard, under Settings > Secrets.
Encore Cloud doesn't store per-service secret values yet. A service's own Secret can only get a value on your machine, with --service. For values you need in deployed environments, use SharedSecret or GlobalSecret.
Checking and removing values
$ encore secret list # which secrets have values, and where$ encore secret list --missing # only declared secrets without a value; exits non-zero if any$ encore secret unset SigningKey # remove this machine's value$ encore secret unset --type production SigningKey
encore secret list never prints values. encore secret unset takes the same target flags as set.
Secrets in tests
encore test gives your tests the same values as encore run: the local values from Encore Cloud, overridden by .secrets.local.toml. A secret with no value raises KeyError when the test reads it.
Secrets in configuration
A config can have fields that read a secret rather than hold a value, so code reading the config gets the secret along with its other settings. See Secrets in config.