How the builtin secret manager is meant to be used
The builtin secret manager stores credentials and other sensitive values outside the project files. Secrets belong to one project and can be loaded into the environments of tasks that need them.
The secret manager is local to your operating-system user account. It is useful for development credentials and other machine-local configuration. It does not synchronize secrets between computers or replace a hosted secret manager for deployment infrastructure.
Secrets belong to a project
xx scopes each secret to the canonical path of the current project. Two projects can use the same key, such as API_TOKEN, without sharing its value. Setting an existing key replaces the value only for the current project.
Run secret commands from the project directory whose secrets you want to manage. Moving the project to a different path gives it a new scope.
Store secrets through the command line
Set and retrieve a value with xx secrets:
xx secrets set API_TOKEN "secret value"
xx secrets get API_TOKEN
Passing a value as an argument can expose it through shell history or operating-system process inspection. To avoid a command-line argument, provide the value through standard input:
xx secrets set API_TOKEN < ~/.config/example/token
You can also pipe the value from a password manager or another credential source. xx stores standard input unchanged, including a trailing newline. xx secrets get also writes the stored value unchanged and does not add a newline.
List the keys in the current project without printing their values:
xx secrets list
Remove a key with xx secrets rm API_TOKEN. Both get and rm fail when the key does not exist.
Load secrets into task environments
The builtin secret manager does not add stored values to every task. A build definition must declare an xx_secrets dependency for the tasks that need them:
load("@os@1", "os_run")
load("@secrets@1", "xx_secrets")
secrets = xx_secrets(filter = ["API_TOKEN"])
os_run(("tools/deploy",), deps = [secrets])
The dependency adds the selected values to the dependent task's environment. Use environment-variable names for keys that tasks load, and include only the secrets that the task needs. See the xx_secrets Starlark API for filtering rules and argument details.
Environment variables are visible to the task and any processes that it starts. A task can also print or persist them. Treat a task that receives a secret as trusted code.
Storage and encryption
xx encrypts secret values in an application-data database. It stores the encryption key in the operating-system keyring, separate from the database. The database contains project paths and secret names, so encryption protects values rather than all metadata.
Run xx secrets db to print the database path. The default locations are:
| Operating system | Database path |
|---|---|
| Linux | $XDG_DATA_HOME/xx/secrets.db, or $HOME/.local/share/xx/secrets.db when XDG_DATA_HOME is unset |
| macOS | ~/Library/Application Support/xx/secrets.db |
| Windows | %AppData%\xx\secrets.db |
A copy of the database cannot decrypt values without the matching keyring entry. If the keyring entry is lost, xx refuses to open the existing database and its values cannot be recovered. Remove the database, then set every secret again. Removing the database deletes the secrets for all local projects.