Skip to content

Secret Generation

Secrets can be declared with type and generate to be auto-generated when missing. This is useful for passwords, tokens, and keys that do not need to be shared across developers.

[profiles.default]
DB_PASSWORD = { description = "Database password", type = "password", generate = true }
API_TOKEN = { description = "API token", type = "hex", generate = { bytes = 32 } }
SESSION_KEY = { description = "Session key", type = "base64", generate = { bytes = 64 } }
REQUEST_ID = { description = "Request ID prefix", type = "uuid", generate = true }
TypeDefault OutputOptions
password32 alphanumeric charslength (int), charset ("alphanumeric" or "ascii")
hex64 hex chars (32 bytes)bytes (int)
base6444 chars (32 bytes)bytes (int)
uuidUUID v4 (36 chars)none
commandstdout of commandcommand (string, required)
rsa_private_key2048-bit RSA private key (PKCS1 PEM)bits (int)
openpgp_private_key (0.21+)ASCII-armored OpenPGP transferable secret keyuser_id (required), algorithm ("ed25519" or "rsa"), bits (RSA only), capabilities (["sign"], ["encrypt"], or both)
ssh_private_key (0.21+)Unencrypted OpenSSH Ed25519 private keyalgorithm ("ed25519" or "rsa"), bits (RSA only), comment (string)

The command type runs a shell command and uses its stdout as the generated value:

MONGO_KEY = { description = "MongoDB keyfile", type = "command", generate = { command = "openssl rand -base64 765" } }

command requires generate = { command = "..." } rather than just generate = true.

openpgp_private_key generates a GnuPG-compatible OpenPGP v4 key entirely in process; neither gpg nor another executable is required. Its modern default uses an Ed25519 certification-only primary key and puts routine operations on separate Ed25519 signing and Curve25519 encryption subkeys.

The User ID is required. With no capabilities, SecretSpec creates both signing and encryption subkeys:

[profiles.default]
GENERAL_KEY = { description = "Service OpenPGP key", type = "openpgp_private_key", generate = { user_id = "Service Bot <service@example.com>" } }
# A signing-only key has no encryption subkey.
RELEASE_KEY = { description = "Release signing key", type = "openpgp_private_key", generate = { user_id = "Release Bot <releases@example.com>", capabilities = ["sign"] } }
# RSA is available for consumers that require it; 3072 bits is the default.
LEGACY_KEY = { description = "Legacy-compatible OpenPGP key", type = "openpgp_private_key", generate = { user_id = "Legacy Bot <legacy@example.com>", algorithm = "rsa", bits = 4096 } }

capabilities must be a non-empty list containing "sign", "encrypt", or both without duplicates. algorithm defaults to "ed25519". Selecting "rsa" uses RSA for the primary key and every requested subkey; bits defaults to 3072 and accepts values from 2048 through 8192. bits is invalid with "ed25519".

The result is one -----BEGIN PGP PRIVATE KEY BLOCK----- value that can be imported by GnuPG and other OpenPGP tools. It has no OpenPGP passphrase and no expiration; protect it with an encrypted provider and rotate it according to the consuming system’s policy. Set as_path = true when a command needs a temporary key file rather than the armored value in an environment variable.

ssh_private_key generates an unencrypted OpenSSH private key entirely in process. generate = true uses Ed25519, the sensible default for new SSH keys:

[profiles.default]
DEPLOY_KEY = { description = "Deployment SSH key", type = "ssh_private_key", generate = true }
# RSA is available for compatibility; 3072 bits is the default.
LEGACY_DEPLOY_KEY = { description = "Legacy deployment key", type = "ssh_private_key", generate = { algorithm = "rsa", bits = 4096, comment = "deploy@example.com" } }

RSA sizes from 2048 through 8192 bits are accepted. bits is invalid with Ed25519. comment is optional and cannot contain control characters. Generated keys are not passphrase-encrypted, so store them in an encrypted provider. Set as_path = true when a command needs the key in a temporary file rather than in an environment variable.

  • Generation only triggers when a secret is missing. Existing secrets are never overwritten.
  • Generated values are stored via the secret’s configured provider (or the default provider).
  • Subsequent runs find the stored value and skip generation (idempotent).
  • The null provider (0.19+) instead returns a fresh generated value for only the current resolution.
  • generate and default cannot both be set on the same secret.
  • Setting type without generate is informational only and does not trigger auto-generation.

Use providers = ["null"] when the value should be generated on demand and never written to provider storage:

[profiles.default]
SESSION_SECRET = { description = "Per-run session secret", type = "base64", generate = { bytes = 32 }, providers = ["null"] }

One materializing resolution receives one value. The next run, get, check, or SDK value-carrying resolution receives a new one. Value-free reports describe the value as generated without minting it. Use a writable provider instead when another process or later invocation must retrieve the same value.

[profiles.default]
# Auto-generated on first run, reused after that
DB_PASSWORD = { description = "Database password", type = "password", generate = true }
# Custom length and character set
ADMIN_PASSWORD = { description = "Admin password", type = "password", generate = { length = 64, charset = "ascii" } }
# 64-byte key encoded as base64
ENCRYPTION_KEY = { description = "Encryption key", type = "base64", generate = { bytes = 64 } }
# RSA private key (default 2048-bit)
JWT_SIGNING_KEY = { description = "JWT signing key", type = "rsa_private_key", generate = true }
# RSA private key with custom key size
TLS_KEY = { description = "TLS private key", type = "rsa_private_key", generate = { bits = 4096 } }
# OpenPGP signing key (requires SecretSpec 0.21+)
RELEASE_KEY = { description = "Release signing key", type = "openpgp_private_key", generate = { user_id = "Release Bot <releases@example.com>", capabilities = ["sign"] } }
# OpenSSH Ed25519 private key (requires SecretSpec 0.21+)
DEPLOY_KEY = { description = "Deployment SSH key", type = "ssh_private_key", generate = true }
# Informational type only, no generation
EXTERNAL_API_KEY = { description = "Provided by vendor", type = "password" }

See the configuration reference for the full specification.