# Certctl Configuration Example # Copy this file to .env and configure for your environment # DO NOT commit .env with real secrets to version control # ============================================================================== # PostgreSQL (used by Docker Compose for the postgres container) # ============================================================================== POSTGRES_DB=certctl POSTGRES_USER=certctl POSTGRES_PASSWORD=replace-with-openssl-rand-hex-32 # ============================================================================== # Certctl Server # All server vars use the CERTCTL_ prefix (see internal/config/config.go) # ============================================================================== # IMPORTANT: keep the password segment of CERTCTL_DATABASE_URL in sync with # POSTGRES_PASSWORD above. If you deploy via `deploy/docker-compose.yml`, # this value is *overridden* by the compose file's # `postgres://certctl:${POSTGRES_PASSWORD:-certctl}@postgres:5432/...` # interpolation — but if you run the binary directly with this .env loaded # (e.g. `set -a; source .env; ./certctl-server`), update *both* lines. # Background: editing POSTGRES_PASSWORD after the postgres data directory # has been initialized once does NOT rotate the password — initdb only # seeds pg_authid on first boot of an empty volume. See docs/quickstart.md # "Warning" callout and `internal/repository/postgres/db.go::wrapPingError` # for the SQLSTATE 28P01 diagnostic that fires when the two drift. CERTCTL_DATABASE_URL=postgres://certctl:replace-with-openssl-rand-hex-32@postgres:5432/certctl?sslmode=disable CERTCTL_SERVER_HOST=0.0.0.0 CERTCTL_SERVER_PORT=8443 CERTCTL_LOG_LEVEL=info CERTCTL_LOG_FORMAT=json # Auth type: "api-key" (production), "none" (demo/development), or # "oidc" (Auth Bundle 2 - native OIDC SSO via coreos/go-oidc/v3, ships # in Bundle 2 phases 5+6; setting CERTCTL_AUTH_TYPE=oidc on a build # without Bundle 2 wired triggers a clear refuse-to-start error rather # than a silent fallback to api-key). For JWT / SAML / LDAP, continue to # run an authenticating gateway in front of certctl (oauth2-proxy / # Envoy ext_authz / Traefik ForwardAuth / Pomerium) and set # CERTCTL_AUTH_TYPE=none on the upstream - see docs/architecture.md # "Authenticating-gateway pattern". G-1 removed the in-process "jwt" # option (no JWT middleware shipped - silent auth downgrade); see # docs/upgrade-to-v2-jwt-removal.md if you previously set # CERTCTL_AUTH_TYPE=jwt. # # Bundle 2 closure (2026-05-12): the docker-compose base file no longer # defaults to AUTH_TYPE=none. The base ships production-shaped; the demo # overlay (deploy/docker-compose.demo.yml) flips this baseline into the # populated-dashboard demo path. CERTCTL_AUTH_TYPE=api-key # Required when CERTCTL_AUTH_TYPE is "api-key". Generate with: # openssl rand -base64 32 # The Bundle 2 fail-closed Validate() REFUSES TO START if this value # equals the placeholder string "change-me-in-production" outside of # demo mode (CERTCTL_DEMO_MODE_ACK=true). CERTCTL_AUTH_SECRET=replace-with-openssl-rand-base64-32 # Bundle 2 closure: AES-256-GCM key for encrypting issuer/target config # secrets at rest. Required for any deployment that uses the dynamic # config GUI to store issuer credentials. Generate with: # openssl rand -base64 32 # Minimum 32 bytes. The Bundle 2 fail-closed Validate() REFUSES TO # START if this value equals the placeholder string # "change-me-32-char-encryption-key" outside of demo mode. CERTCTL_CONFIG_ENCRYPTION_KEY=replace-with-openssl-rand-base64-32 # ============================================================================== # Certctl Agent # ============================================================================== # HTTPS-only as of v2.2 (TLS 1.3 pinned). Agents reject http:// URLs at # startup. Use the docker-compose self-signed bootstrap CA bundle from # `deploy/test/certs/ca.crt` or supply your own via CERTCTL_SERVER_CA_BUNDLE_PATH. CERTCTL_SERVER_URL=https://localhost:8443 # Matches one of the server's CERTCTL_AUTH_SECRET rotation values. The # placeholder is rejected outside demo mode (Bundle 2 fail-closed guard). CERTCTL_API_KEY=replace-with-openssl-rand-base64-32 CERTCTL_AGENT_NAME=local-agent # Returned from `POST /api/v1/agents` during agent enrollment. The agent # fail-fasts at startup with "agent-id flag or CERTCTL_AGENT_ID env var # is required" if this is unset. # CERTCTL_AGENT_ID=agent-from-registration-response # ============================================================================== # Optional: Scheduler Tuning (defaults are usually fine) # ============================================================================== # CERTCTL_SCHEDULER_RENEWAL_CHECK_INTERVAL=1h # CERTCTL_SCHEDULER_JOB_PROCESSOR_INTERVAL=30s # CERTCTL_SCHEDULER_AGENT_HEALTH_CHECK_INTERVAL=2m # CERTCTL_SCHEDULER_NOTIFICATION_PROCESS_INTERVAL=1m # CERTCTL_DATABASE_MAX_CONNS=25