Skip to content

Bootstrap Settings (.env)

Bootstrap settings are loaded once at startup from the .env file (or OS environment variables if no .env is present). Changing any of these requires restarting the server.

Autentico loads .env from the current working directory.

Generate a .env with secure defaults:

Terminal window
# Production (HTTPS) — secure cookie flags default to true
./autentico init --url https://auth.example.com
# Local development (HTTP) — pass --dev to disable Secure cookie flags
./autentico init --url http://localhost:9999 --dev
Variable Default Description
AUTENTICO_APP_URL http://localhost:9999 Public base URL of the application. Used as the OIDC issuer (iss) and for constructing redirect URIs. Must match the URL clients use to reach the server.
AUTENTICO_APP_OAUTH_PATH /oauth2 URL path prefix for all OAuth2 endpoints. Change this only if you need to namespace the endpoints.
AUTENTICO_DB_FILE_PATH ./autentico.db Path to the SQLite database file. The directory must exist and be writable. Use an absolute path in production.
AUTENTICO_LISTEN_PORT (derived from APP_URL) Override the port the server binds to locally. Useful when a reverse proxy handles TLS and the public AUTENTICO_APP_URL port differs from the local bind port. Defaults to the port in AUTENTICO_APP_URL.

All secrets are generated by autentico init. In production, inject them as environment variables from a secrets manager rather than committing them to .env.

Variable Description
AUTENTICO_PRIVATE_KEY Base64-encoded RSA 2048 private key PEM. Used to sign ID tokens and access tokens (RS256). If unset, an ephemeral key is generated at startup — tokens issued with an ephemeral key are invalidated on restart.
AUTENTICO_TOTP_ENCRYPTION_KEY Required persistent base64-encoded 32-byte key for TOTP encryption. Generated by init; keep the same key for migration, restarts and restores.
AUTENTICO_ACCESS_TOKEN_SECRET HMAC secret for access token signing. Must be a strong random value (at least 32 bytes).
AUTENTICO_REFRESH_TOKEN_SECRET HMAC secret for refresh token signing. Must be a strong random value.
AUTENTICO_CSRF_SECRET_KEY 32-byte secret for CSRF token generation (gorilla/csrf). Must be stable across restarts — changing it invalidates all in-flight CSRF tokens.

The two _SECURE cookie flags default to true. They should only be set to false for local HTTP development — use autentico init --dev to generate a .env with these flags disabled.

Variable Default Description
AUTENTICO_CSRF_COOKIE_NAME _gorilla_csrf CSRF middleware cookie name; the form field and header names stay unchanged.
AUTENTICO_TRUSTED_DEVICE_COOKIE_NAME autentico_trusted_device Trusted-device cookie name, retaining its OAuth path and Strict SameSite policy.
AUTENTICO_FEDERATION_COOKIE_NAME autentico_federation Base name for the upstream-login browser binding. Adds __Host- when AUTENTICO_IDP_SESSION_SECURE=true.
AUTENTICO_PASSKEY_REGISTRATION_COOKIE_NAME autentico_passkey_registration Base name for the passkey-registration binding. Adds __Host- when AUTENTICO_CSRF_SECURE_COOKIE=true.
AUTENTICO_FORWARD_AUTH_COOKIE_PREFIX autentico_fa_ Reserved prefix for app sessions and pending login cookies; app IDs and transaction state are appended. Adds __Host- for HTTPS app origins.
AUTENTICO_CSRF_SECURE_COOKIE true Adds the Secure flag to the CSRF cookie. Set to false only when running over plain HTTP (local development).
AUTENTICO_IDP_SESSION_COOKIE_NAME autentico_idp_session Cookie name for the IdP SSO session.
AUTENTICO_IDP_SESSION_SECURE true Adds the Secure flag to the IdP session cookie. Set to false only for local HTTP development.
AUTENTICO_REFRESH_TOKEN_COOKIE_NAME autentico_refresh_token Cookie name used when cookie-only delivery is enabled. Change if you run multiple Autentico instances under the same domain.
AUTENTICO_REFRESH_TOKEN_COOKIE_ONLY false Opt-in security enhancement. When true, the refresh token is delivered as an HttpOnly cookie instead of in the JSON response body. This prevents JavaScript (including XSS payloads) from ever reading the refresh token. Non-standard: the OIDC spec expects refresh_token in the response body, so only enable this if your client is purpose-built to read the token from the cookie rather than the JSON response.

Cookie names are bootstrap settings: set them in the process environment or .env, then restart Autentico. For the five new name/prefix settings, use a nonempty HTTP-token name of at most 128 ASCII bytes. Spaces, separators, control characters and reserved browser prefixes (__Host-, __Secure-, __Http-) are rejected at startup. Supply base names without those prefixes. Automatic __Host- naming for federation, passkey registration and HTTPS ForwardAuth retains Secure, Path=/, no Domain and HttpOnly. CSRF and trusted-device cookies retain their existing naming/security behavior; no prefix is added to them automatically. The existing IdP-session and refresh-token settings continue to use their supplied literal names.

Startup also rejects collisions involving the new effective cookie names and overlaps between the ForwardAuth prefix and fixed cookie names. Reserve the entire ForwardAuth prefix for authentication; application cookies should use different names. ForwardAuth strips configured authentication cookies and historical default names before forwarding requests to the backend.

Use distinct names for every instance sharing a hostname, for example:

AUTENTICO_IDP_SESSION_COOKIE_NAME=tenant_a_idp
AUTENTICO_REFRESH_TOKEN_COOKIE_NAME=tenant_a_refresh
AUTENTICO_CSRF_COOKIE_NAME=tenant_a_csrf
AUTENTICO_TRUSTED_DEVICE_COOKIE_NAME=tenant_a_trusted
AUTENTICO_FEDERATION_COOKIE_NAME=tenant_a_federation
AUTENTICO_PASSKEY_REGISTRATION_COOKIE_NAME=tenant_a_registration
AUTENTICO_FORWARD_AUTH_COOKIE_PREFIX=tenant_a_fa_

Changing names starts new browser authentication state. Previous names are not accepted as aliases; users should clear old cookies and sign in again. Pending login/registration flows must restart. Server-side session/device records are unchanged by a rename. Use consistent settings across replicas of the same instance.

AUTENTICO_TRUSTED_PROXIES defaults to empty: client IPs come from the network connection and X-Forwarded-For is ignored. Set a comma-separated list of IPv4 or IPv6 CIDRs to trust your reverse proxies. For a proxy on the same host:

AUTENTICO_TRUSTED_PROXIES=127.0.0.1/32,::1/128

When the connecting peer is trusted, Autentico reads X-Forwarded-For from right to left, skipping configured proxy addresses and using the first untrusted hop. Earlier values can be supplied by the client and are ignored. Invalid nearest hops, missing headers, or a chain containing only trusted proxies fall back to the network peer. X-Real-IP and Forwarded do not override this result. Rate limiting, session records and audit logs all use this address.

Configure only proxy addresses or dedicated proxy networks; leave client networks outside this list. An invalid CIDR stops startup with a configuration error. A host address needs its prefix length, such as /32 for IPv4 or /128 for IPv6.

On upgrade, deployments behind a proxy must configure this setting to retain per-client rate limits and IP records. Without it, clients behind that proxy share the proxy’s rate-limit budget. See Reverse Proxy and Docker Compose.

Per-IP token-bucket rate limiting applied to authentication and sensitive endpoints:

  • /oauth2/login
  • /oauth2/mfa and /oauth2/mfa/
  • /oauth2/passkey/login/begin and /oauth2/passkey/login/finish
  • /oauth2/forgot-password
  • /oauth2/reset-password
  • /oauth2/token (and Keycloak-compatible /oauth2/protocol/openid-connect/token)
  • /account/api/password
  • /account/api/mfa/totp (DELETE)

Two-tier limiting: a request must pass both the per-second and per-minute bucket to proceed.

Variable Default Description
AUTENTICO_RATE_LIMIT_RPS 5 Sustained request rate per IP (requests/second). Set to 0 to disable both limiters — useful when your reverse proxy already handles rate limiting.
AUTENTICO_RATE_LIMIT_BURST 10 Burst capacity for the per-second limiter. An IP can send this many requests instantly before the per-second rate applies.
AUTENTICO_RATE_LIMIT_RPM 20 Sustained request rate per IP (requests/minute). Caps long-term enumeration even when requests are spaced to avoid the per-second limit.
AUTENTICO_RATE_LIMIT_RPM_BURST 20 Burst capacity for the per-minute limiter.

Random delay added to authentication responses (/oauth2/passkey/login/*, /oauth2/forgot-password, /oauth2/resend-verification) to prevent timing-based user enumeration. The server sleeps for a random duration between the min and max values before responding.

Set both to 0 to disable — useful for profiling or when your infrastructure already mitigates timing attacks.

Variable Default Description
AUTENTICO_ANTI_TIMING_MIN_MS 50 Minimum delay in milliseconds.
AUTENTICO_ANTI_TIMING_MAX_MS 150 Maximum delay in milliseconds. Must be greater than min, otherwise the delay is disabled.
Variable Default Description
GOMAXPROCS all CPUs Standard Go environment variable that controls the maximum number of OS threads executing goroutines simultaneously. Not an Autentico setting — it is read by the Go runtime directly. Set to a lower value to reserve CPU for other processes on the same machine.
AUTENTICO_DB_READ_POOL_SIZE 0 Number of SQLite read connections in the pool. Reads run concurrently via WAL mode while writes serialize through a single connection. 0 means auto: whichever is smaller between available CPUs and 4, with a minimum of 2. On a 2-core machine you get 2 readers; on 4+ cores you get 4. Set explicitly to override (e.g. 8 for read-heavy workloads).
Variable Default Description
AUTENTICO_JWK_CERT_KEY_ID autentico-key-1 Key ID (kid) embedded in the JWK Set and JWT headers. Relying parties use this to select the correct verification key. Change if you are rotating keys.

The AppDomain, AppHost, AppPort, and AppAuthIssuer values are all derived from AUTENTICO_APP_URL — do not set them manually.

Derived value Example (from https://auth.example.com)
Domain auth.example.com
Host auth.example.com
Port 443
Auth Issuer https://auth.example.com/oauth2
AUTENTICO_APP_URL=https://auth.example.com
AUTENTICO_APP_OAUTH_PATH=/oauth2
AUTENTICO_DB_FILE_PATH=/data/autentico.db
AUTENTICO_PRIVATE_KEY=LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQo...
AUTENTICO_ACCESS_TOKEN_SECRET=change-me-to-a-strong-random-secret
AUTENTICO_REFRESH_TOKEN_SECRET=change-me-to-another-strong-random-secret
AUTENTICO_CSRF_SECRET_KEY=change-me-to-a-32-byte-random-secret
AUTENTICO_CSRF_SECURE_COOKIE=true
AUTENTICO_IDP_SESSION_SECURE=true
AUTENTICO_REFRESH_TOKEN_COOKIE_ONLY=false
# Rate limiting (set RPS=0 to disable both tiers if reverse proxy handles it)
AUTENTICO_RATE_LIMIT_RPS=5
AUTENTICO_RATE_LIMIT_BURST=10
AUTENTICO_RATE_LIMIT_RPM=20
AUTENTICO_RATE_LIMIT_RPM_BURST=20
# Anti-timing delay (set both to 0 to disable for profiling)
AUTENTICO_ANTI_TIMING_MIN_MS=50
AUTENTICO_ANTI_TIMING_MAX_MS=150
# Read pool size (0 = auto)
AUTENTICO_DB_READ_POOL_SIZE=0