Skip to content

Configuration

A Custos deployment is configured through environment variables and a small set of runtime settings. This page is the operator’s map of that surface: the knobs you’ll actually set, with the context to set them safely. The exhaustive, drift-proof inventory of every setting is the generated configuration reference, produced directly from the server’s configuration types.

Some of these settings change what your server advertises to clients, not just how it behaves: describeServer names the capabilities this deployment offers, and clients enable features accordingly. See Capabilities for which settings those are.

These are injected at runtime and never baked into the image:

VariableRole
EZPDS_SIGNING_KEY_MASTER_KEYMaster key (64 hex chars = 32 bytes) — the AES-256-GCM key that encrypts all at-rest signing material: every account’s repo signing key, the server’s OAuth signing key, the JWT secret, and the node identity.
EZPDS_ADMIN_TOKENBearer token guarding the admin/operator endpoints.

Rotation is supported, but only as a deliberate offline operation: the pds rewrap-master-key subcommand re-encrypts every stored secret from the old key to the new one in a single atomic transaction, with the server stopped. Old and new keys are supplied via EZPDS_REWRAP_OLD_MASTER_KEY / EZPDS_REWRAP_NEW_MASTER_KEY environment variables (never CLI arguments), a wrong old key aborts with no writes, and only after the re-wrap succeeds do you point EZPDS_SIGNING_KEY_MASTER_KEY at the new key and restart. Never rotate by changing the environment variable alone.

VariableRole
PORTInjected by the platform; the server binds it.
EZPDS_PUBLIC_URLThe externally reachable origin of the PDS.
EZPDS_AVAILABLE_USER_DOMAINSDomains users may claim handles on.
EZPDS_LABELER_WATCHEDComma-separated labeler DIDs to watch; hosted accounts they label are flagged on the operator console. Off (empty) by default — see Moderation § Labeler watching.
EZPDS_OAUTH_ACCESS_TOKEN_TTL_SECSHow long an OAuth access token stays valid, in seconds. Defaults to 900 (15 minutes), matching the reference implementation; accepted range is 1–1800. Leave it alone unless you have a specific reason: shortening it makes every app refresh more often, and lengthening it widens the window in which a leaked token still works.

The table above is the operator-facing subset. Every remaining setting, with its type, default, and doc-comment, is in the generated configuration reference.