Skip to main content
Unkey services read configuration from a TOML file passed at startup. Environment variables can be referenced with ${VAR} and are expanded before parsing. Defaults and validation run after parsing.

Configuration model

The config schema maps to svc/vault/config.go. Vault loads configuration via config.Load, which expands ${VAR} environment variables before parsing. Minimal config example:
http_port = 8060
region = "${UNKEY_REGION}"
instance_id = "${POD_NAME}"
bearer_token = "${UNKEY_VAULT_TOKEN}"

[encryption]
master_key = "${UNKEY_ENCRYPTION_MASTER_KEY}"

[s3]
url = "${UNKEY_S3_URL}"
bucket = "${UNKEY_S3_BUCKET}"
access_key_id = "${UNKEY_S3_ACCESS_KEY_ID}"
access_key_secret = "${UNKEY_S3_ACCESS_KEY_SECRET}"
instance_id
string
Used for tracing attributes. Set to pod name in Kubernetes. Example: vault-7d9b8c4f5d-2kq7m.
http_port
int
default:"8060"
Port for HTTP and RPC traffic. Example: 8060.
region
string
Included in logs and traces. Example: us-east-1.
bearer_token
string
required
Used for RPC auth. Must be non-empty. Example: "s3cr3t-token".

Encryption

encryption
object
required
Encryption key configuration.
Vault expects master_key values to be a base64 encoding of the serialized KeyEncryptionKey protobuf. This format is produced by the vault key generation code. Example:
[encryption]
master_key = "${UNKEY_ENCRYPTION_MASTER_KEY}"
previous_master_key = "${UNKEY_ENCRYPTION_PREVIOUS_MASTER_KEY}"

S3 storage

s3
object
required
S3-compatible storage configuration.
Example:
[s3]
url = "${UNKEY_S3_URL}"
bucket = "${UNKEY_S3_BUCKET}"
access_key_id = "${UNKEY_S3_ACCESS_KEY_ID}"
access_key_secret = "${UNKEY_S3_ACCESS_KEY_SECRET}"
Vault initializes the S3 client on startup and creates the bucket if it does not exist.

Observability

observability
object
Tracing and logging configuration. Each nested section is optional.
Vault accepts observability.metrics in the config file, but the vault runtime does not start a Prometheus endpoint. Example:
[observability.tracing]
sample_rate = 0.1

[observability.logging]
sample_rate = 0.01
slow_threshold = "2s"

Environment variables

The Helm chart provides these variables for the default config template:
UNKEY_VAULT_TOKEN
env
required
Bearer token for vault RPC auth. Example: "s3cr3t-token".
UNKEY_ENCRYPTION_MASTER_KEY
env
required
Base64-encoded master key. Example: "CiV2YXVsdC1rZXktMSIsIk9TQjRvYjBqWnU9".
UNKEY_ENCRYPTION_PREVIOUS_MASTER_KEY
env
Optional previous master key for rotation. Example: "CiV2YXVsdC1rZXktMCIsIk9TQjRvYjBqWnU9".
UNKEY_S3_URL
env
required
S3-compatible endpoint URL. Example: "https://s3.us-east-1.amazonaws.com".
UNKEY_S3_BUCKET
env
required
Bucket name for encrypted objects. Example: "unkey-vault".
UNKEY_S3_ACCESS_KEY_ID
env
required
S3 access key ID. Example: "AKIA...".
UNKEY_S3_ACCESS_KEY_SECRET
env
required
S3 access key secret. Example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCY".
UNKEY_REGION
env
Region label for observability. Example: "us-east-1".
OTEL_EXPORTER_OTLP_ENDPOINT
env
OTEL exporter endpoint. Example: "http://otel-collector.monitoring.svc.cluster.local:4318".
OTEL_EXPORTER_OTLP_PROTOCOL
env
OTEL exporter protocol. Example: "http/protobuf".

Authentication

Vault requires callers to pass an Authorization: Bearer <token> header. The token must match bearer_token from the config.

Key management and rotation

Master keys and bearer tokens are managed manually. When you rotate keys, generate a new master key and update AWS Secrets Manager. Keep the previous master key in UNKEY_ENCRYPTION_PREVIOUS_MASTER_KEY until all data is re-encrypted.

Generate a master key

From the repo root, use the Unkey CLI to generate a base64-encoded master key:
go run . dev generate-master-key
The command prints the encoded key to stdout. Store the value in AWS Secrets Manager as UNKEY_ENCRYPTION_MASTER_KEY.

Generate a bearer token

Vault accepts any non-empty bearer token. Use a strong random value and store it as UNKEY_VAULT_TOKEN:
openssl rand -base64 32
High-level flow:
  1. Generate a new master key and set it as UNKEY_ENCRYPTION_MASTER_KEY.
  2. Move the prior master key to UNKEY_ENCRYPTION_PREVIOUS_MASTER_KEY.
  3. Update AWS Secrets Manager for unkey/vault.
  4. Re-sync the Helm release to roll the vault pods.
  5. Remove UNKEY_ENCRYPTION_PREVIOUS_MASTER_KEY after re-encryption is complete.
Vault does not expose a DEK re-encryption RPC. Re-encryption requires running the internal RollDeks flow, which walks stored DEKs and rewrites them with the current master key.

Secret sources

The default Helm chart uses External Secrets to source the vault secrets from unkey/vault in AWS Secrets Manager:
UNKEY_VAULT_TOKEN
secret
required
Used for RPC authentication. Example: "s3cr3t-token".
UNKEY_ENCRYPTION_MASTER_KEY
secret
required
Base64-encoded master key. Example: "CiV2YXVsdC1rZXktMSIsIk9TQjRvYjBqWnU9".
UNKEY_ENCRYPTION_PREVIOUS_MASTER_KEY
secret
Optional key for rotation. Example: "CiV2YXVsdC1rZXktMCIsIk9TQjRvYjBqWnU9".
UNKEY_S3_URL
secret
required
S3 endpoint. Example: "https://s3.us-east-1.amazonaws.com".
UNKEY_S3_BUCKET
secret
required
Bucket name. Example: "unkey-vault".
UNKEY_S3_ACCESS_KEY_ID
secret
required
Access key ID. Example: "AKIA...".
UNKEY_S3_ACCESS_KEY_SECRET
secret
required
Access key secret. Example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCY".

Example configuration

http_port = 8060
region = "${UNKEY_REGION}"
instance_id = "${POD_NAME}"
bearer_token = "${UNKEY_VAULT_TOKEN}"

[encryption]
master_key = "${UNKEY_ENCRYPTION_MASTER_KEY}"
previous_master_key = "${UNKEY_ENCRYPTION_PREVIOUS_MASTER_KEY}"

[s3]
url = "${UNKEY_S3_URL}"
bucket = "${UNKEY_S3_BUCKET}"
access_key_id = "${UNKEY_S3_ACCESS_KEY_ID}"
access_key_secret = "${UNKEY_S3_ACCESS_KEY_SECRET}"

[observability.tracing]
sample_rate = 0.1

[observability.logging]
sample_rate = 0.01
slow_threshold = "2s"