Deploy
Secrets
Every project gets a key/value store for API keys, database URLs, and plain configuration. Every value is encrypted the same way whether it's marked secret or not, injected into the container once at start, and never fetched back over the network afterward.
How are secrets stored?
Every value - secret or plain environment variable - is encrypted with libsodium's crypto_secretbox before it touches the database, using a 32-byte master key that lives only as a Docker secret, never an environment variable. A fresh random nonce is generated per write and stored alongside the ciphertext, so the same value never produces the same row twice.
The distinction between a secret and a plain env var is purely about handling, not encryption: a secret's value is never echoed back through the API once written (the field comes back masked), and it's scrubbed out of live log output. A plain env var is readable and shown in the clear - useful for a non-sensitive setting like a feature flag or a base URL that's handy to see at a glance.
When are secrets injected into the container?
Secrets and env vars are decrypted once, at the moment a container is created, and passed in as its environment - the same way any Docker container receives env. A deployed server never calls back into the platform to ask for a value; there's nothing to reach, since a project's container sits on its own network with no path to the platform's internal API. Changing a value takes effect on the next deploy or redeploy, not instantly on save.
What can a secret be named?
A key must start with a letter or underscore and contain only letters, digits, and underscores - the shape every shell and container runtime expects for an environment variable name. A small set of names is reserved for the platform itself (the routing port, the per-project auth token, the public-visibility flag, the host allowlist), plus the FORO_ and FASTMCP_ prefixes entirely, so a project's own entry can never silently shadow something the platform or FastMCP relies on. A key that collides is rejected outright, before it's ever stored.
Can a secret leak into the logs?
Every secret value (not plain env vars) is scrubbed from the live deploy and build log streams before a line is published or persisted - so a build script that prints its environment for debugging doesn't leak an API key into a log another teammate can read later.