All pages
Secrets
A secret is a value your app needs in its environment that must not be in the repository, in the state store, in a shell history, or in a conversation with an agent. Everything else is plain configuration and goes in the compose file as it is.
Setting one
pilot secret set DATABASE_URL # prompts. The value is never an argument
pilot secret import .env
pilot secret ls
pilot secret rm DATABASE_URL
pilot secret set prompts for the value rather than taking it as
an argument, which is what keeps it out of your shell history. It stores it locally,
keyed by the app the compose file names.
Referring to it
compose.pilots.yaml
services:
web:
build: .
environment:
DATABASE_URL: secret://database_url
LOG_LEVEL: debug
pilot deployresolves eachsecret://reference on your own machine and sends the values as a sealed environment.- The host seals them with the fleet key before they touch any replicated row, so a secret is never readable out of the state store.
pilot service inforeturns environment KEYS and never values.
The rules
| Rule | Why |
|---|---|
| You run the command that holds the value, not an agent | A value passed as a tool argument has already passed through the model and the transcript. |
The compose file carries secret://name, never a value
| The file is committed. The value is not. |
| A fleet with no fleet key refuses a sealed environment | It would otherwise write a plaintext secret into every replica of the state store. |
--secret-env on pilot service set REPLACES the sealed
environment rather than merging into it
| A secret that was meant to be removed must not linger because a later call forgot it. |
When it is refused
not_configurednaming the fleet key means the fleet cannot seal secrets. Send plain configuration only, and tell whoever runs the fleet.- A
secret://reference with nothing stored means the deploy has no value for it. Set it and deploy again.
Three things that do not work, on purpose
- Reading a secret back to confirm it. Nothing returns one.
- Passing a secret as plain
env. It would be stored unsealed. - Putting a long-lived API key in a machine's environment so it can call the API. Use a grant instead: the key would otherwise be in every snapshot and every fork, and would outlive the machine (what a machine may do).