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

Environment Variables

Every server setting listed here is available three ways: as a VOUCH_-prefixed environment variable, as an equivalent --kebab-case command-line flag, and as a field in the S3 configuration document. An explicit flag beats the environment variable; S3 configuration beats both. See Configuration Sources.

A few variables the server reads are not VOUCH_-prefixed — RUST_LOG, the OTEL_* and AWS_* families, and DSQL_USER. They are listed in their relevant sections below.

Core Configuration

VariableRequiredDefaultDescription
VOUCH_RP_IDNolocalhostRelying Party ID (domain, e.g. auth.example.com). Used as the WebAuthn RP ID. The default only works for local development — set it for any real deployment, because WebAuthn credentials are bound to it and changing it later invalidates every enrolled authenticator.
VOUCH_RP_NAMENoVouchRelying Party display name shown in browser prompts and UI.
VOUCH_DATABASE_URLNosqlite:vouch.db?mode=rwcDatabase connection URL. Supports sqlite:, postgres:, and Aurora DSQL endpoints. The default creates a SQLite file in the process working directory — set it explicitly so the database does not land somewhere transient.
VOUCH_JWT_SECRETConditional(empty)JWT signing secret. Must be at least 32 characters. Must not consist of a single repeated character. Used to sign internal state tokens. Required unless VOUCH_JWT_HMAC_KMS_KEY_ID is set.
VOUCH_BASE_URLNohttps://{rp_id}Base URL for this server. Auto-derived from VOUCH_RP_ID if not set (http://localhost:{port} for local dev, https://{rp_id} for production).
VOUCH_ORG_NAMENo(none)Organization name for branding in the UI. Falls back to VOUCH_RP_NAME if not set.
VOUCH_ALLOWED_DOMAINSNo(none)Comma-separated list of allowed email domains for enrollment (e.g., example.com,corp.example.com). If not set, all domains are allowed. Normalized to lowercase.

Network

VariableRequiredDefaultDescription
VOUCH_LISTEN_ADDRNo[::]:3000Address and port to listen on. Ignored when TLS is configured — the server then binds 443 and 80 unconditionally.
VOUCH_MTLS_PORTNo8443Port for the mTLS listener used by RFC 8705 certificate-bound tokens. The listener starts automatically whenever TLS is configured; there is no flag to disable it, and a bind failure here is fatal.
VOUCH_TRUSTED_PROXIESNo(empty)Comma-separated CIDRs of trusted reverse proxies (e.g. 10.0.0.0/8). When empty, X-Forwarded-For is ignored entirely and the TCP peer is treated as the client — which behind a load balancer means every user shares one rate-limit bucket. An invalid CIDR is a fatal startup error. See Behind a Reverse Proxy.
VOUCH_EXTRA_CA_CERTSNo(none)Path to a PEM bundle of additional certificate authorities for the server’s outbound HTTPS client. Needed when your IdP, or another service the server calls, uses an internal CA. An unreadable file is a fatal startup error.

Upstream Identity Provider

Configure one or more upstream IdPs (OIDC, SAML, or any mix) as a single unified list. VOUCH_IDPS holds a comma-separated list of slugs; each slug picks up its VOUCH_IDP_<SLUG>_* variables. Slugs match [a-z0-9-]{1,32} (no leading or trailing hyphen) and must be unique.

VariableRequiredDefaultDescription
VOUCH_IDPSYes(none)Comma-separated list of IdP slugs in display order (e.g., google,entra,corp-saml). At least one slug is required; the server refuses to start otherwise.
VOUCH_IDP_<SLUG>_TYPEYes (per IdP)(none)oidc or saml.

Hyphens in slugs become underscores in variable names: a slug of corp-saml becomes VOUCH_IDP_CORP_SAML_*.

OIDC IdP (per slug)

OIDC IdPs auto-discover authorization, token, and JWKS endpoints from {issuer}/.well-known/openid-configuration at startup.

VariableRequiredDefaultDescription
VOUCH_IDP_<SLUG>_ISSUERYes(none)OIDC issuer URL (e.g., https://accounts.google.com). Must serve a valid OIDC discovery document.
VOUCH_IDP_<SLUG>_CLIENT_IDYes(none)OIDC client ID from the IdP.
VOUCH_IDP_<SLUG>_CLIENT_SECRETYes(none)OIDC client secret from the IdP.

SAML IdP (per slug)

VariableRequiredDefaultDescription
VOUCH_IDP_<SLUG>_METADATA_URLYes(none)URL to the SAML IdP metadata XML document. Fetched at server startup.
VOUCH_IDP_<SLUG>_SP_ENTITY_IDNo{VOUCH_BASE_URL}SP entity ID sent in authentication requests. Defaults to the server’s base URL.
VOUCH_IDP_<SLUG>_EMAIL_ATTRIBUTENo(auto-detect)SAML attribute name containing the user’s email address.
VOUCH_IDP_<SLUG>_DOMAIN_ATTRIBUTENo(none)SAML attribute name containing the user’s domain (for domain restriction).

Session

VariableRequiredDefaultDescription
VOUCH_SESSION_HOURSNo8Session duration in hours. After this time, the user must re-authenticate.
VOUCH_DEVICE_CODE_EXPIRESNo600Device code expiration in seconds. How long a device code remains valid during enrollment.
VOUCH_DEVICE_POLL_INTERVALNo5Device code polling interval in seconds. How frequently the CLI polls for device code completion.
VOUCH_SESSION_CACHE_MAX_CAPACITYNo10000Maximum entries in the in-memory session lookup cache.
VOUCH_SESSION_CACHE_TTL_SECSNo30How long a cached session lookup stays valid. Raising it reduces database reads; lowering it shortens the window in which a revoked session is still honored by an instance.

SSH CA

VariableRequiredDefaultDescription
VOUCH_SSH_CA_KEYNo(none)SSH CA private key content (Ed25519, OpenSSH format). Accepts either raw PEM or base64-encoded PEM — the server detects which by looking for the -----BEGIN header. If set, takes precedence over VOUCH_SSH_CA_KEY_PATH.
VOUCH_SSH_CA_KEY_PATHNo./ssh_ca_keyPath to SSH CA private key file (raw PEM). Set to an empty string to disable the SSH CA entirely. If the file does not exist, the server generates a new Ed25519 CA key and writes it to this path — see the warning below.

Warning: because a missing VOUCH_SSH_CA_KEY_PATH file causes the server to generate a new CA key, starting on a fresh or unmounted volume silently rotates your SSH CA. Every host’s TrustedUserCAKeys entry then stops matching and users cannot log in with newly issued certificates. Either provision the key file before first start, or supply the key through VOUCH_SSH_CA_KEY / VOUCH_SSH_CA_KMS_KEY_ID, which never auto-generate.

OIDC Signing

VariableRequiredDefaultDescription
VOUCH_OIDC_SIGNING_KEYNo(auto-generate)OIDC signing key content (base64-encoded PEM format, P-256 ECDSA). Used for signing access tokens and ID tokens with ES256 algorithm. If not set, an ephemeral key is generated on each server restart, and issued tokens fail verification after a restart or across instances.
VOUCH_OIDC_RSA_SIGNING_KEYNo(auto-generate)OIDC RSA signing key content (base64-encoded PEM format, RSA-3072). Used for signing ID tokens with RS256 algorithm per OIDC Core Section 3.1.3.7 and all AWS credential tokens (/v1/credentials/aws/token, serving both STS AssumeRoleWithWebIdentity and IAM Identity Center CreateTokenWithIAM). Minimum 3072-bit key enforced. If not set, an ephemeral key is generated on each server restart — AWS token verification then breaks after restarts and across multiple instances, so any deployment using the AWS integration must set this (or the KMS variant).

AWS KMS

VariableRequiredDefaultDescription
VOUCH_SSH_CA_KMS_KEY_IDNo(none)AWS KMS key ID for SSH CA signing (Ed25519). When set, overrides VOUCH_SSH_CA_KEY and VOUCH_SSH_CA_KEY_PATH.
VOUCH_OIDC_SIGNING_KMS_KEY_IDNo(none)AWS KMS key ID for OIDC token signing (P-256 ECDSA). When set, overrides VOUCH_OIDC_SIGNING_KEY.
VOUCH_OIDC_RSA_SIGNING_KMS_KEY_IDNo(none)AWS KMS key ID for OIDC RSA token signing (RSA-3072, RSASSA_PKCS1_V1_5_SHA_256). When set, overrides VOUCH_OIDC_RSA_SIGNING_KEY.
VOUCH_JWT_HMAC_KMS_KEY_IDNo(none)AWS KMS key ID for HMAC state token signing. When set, VOUCH_JWT_SECRET is not required.

DPoP

VariableRequiredDefaultDescription
VOUCH_DPOP_MAX_AGENo300Maximum age of DPoP proofs in seconds. Proofs older than this are rejected.

Cleanup & Retention

VariableRequiredDefaultDescription
VOUCH_CLEANUP_INTERVALNo15Background cleanup task interval in minutes. Set to 0 to disable automatic cleanup.
VOUCH_AUTH_EVENTS_RETENTION_DAYSNo90Retention period for authentication events in days. Events older than this are purged during cleanup.
VOUCH_OAUTH_EVENTS_RETENTION_DAYSNo90Retention period for OAuth usage and credential-issuance (aws_credential, github_credential, ssh_credential, token_exchange) events in days. Events older than this are purged during cleanup.

CORS

VariableRequiredDefaultDescription
VOUCH_CORS_ORIGINSNo(none)Comma-separated list of explicit CORS allowed origins for UI routes (e.g. https://app.example.com). Empty means same-origin only. Wildcard (*) is not supported — UI routes use credentialed cookie sessions, which are incompatible with wildcard origins per the CORS spec.

GitHub App

These variables configure the Vouch GitHub App integration for issuing GitHub tokens. The App ID, name, and key are required together for GitHub App functionality. OAuth client ID and secret are additionally needed for GitHub user authentication.

VariableRequiredDefaultDescription
VOUCH_GITHUB_APP_IDNo(none)GitHub App ID (numeric, assigned when creating the app on github.com).
VOUCH_GITHUB_APP_NAMENo(none)GitHub App name (the slug from github.com/apps/{name}).
VOUCH_GITHUB_APP_KEYNo(none)GitHub App private key (PEM format, RSA). Can use literal \n for newlines.
VOUCH_GITHUB_WEBHOOK_SECRETNo(none)GitHub webhook secret for verifying webhook signatures (HMAC-SHA256).
VOUCH_GITHUB_APP_CLIENT_IDNo(none)GitHub App Client ID for OAuth user authentication. Found in GitHub App settings (different from the numeric App ID).
VOUCH_GITHUB_APP_CLIENT_SECRETNo(none)GitHub App Client Secret for OAuth user authentication.

TLS

When both VOUCH_TLS_CERT and VOUCH_TLS_KEY are set, the server listens on port 443 (HTTPS) with an automatic HTTP-to-HTTPS redirect on port 80. The VOUCH_LISTEN_ADDR setting is ignored when TLS is configured.

VariableRequiredDefaultDescription
VOUCH_TLS_CERTNo(none)TLS certificate (base64-encoded PEM).
VOUCH_TLS_KEYNo(none)TLS private key (base64-encoded PEM). Required if VOUCH_TLS_CERT is set.

S3 Configuration

Vouch supports loading configuration from an S3 object for centralized management. S3 configuration values override environment variables.

VariableRequiredDefaultDescription
VOUCH_S3_CONFIG_BUCKETNo(none)S3 bucket name for configuration file. If set, config is loaded from S3.
VOUCH_S3_CONFIG_KEYNoconfig/vouch-server.jsonS3 object key for configuration file.
VOUCH_S3_CONFIG_REGIONNo(auto)AWS region for S3 access. Uses the default credential chain region if not set.
VOUCH_S3_CONFIG_POLL_INTERVALNo60S3 config polling interval in seconds. How frequently the server checks for configuration changes.

JWT Assertion

VariableRequiredDefaultDescription
VOUCH_JWT_ASSERTION_MAX_LIFETIMENo300Maximum lifetime (seconds) for private_key_jwt client-authentication JWT assertions (RFC 7523 §2.2 / §3). Assertions older than this are rejected.

The signing algorithm allowed for a client’s assertion depends on its FAPI 2.0 profile, not just this lifetime bound. Applications with fapi_profile = fapi2_security may only sign assertions with ES256, PS256, or EdDSA (FAPI 2.0 Section 5.4.1); other applications may additionally use RS256. Discovery’s token_endpoint_auth_signing_alg_values_supported advertises the full four-algorithm union — an application’s own profile determines which of those it may actually use. Setting fapi_profile = fapi2_security on an application whose JWKS keys are all pinned to an algorithm outside that set (e.g. every key declares "alg": "RS256") is refused with a fapi_jwks_algorithm_unsupported error, since the application would otherwise be unable to authenticate at all after the change.

Protected Resource Metadata (RFC 9728)

These optional variables configure descriptive metadata published in the OAuth 2.0 Protected Resource Metadata document at /.well-known/oauth-protected-resource.

VariableRequiredDefaultDescription
VOUCH_RESOURCE_NAMENoVouchHuman-readable name of this protected resource.
VOUCH_RESOURCE_DOCUMENTATIONNohttps://vouch.sh/docs/URL of developer documentation for this protected resource.
VOUCH_RESOURCE_POLICY_URINohttps://vouch.sh/privacy/URL of the resource’s data-use policy.
VOUCH_RESOURCE_TOS_URINohttps://vouch.sh/terms/URL of the resource’s terms of service.

Override the last three on a self-hosted deployment. Their defaults point at Vouch’s own site, so a deployment that leaves them alone publishes Vouch’s documentation, privacy policy, and terms as its own in a document clients read to learn who operates the resource. Point them at your organization’s pages.

The same applies to the /privacy and /terms UI routes, which are fixed redirects to vouch.sh. Override those at your reverse proxy if you need your own.

Vulnerability Disclosure (RFC 9116)

The server publishes a security.txt document at /.well-known/security.txt with Contact, Expires (rolling, 30 days ahead), and Canonical (built from the base URL) fields.

VariableRequiredDefaultDescription
VOUCH_SECURITY_CONTACTNosecurity@vouch.shContact email published in security.txt. Set this on a self-hosted deployment — the default routes vulnerability reports about your deployment to Vouch’s security team.

CLI Download URLs

These optional variables configure download links displayed in the server UI.

VariableRequiredDefaultDescription
VOUCH_CLI_DOWNLOAD_MACOSNo(none)CLI download URL for macOS, displayed in the server UI.
VOUCH_CLI_DOWNLOAD_LINUXNo(none)CLI download URL for Linux, displayed in the server UI.
VOUCH_CLI_DOWNLOAD_WINDOWSNo(none)CLI download URL for Windows, displayed in the server UI.

Database Tuning

VariableRequiredDefaultDescription
VOUCH_DB_MAX_CONNECTIONSNo25Maximum size of the connection pool. Multiply by your instance count when sizing PostgreSQL’s max_connections.
VOUCH_DB_MIN_CONNECTIONSNo2Minimum idle connections kept open.
VOUCH_DB_IDLE_TIMEOUT_SECSNo300How long an idle connection is kept before being closed.
VOUCH_DB_ACQUIRE_TIMEOUT_SECSNo5How long a request waits for a free connection before failing.
DSQL_USERNoadminNot VOUCH_-prefixed. Database username for Aurora DSQL when the connection URL carries none.

Authenticator Policy

VariableRequiredDefaultDescription
VOUCH_ALLOWED_AAGUIDSNo(empty — any)Which authenticator models may enroll, matched against the model named in the attestation certificate. Accepts fips-only, yubikey-5, or a comma-separated list of AAGUID UUIDs. Empty means any authenticator with a valid attestation chain. A non-UUID entry is a fatal startup error.

Regardless of these settings, software authenticators are always rejected: the none attestation format is refused, so only hardware-backed credentials can enroll. See Security Hardening.

Observability

VariableRequiredDefaultDescription
VOUCH_LOG_FORMATNotextLog output format: text or json. Any other value is a fatal startup error.
VOUCH_METRICS_BEARER_TOKENNo(none)Bearer token protecting GET /metrics. When unset, the metrics endpoint is not registered at all.
RUST_LOGNoinfoNot VOUCH_-prefixed. Standard EnvFilter directive, e.g. info,vouch_server=debug.
OTEL_EXPORTER_OTLP_ENDPOINTNo(none)Not VOUCH_-prefixed. OTLP/gRPC collector endpoint. When unset, span export is disabled entirely. When set but unreachable at startup, the server fails to start.
OTEL_SERVICE_NAMENovouch-serverNot VOUCH_-prefixed. Service name attached to exported spans.

See Monitoring and Metrics.

AWS Environment

These are read by the AWS SDK or by Vouch’s AWS-specific resolution logic. None are VOUCH_-prefixed.

VariableUsed for
AWS_REGION / AWS_DEFAULT_REGIONRegion for KMS and S3, and for resolving dsql_endpoints
AWS_AZAvailability zone, checked first when resolving dsql_endpoints
AWS_PARTITIONPartition segment (aws, aws-us-gov) when building cross-account KMS ARNs
AWS_USE_FIPS_ENDPOINTWhether AWS SDK clients (S3, KMS) use FIPS endpoints

On EC2, AWS_REGION, AWS_AZ, and AWS_PARTITION fall back to IMDS (placement/region, placement/availability-zone, services/partition) when unset — see EC2 instance bootstrap below. AWS_PARTITION has no IMDS equivalent on older instance generations (services/partition 404s), in which case cross-account KMS ARN construction is skipped.

EC2 Instance Bootstrap

On EC2, vouch-server performs its own bootstrap at startup before building ServerConfig: it reads the region, availability zone, and partition from IMDSv2, then fetches a KEY=VALUE configuration blob from AWS Systems Manager Parameter Store (ssm:GetParameter with decryption) and applies it as a config layer strictly below CLI flags and process environment variables — an explicit --flag or a real env var always wins over the parameter; only variables the operator hasn’t already set are filled in.

  • Parameter name. Read from the VouchConfigParameter EC2 instance tag (requires the instance to have been launched with --metadata-options 'InstanceMetadataTags=enabled'). The tag is the opt-in: when it is not visible, the SSM fetch is skipped and the server keeps only the IMDS-derived instance facts, starting from CLI flags and process environment.
  • Format. Strict KEY=VALUE lines, one per line, with # comments and blank lines allowed — the same format systemd’s EnvironmentFile= accepts. No export prefix, no CRLF line endings, no quoted values; any of these is a hard startup error rather than a silent misparse.
  • Scope. Only variables backed by a vouch-server CLI flag (every VOUCH_* variable in this reference, plus AWS_REGION/AWS_AZ/AWS_PARTITION/ AWS_USE_FIPS_ENDPOINT) are read from the parameter. Anything else in the blob (for example a stray RUST_LOG) is ignored, since it was never real process environment to begin with. In particular, use AWS_REGION — not AWS_DEFAULT_REGION — in the parameter: the alias is honored only as a real environment variable, and inside the blob it is ignored in favor of the IMDS-derived region.
  • Never running on EC2 (IMDS unreachable), or AWS_EC2_METADATA_DISABLED=true. Bootstrap is skipped entirely and the server starts from CLI flags and process environment only, same as a non-EC2 deployment.
  • On EC2 but the SSM call fails. This is treated as a startup failure (never a silent fallback to an unconfigured server) — the log records a VOUCH_BOOTSTRAP_FAILED line naming the parameter and region. The unit’s Restart=always retries transient failures (e.g. SSM throttling); a persistent failure means the instance never becomes healthy, which an Auto Scaling Group replaces.
  • Already configured via env/CLI. If the S3 config bucket is already set (the VOUCH_S3_CONFIG_BUCKET variable or the --s3-config-bucket flag), the IMDS probe is skipped entirely, so non-EC2 and fully env-configured deployments pay nothing.

Test Mode

VariableRequiredDefaultDescription
VOUCH_CERTIFICATION_TEST_TOKENNo(none)Never set in production. Enables OpenID conformance test mode: registers a login-bypass route, disables all rate limiting, and relaxes the requirement for an upstream IdP. The server logs a security warning at startup when it is set.

Startup Validation

The server refuses to start when any of the following holds. Each produces a message naming the offending variable.

ConditionMessage
VOUCH_IDPS empty or unsetNo upstream IdP configured. Set VOUCH_IDPS=<slug>[,<slug>...]
A slug fails [a-z0-9-]{1,32}, or leads/trails with a hyphenInvalid provider slug
Two IdPs share a slugDuplicate IdP slug '<id>'
A per-IdP variable is missing (_TYPE, or OIDC _ISSUER/_CLIENT_ID/_CLIENT_SECRET, or SAML _METADATA_URL)Names the missing variable
VOUCH_IDP_<SLUG>_TYPE is neither oidc nor samlInvalid type
An IdP’s OIDC discovery or SAML metadata fetch failsFailed to configure IdP '<id>'
Only one of VOUCH_TLS_CERT / VOUCH_TLS_KEY is setPartial TLS configuration: set both ... or neither.
VOUCH_JWT_SECRET under 32 characters, and no KMS HMAC keyVOUCH_JWT_SECRET must be at least 32 characters
VOUCH_JWT_SECRET is a single repeated charactermust not consist of a single repeated character
Either retention variable is negativeNegative retention rejected
VOUCH_CORS_ORIGINS contains *Wildcard is invalid with credentialed cookie sessions
VOUCH_ALLOWED_AAGUIDS has a non-UUID entryInvalid VOUCH_ALLOWED_AAGUIDS
VOUCH_LOG_FORMAT is not text or jsonInvalid VOUCH_LOG_FORMAT
VOUCH_TRUSTED_PROXIES has a malformed CIDRInvalid CIDR in VOUCH_TRUSTED_PROXIES
VOUCH_EXTRA_CA_CERTS file is unreadableRead failure
VOUCH_DATABASE_URL scheme is not sqlite:/postgres:/postgresql:Unsupported scheme
A KMS key ID is set but the KMS client cannot be builtNames the key
S3 configuration is enabled but the object cannot be fetched or parsedFailed to fetch S3 configuration
Issuer subdomains are claimed but document encryption is not configuredissuer subdomains are claimed but document encryption is not configured
The mTLS listener cannot bindFailed to start mTLS listener

A JWT secret with fewer than 8 distinct bytes produces a warning, not an error.

See Troubleshooting for what to do about each.

Localization

The server negotiates the response language per request from the Accept-Language header and the OIDC ui_locales parameter. There is no server-side environment variable for it, and no configuration is required.

The vouch CLI resolves its own language separately, from --lang, VOUCH_LANG, and the standard POSIX locale variables. That is client-side; see vouch.sh/docs.