Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

S3 Configuration Schema

For production deployments, Vouch supports loading configuration from an S3 object. This enables:

  • Centralized management — Single source of truth for multi-instance deployments
  • Dynamic updates — Configuration changes without server restart (for supported fields)
  • TLS hot-reload — Automatic certificate rotation without downtime
  • Secrets management — Leverage S3 server-side encryption and IAM for credential protection

Enabling S3 Configuration

Set the following environment variables to enable S3-based configuration:

# Required: bucket name
VOUCH_S3_CONFIG_BUCKET=my-bucket

# Optional: object key (default: config/vouch-server.json)
VOUCH_S3_CONFIG_KEY=config/vouch-server.json

# Optional: AWS region (uses default credential chain region if not set)
VOUCH_S3_CONFIG_REGION=us-west-2

# Optional: polling interval in seconds (default: 60)
VOUCH_S3_CONFIG_POLL_INTERVAL=60

When S3 configuration is enabled, it overrides environment variables. This allows for centralized configuration management with dynamic updates.

JSON Schema

The S3 configuration file is a JSON document with the following schema:

{
  "version": 1,
  "listen_addr": "0.0.0.0:443",
  "rp_id": "vouch.example.com",
  "rp_name": "Example Corp",
  "base_url": "https://vouch.example.com",
  "database_url": "postgres://...",
  "dsql_endpoints": {
    "us-east-1": "postgres://vouch@abc123.dsql.us-east-1.on.aws/postgres"
  },
  "jwt_secret": "32+ character secret",
  "session_hours": 8,
  "org_name": "Example Corp",
  "tls": {
    "cert": "<base64-encoded PEM certificate>",
    "key": "<base64-encoded PEM private key>"
  },
  "idps": [
    {
      "id": "google",
      "type": "oidc",
      "issuer": "https://accounts.google.com",
      "client_id": "...",
      "client_secret": "..."
    },
    {
      "id": "corp-saml",
      "type": "saml",
      "metadata_url": "https://idp.example.com/saml/metadata",
      "sp_entity_id": "https://vouch.example.com",
      "email_attribute": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
      "domain_attribute": "department"
    }
  ],
  "allowed_domains": ["example.com"],
  "ssh_ca_key": "<base64-encoded PEM Ed25519 private key>",
  "ssh_ca_kms_key_id": "mrk-1234abcd5678efgh",
  "oidc_signing_key": "<base64-encoded PEM EC P-256 private key>",
  "oidc_signing_kms_key_id": "mrk-abcd1234efgh5678",
  "oidc_rsa_signing_key": "<base64-encoded PEM RSA-3072 private key>",
  "oidc_rsa_signing_kms_key_id": "mrk-rsa1234abcd5678",
  "jwt_hmac_kms_key_id": "mrk-5678abcd1234efgh",
  "document_key": {
    "kms_key_id": "mrk-<key-id>",
    "encrypted_private_key": "<base64-encoded KMS ciphertext>"
  },
  "dpop": {
    "max_age_seconds": 300
  },
  "cors_origins": ["https://app.example.com"],
  "github": {
    "app_id": 12345,
    "app_name": "my-vouch-app",
    "app_key": "<PEM RSA private key>",
    "webhook_secret": "<secret>",
    "client_id": "<oauth-client-id>",
    "client_secret": "<oauth-client-secret>"
  },
  "cleanup_interval_minutes": 15,
  "auth_events_retention_days": 90,
  "oauth_events_retention_days": 90,
  "resource_name": "Vouch",
  "resource_documentation": "https://vouch.sh/docs/",
  "resource_policy_uri": "https://vouch.sh/privacy/",
  "resource_tos_uri": "https://vouch.sh/terms/",
  "cli_download_macos": "https://example.com/vouch-macos",
  "cli_download_linux": "https://example.com/vouch-linux",
  "cli_download_windows": "https://example.com/vouch-windows",
  "device_code_expires_seconds": 600,
  "device_poll_interval_seconds": 5
}

Field Descriptions

FieldTypeDescription
versionintegerSchema version. Must be 1.
listen_addrstringAddress and port to listen on (e.g., 0.0.0.0:443).
rp_idstringRelying Party ID (domain). Used as the WebAuthn RP ID.
rp_namestringRelying Party display name for browser prompts and UI.
base_urlstringExternal base URL for the server.
database_urlstringDatabase connection URL (sqlite:, postgres:, or Aurora DSQL).
dsql_endpointsobjectRegional DSQL endpoints. Maps AWS region to full connection string.
jwt_secretstringJWT signing secret (minimum 32 characters). Not required if jwt_hmac_kms_key_id is set.
session_hoursintegerSession duration in hours.
org_namestringOrganization display name for branding in the UI.
tls.certstringTLS certificate (base64-encoded PEM).
tls.keystringTLS private key (base64-encoded PEM).
idps[]array of objectsConfigured identity providers (OIDC + SAML). Order controls login-page button order. Each entry has id, type ("oidc" or "saml"), and type-specific fields.
idps[].idstringOperator-chosen slug ([a-z0-9-]{1,32}, no leading/trailing hyphen, unique). Used in the state table, callback routing, and audit logs.
idps[].typestring"oidc" or "saml".
idps[].issuer (OIDC)stringOIDC issuer URL. The server auto-discovers endpoints.
idps[].client_id (OIDC)stringOIDC client ID from the IdP.
idps[].client_secret (OIDC)stringOIDC client secret from the IdP.
idps[].metadata_url (SAML)stringURL to the SAML IdP metadata XML document.
idps[].sp_entity_id (SAML)stringSP entity ID (defaults to base_url).
idps[].email_attribute (SAML)stringSAML attribute name for email extraction.
idps[].domain_attribute (SAML)stringSAML attribute name for domain extraction.
allowed_domainsarray of stringsAllowed email domains for enrollment.
ssh_ca_keystringSSH CA private key (base64-encoded PEM, Ed25519).
ssh_ca_kms_key_idstringAWS KMS key ID for SSH CA signing (Ed25519). Overrides ssh_ca_key.
oidc_signing_keystringOIDC signing key (base64-encoded PEM, P-256 ECDSA).
oidc_signing_kms_key_idstringAWS KMS key ID for OIDC token signing (P-256). Overrides oidc_signing_key.
oidc_rsa_signing_keystringOIDC RSA signing key (base64-encoded PEM, RSA-3072). Signs ID tokens with RS256.
oidc_rsa_signing_kms_key_idstringAWS KMS key ID for OIDC RSA signing (RSA-3072). Overrides oidc_rsa_signing_key.
jwt_hmac_kms_key_idstringAWS KMS key ID for HMAC state token signing. Overrides jwt_secret.
document_keyobjectP-384 document encryption key. Contains kms_key_id and encrypted_private_key.
dpop.max_age_secondsintegerMaximum age of DPoP proofs in seconds.
cors_originsarray of stringsCORS allowed origins.
github.app_idintegerGitHub App ID.
github.app_namestringGitHub App name (slug from github.com/apps/{name}).
github.app_keystringGitHub App private key (PEM RSA).
github.webhook_secretstringGitHub webhook secret for signature verification.
github.client_idstringGitHub App OAuth client ID.
github.client_secretstringGitHub App OAuth client secret.
cleanup_interval_minutesintegerBackground cleanup task interval in minutes.
auth_events_retention_daysintegerRetention period for authentication events in days.
oauth_events_retention_daysintegerRetention period for OAuth usage events in days.
resource_namestringHuman-readable name of this protected resource (RFC 9728). Defaults to "Vouch".
resource_documentationstringURL of developer documentation for this protected resource (RFC 9728). Defaults to "https://vouch.sh/docs/".
resource_policy_uristringURL of the resource’s data-use policy (RFC 9728). Defaults to "https://vouch.sh/privacy/".
resource_tos_uristringURL of the resource’s terms of service (RFC 9728). Defaults to "https://vouch.sh/terms/".
cli_download_macosstringCLI download URL for macOS, displayed in the server UI.
cli_download_linuxstringCLI download URL for Linux, displayed in the server UI.
cli_download_windowsstringCLI download URL for Windows, displayed in the server UI.
device_code_expires_secondsintegerDevice code expiration in seconds.
device_poll_interval_secondsintegerDevice code polling interval in seconds.

Base64 Encoding

All certificate and key fields in the S3 configuration must be base64-encoded PEM strings. To encode a PEM file:

# Encode a PEM file for S3 config
base64 -i cert.pem | tr -d '\n'

This ensures proper handling of newlines and special characters within JSON values.

Hot-Reloadable vs Startup-Only Fields

The server polls S3 at the configured interval and detects changes via ETag comparison. However, only certain fields support hot-reload without a server restart:

FieldHot-ReloadableNotes
tls.cert, tls.keyYesAutomatic reload on change
All other fieldsNoRequires server restart

Non-hot-reloadable fields include: jwt_secret, database_url, listen_addr, rp_id, rp_name, session_hours, cors_origins, allowed_domains, dpop.*, idps[], GitHub App settings, SSH CA key, OIDC signing keys, and all KMS key IDs.

Legacy blocks silently ignored: The previous top-level oidc and saml blocks (single-IdP nested objects) are no longer read by the server. They configure nothing; only entries inside the idps array are honored. See IdP Overview for the field-by-field mapping.

Changes to non-hot-reloadable fields in S3 are silently ignored. A server restart is required to apply them.

TLS Certificate Hot-Reload

Vouch supports automatic TLS certificate reloading without dropping connections:

  1. Via S3 polling — Update tls.cert and tls.key in the S3 config; the server detects the change via ETag and reloads automatically.
  2. Via SIGHUP — Send SIGHUP to the server process to reload TLS certificates.
# Manual TLS certificate reload (Unix only)
kill -SIGHUP $(pgrep vouch-server)

Note: SIGHUP only reloads TLS certificates. It does not reload any other configuration fields.