secretumvault/docs/user-guide/configuration.md
2025-12-26 15:13:36 +00:00

14 KiB

Configuration Reference

Complete guide to SecretumVault configuration via svault.toml.

Quick Start Configuration

Minimal working configuration:

[vault]
crypto_backend = "openssl"

[server]
address = "0.0.0.0"
port = 8200

[storage]
backend = "etcd"

[storage.etcd]
endpoints = ["http://localhost:2379"]

[seal]
seal_type = "shamir"
threshold = 2
shares = 3

[engines.kv]
path = "secret/"
versioned = true

[logging]
level = "info"
format = "json"

[telemetry]
prometheus_port = 9090

[auth]
default_ttl = 24

[vault] Section

Global vault settings.

[vault]
# Crypto backend: "openssl" (stable) | "aws-lc" (PQC ready) | "rustcrypto" (planned)
crypto_backend = "openssl"

Options

Option Type Default Description
crypto_backend string "openssl" Cryptographic backend for encrypt/decrypt/sign operations

Valid Values

  • openssl - OpenSSL backend with classical crypto (RSA, ECDSA)
  • aws-lc - AWS-LC with post-quantum support (requires feature aws-lc)
  • rustcrypto - Pure Rust implementation (requires feature rustcrypto)

Example

[vault]
crypto_backend = "aws-lc"  # Enable AWS-LC with ML-KEM, ML-DSA

[server] Section

HTTP server configuration.

[server]
# Binding address
address = "0.0.0.0"

# Port for API
port = 8200

# TLS certificate (optional)
# tls_cert = "/etc/secretumvault/tls.crt"

# TLS private key (optional)
# tls_key = "/etc/secretumvault/tls.key"

# Client CA for mTLS (optional)
# tls_client_ca = "/etc/secretumvault/client-ca.crt"

Options

Option Type Default Description
address string "0.0.0.0" IP address to bind to
port integer 8200 Port for HTTP/HTTPS
tls_cert string null Path to TLS certificate file
tls_key string null Path to TLS private key
tls_client_ca string null Path to client CA certificate for mTLS

Examples

Development (HTTP only):

[server]
address = "127.0.0.1"
port = 8200

Production (HTTPS):

[server]
address = "0.0.0.0"
port = 8200
tls_cert = "/etc/secretumvault/tls.crt"
tls_key = "/etc/secretumvault/tls.key"

With mTLS:

[server]
address = "0.0.0.0"
port = 8200
tls_cert = "/etc/secretumvault/tls.crt"
tls_key = "/etc/secretumvault/tls.key"
tls_client_ca = "/etc/secretumvault/client-ca.crt"

[storage] Section

Backend storage configuration.

[storage]
backend = "etcd"  # etcd | surrealdb | postgresql | filesystem

[storage.etcd]
endpoints = ["http://localhost:2379"]
# username = "vault"  # optional
# password = "secret"  # optional

[storage.surrealdb]
url = "ws://localhost:8000"
# password = "secret"  # optional

[storage.postgresql]
connection_string = "postgres://vault:secret@localhost:5432/secretumvault"

[storage.filesystem]
path = "/var/lib/secretumvault/data"

Backend Options

etcd

[storage]
backend = "etcd"

[storage.etcd]
# List of etcd endpoints
endpoints = ["http://localhost:2379"]

# Authentication (optional)
# username = "vault"
# password = "secret"

# Key prefix for vault keys (optional, default "/vault/")
# prefix = "/secretumvault/"

SurrealDB

[storage]
backend = "surrealdb"

[storage.surrealdb]
# WebSocket URL
url = "ws://localhost:8000"

# Namespace (optional, default "vault")
# namespace = "secretumvault"

# Database (optional, default "secrets")
# database = "vault_db"

# Authentication
# username = "vault"
# password = "secret"

PostgreSQL

[storage]
backend = "postgresql"

[storage.postgresql]
# Standard PostgreSQL connection string
connection_string = "postgres://vault:password@localhost:5432/secretumvault"

# Or individual components
# host = "localhost"
# port = 5432
# username = "vault"
# password = "secret"
# database = "secretumvault"

Filesystem

[storage]
backend = "filesystem"

[storage.filesystem]
# Directory for storing secrets (will be created if missing)
path = "/var/lib/secretumvault/data"

Example Configurations

High Availability (etcd):

[storage]
backend = "etcd"

[storage.etcd]
endpoints = [
  "http://etcd-1.example.com:2379",
  "http://etcd-2.example.com:2379",
  "http://etcd-3.example.com:2379"
]
username = "vault"
password = "${ETCD_PASSWORD}"

Production (PostgreSQL):

[storage]
backend = "postgresql"

[storage.postgresql]
connection_string = "postgres://vault:${DB_PASSWORD}@db.example.com:5432/secretumvault"

[crypto] Section

Cryptographic backend configuration.

[crypto]
# Backend-specific settings (if any)
# Currently unused, reserved for future extensions

[seal] Section

Seal/unseal mechanism configuration.

[seal]
# Type: "shamir" (Shamir Secret Sharing) | "auto" (planned)
seal_type = "shamir"

[seal.shamir]
# Number of unseal keys to generate
shares = 5

# Number of keys needed to unseal (threshold)
threshold = 3

Shamir Secret Sharing (SSS)

Splits master key into shares keys, requiring threshold to reconstruct.

Config Meaning Example
shares = 5, threshold = 3 5 keys generated, need 3 to unseal Most common
shares = 3, threshold = 2 3 keys, need 2 (faster unsealing) Small teams
shares = 7, threshold = 4 7 keys, need 4 (higher security) Large organizations

Example

[seal]
seal_type = "shamir"

[seal.shamir]
shares = 5
threshold = 3

Unsealing: Run POST /v1/sys/unseal 3 times with 3 different keys.


[engines] Section

Secrets engines to mount.

Each engine has:

  • path - Mount point (e.g., "secret/", "transit/")
  • versioned - Support multiple versions (KV, Transit only)

KV Engine

[engines.kv]
# Mount at /v1/secret/
path = "secret/"

# Support versioning: read past versions, restore, etc.
versioned = true

Transit Engine

[engines.transit]
# Mount at /v1/transit/
path = "transit/"

# Support key versioning and rotation
versioned = true

PKI Engine

[engines.pki]
# Mount at /v1/pki/
path = "pki/"

# PKI doesn't support versioning
versioned = false

Database Engine

[engines.database]
# Mount at /v1/database/
path = "database/"

# Database dynamic secrets don't support versioning
versioned = false

Complete Example

[engines.kv]
path = "secret/"
versioned = true

[engines.transit]
path = "transit/"
versioned = true

[engines.pki]
path = "pki/"
versioned = false

[engines.database]
path = "database/"
versioned = false

Then access at:

  • GET /v1/secret/data/myapp - KV read
  • POST /v1/transit/encrypt/key - Transit encrypt
  • POST /v1/pki/issue/role - PKI issue
  • POST /v1/database/config/postgres - Database config

[logging] Section

Structured logging configuration.

[logging]
# Level: "trace" | "debug" | "info" | "warn" | "error"
level = "info"

# Format: "json" | "pretty"
format = "json"

# Output: "stdout" | "stderr" | file path
output = "stdout"

# ANSI colors (for pretty format)
ansi = true

Options

Option Type Values Default
level string trace, debug, info, warn, error "info"
format string json, pretty "json"
output string stdout, stderr, file path "stdout"
ansi bool true, false true

Examples

Development (Human-readable):

[logging]
level = "debug"
format = "pretty"
output = "stdout"
ansi = true

Production (JSON logs):

[logging]
level = "info"
format = "json"
output = "stdout"
ansi = false

To file:

[logging]
level = "info"
format = "json"
output = "/var/log/secretumvault/vault.log"

[telemetry] Section

Observability and metrics configuration.

[telemetry]
# Port for Prometheus metrics endpoint
prometheus_port = 9090

# Enable distributed tracing (future)
enable_trace = false

Options

Option Type Default Description
prometheus_port integer 9090 Port for /metrics endpoint
enable_trace bool false Enable OpenTelemetry tracing (planned)

Metrics Endpoint

With prometheus_port = 9090:

curl http://localhost:9090/metrics

Returns Prometheus-format metrics:

  • vault_secrets_stored_total - Secrets stored
  • vault_secrets_read_total - Secrets read
  • vault_operations_encrypt - Encryption ops
  • vault_tokens_created - Tokens created

Prometheus Scrape Config

scrape_configs:
  - job_name: 'vault'
    static_configs:
      - targets: ['localhost:9090']
    scrape_interval: 10s

[auth] Section

Authentication and authorization configuration.

[auth]
# Default token TTL in hours
default_ttl = 24

# Cedar policies directory
# cedar_policies_dir = "/etc/secretumvault/policies"

# Cedar entity entities file (optional)
# cedar_entities_file = "/etc/secretumvault/entities.json"

Options

Option Type Default Description
default_ttl integer 24 Token lifetime in hours
cedar_policies_dir string null Directory containing .cedar policy files
cedar_entities_file string null JSON file with Cedar entities

Cedar Policies

Load policies from directory:

mkdir -p /etc/secretumvault/policies

cat > /etc/secretumvault/policies/admin.cedar <<'EOF'
permit (
  principal == User::"admin",
  action,
  resource
);
EOF

cat > /etc/secretumvault/policies/readers.cedar <<'EOF'
permit (
  principal,
  action == Action::"read",
  resource == Secret::*
) when {
  principal has policies &&
  principal.policies.contains("reader")
};
EOF

Config:

[auth]
default_ttl = 24
cedar_policies_dir = "/etc/secretumvault/policies"

Cedar Entities

Define attributes for principals and resources:

{
  "User::alice": {
    "policies": ["admin", "reader"],
    "department": "engineering"
  },
  "User::bob": {
    "policies": ["reader"],
    "department": "finance"
  },
  "Secret::secret/database": {
    "sensitivity": "high",
    "owner": "engineering"
  }
}

Config:

[auth]
cedar_entities_file = "/etc/secretumvault/entities.json"

Environment Variable Substitution

Use environment variables in configuration:

[storage.postgresql]
connection_string = "postgres://vault:${DB_PASSWORD}@db.example.com:5432/vault"

[storage.surrealdb]
password = "${SURREAL_PASSWORD}"

[storage.etcd]
username = "${ETCD_USER}"
password = "${ETCD_PASSWORD}"

At startup:

export DB_PASSWORD="secret123"
export SURREAL_PASSWORD="surrealpass"
export ETCD_USER="vault"
export ETCD_PASSWORD="etcdpass"

cargo run -- server --config svault.toml

Or in Docker:

docker run -e DB_PASSWORD=secret123 secretumvault:latest server --config svault.toml

Complete Production Configuration

[vault]
crypto_backend = "aws-lc"

[server]
address = "0.0.0.0"
port = 8200
tls_cert = "/etc/secretumvault/tls.crt"
tls_key = "/etc/secretumvault/tls.key"
tls_client_ca = "/etc/secretumvault/client-ca.crt"

[storage]
backend = "postgresql"

[storage.postgresql]
connection_string = "postgres://vault:${DB_PASSWORD}@db.prod.internal:5432/secretumvault"

[seal]
seal_type = "shamir"

[seal.shamir]
shares = 5
threshold = 3

[engines.kv]
path = "secret/"
versioned = true

[engines.transit]
path = "transit/"
versioned = true

[engines.pki]
path = "pki/"
versioned = false

[engines.database]
path = "database/"
versioned = false

[logging]
level = "info"
format = "json"
output = "stdout"
ansi = false

[telemetry]
prometheus_port = 9090
enable_trace = true

[auth]
default_ttl = 24
cedar_policies_dir = "/etc/secretumvault/policies"
cedar_entities_file = "/etc/secretumvault/entities.json"

Configuration Validation

Vault validates configuration at startup:

Config Loading
  ↓
Parse TOML
  ↓
Validate backends available
  ↓
Check path collisions (no duplicate mount paths)
  ↓
Validate seal config (threshold ≤ shares)
  ↓
Check required fields
  ↓
Success: Start vault

If validation fails, vault exits with error message.


Configuration Changes

Static Configuration

Configuration is loaded once at startup. To change:

  1. Edit svault.toml
  2. Restart vault process
  3. Re-unseal vault with keys

Hot Reload (Planned)

Future versions may support:

  • Token policy updates without restart
  • Log level changes
  • Metrics port changes

For now, restart is required.


Troubleshooting

"Unknown backend: xyz"

Cause: Backend name doesn't exist or feature not enabled

Solution:

# Check available backends
grep "backend =" svault.toml

# Verify feature enabled
cargo build --features etcd-storage,postgresql-storage

"Duplicate mount path"

Cause: Two engines configured at same path

Solution:

# Wrong:
[engines.kv]
path = "secret/"

[engines.transit]
path = "secret/"  # Conflict!

# Correct:
[engines.kv]
path = "secret/"

[engines.transit]
path = "transit/"

"Invalid seal config: threshold > shares"

Cause: Need more keys than generated

Solution:

# Wrong:
[seal.shamir]
shares = 3
threshold = 5  # Can't need 5 keys when only 3 exist!

# Correct:
[seal.shamir]
shares = 5
threshold = 3  # threshold ≤ shares

"Failed to connect to storage"

Cause: Backend endpoint wrong or unreachable

Solution:

# Test connectivity
curl http://localhost:2379/health  # etcd
curl ws://localhost:8000           # SurrealDB
psql postgres://user:pass@host/db  # PostgreSQL

For deployment-specific configuration, see Deployment Guide