Server Configuration¶
Use this page when you run SigID yourself or operate a SigID deployment. It is for platform engineers, SREs, and security owners who need to configure the runtime, database, networking, secrets, production guards, and observability.
For workspace launch decisions, use Launch Your Workspace. For application integration, use Add SigID Login.
Configuration Sources¶
SigID loads configuration in this order:
- built-in defaults
sigid.tomlin the working directory, or the file pointed to bySIGID_CONFIG_FILE- environment variable overrides
The repository root includes these starting points:
| File | Use |
|---|---|
sigid.example.toml |
Complete commented server configuration |
.env.example |
Local environment variable examples |
docker/sigid.org.toml |
Docker development configuration |
Environment variables use SIGID_ with __ between nested keys. For example:
DATABASE_URL is also accepted as a direct override for [database].url.
For single-tenant local development, [tenant].default_tenant_slug = "dev"
skips subdomain-based tenant resolution and routes requests to that tenant slug.
Choose a Deployment Topology¶
SigID can run as one process or as separate runtime planes.
| Topology | Use when | Configuration |
|---|---|---|
| All-in-one | Local development, small deployments, first production rollout | Keep deployment.allow_all_in_one_runtime_plane = true |
| Split plane | You want separate scaling or isolation for auth, control, and async workloads | Set deployment.allow_all_in_one_runtime_plane = false and run one process per SIGID_RUNTIME_PLANE |
The [deployment] section controls runtime shape:
| Setting | Purpose |
|---|---|
allow_all_in_one_runtime_plane |
Allows one process to serve every plane |
background_tasks_enabled |
Lets this process run background workers; disable for canary request-serving slots |
embedded_chain_monitor |
Runs chain monitoring in the server process when chain monitoring is configured |
coordination_backend |
Shared state backend: postgres, redis, or memcached |
database_topology |
Database routing mode: shared or split_by_plane |
Coordination backends use these companion sections:
| Backend | Required config | Other settings |
|---|---|---|
postgres |
No extra section; uses the configured database | Default backend |
redis |
[redis].url |
[redis].pool_size |
memcached |
[memcached].address |
pool_size, max_idle, connect_timeout_secs, command_timeout_secs |
Redis is active when deployment.coordination_backend = "redis" and
redis.url is set. Memcached is active when
deployment.coordination_backend = "memcached" and memcached.address is set.
Runtime Planes¶
Set SIGID_RUNTIME_PLANE when you run split-plane deployments.
| Value | Purpose |
|---|---|
all |
Serve all runtime planes in one process; only valid when all-in-one mode is allowed |
auth |
Authentication, OAuth, sessions, hosted login, user-facing identity routes |
control |
Management APIs, admin routes, OpenAPI docs when enabled |
async |
Background workers, event processing, async maintenance work |
When deployment.allow_all_in_one_runtime_plane = false, startup requires
SIGID_RUNTIME_PLANE=auth, SIGID_RUNTIME_PLANE=control, or
SIGID_RUNTIME_PLANE=async.
Server And Networking¶
The [server] section controls the HTTP listener, first-party origins, CORS,
proxy trust, host validation, metrics authentication, throttling, and shutdown
behavior.
| Setting | Purpose |
|---|---|
host, port |
Listen address and port |
transport |
plain_http for local/non-production, tls_h2_only for production |
base_domain |
Primary domain for cookie scoping and tenant routing |
identity_app_origin |
First-party identity app origin |
dashboard_app_origin |
First-party dashboard app origin |
allowed_hosts |
Host-header allowlist; required in production |
trusted_proxies |
Proxy IPs/CIDRs allowed to supply X-Forwarded-For |
direct_client_exposure |
Explicit acknowledgement that the process is directly exposed without a trusted proxy |
metrics_bearer_token |
Optional static bearer token for Prometheus scrapes |
endpoint_throttle |
Per-endpoint throttling rules |
request_timeout_secs |
Per-request deadline; production rejects 0 |
shutdown_deadline_secs |
Graceful shutdown deadline; production rejects 0 |
server.transport = "tls_h2_only" terminates TLS in-process and requires HTTP/2
ALPN. Configure [server.tls] with cert_pem_path and key_pem_path. Set
ca_pem_path when local clients, such as container health checks, need an
explicit trust bundle for the direct listener.
Production mode rejects server.transport = "plain_http". Local development
can still use plain HTTP.
Database¶
The [database] section configures PostgreSQL URLs, pool sizing, timeouts, and
SSL requirements.
| Setting | Purpose |
|---|---|
url |
Shared runtime database URL |
identity_url |
Required identity/session database URL |
auth_url |
Optional auth-plane database URL |
control_url |
Optional control-plane database URL |
async_url |
Optional async-plane database URL |
migration_url |
Optional migrator database URL |
maintenance_url |
Optional maintenance database URL |
max_connections, min_connections |
Default pool sizing |
connect_timeout_secs |
Database connection timeout |
idle_timeout_secs, max_lifetime_secs |
Connection recycling controls |
statement_cache_capacity |
Prepared statement cache size per connection |
test_before_acquire |
Validate pooled connections before use |
statement_timeout_secs |
Request-serving SQL statement timeout |
idle_in_transaction_timeout_secs |
Timeout for sessions idle inside transactions |
maintenance_statement_timeout_secs |
Longer timeout for maintenance operations |
require_ssl |
Require TLS for database connections |
For shared topology, set [database].url or DATABASE_URL. For split-plane
topology, set deployment.database_topology = "split_by_plane" and provide
plane URLs as needed. Missing plane URLs fall back to [database].url.
Plane-specific pool sections override pool sizing when the matching runtime plane is active:
[database.auth_pool]
max_connections = 64
min_connections = 8
[database.control_pool]
max_connections = 24
min_connections = 4
[database.async_pool]
max_connections = 16
min_connections = 2
Production mode requires database.require_ssl = true unless the database URL
explicitly includes an sslmode= parameter.
KMS And Production Secrets¶
Production deployments require sigid-kms. Without [kms], non-production
starts with ephemeral in-memory keys, which are not suitable for production.
| Setting | Purpose |
|---|---|
socket_path |
Unix socket path for the local sigid-kms service |
server_public_key_path |
Pinned Noise public key published by sigid-kms |
client_private_key_path |
This runtime's persistent Noise client private key |
Several historical secret environment variables are intentionally rejected at
startup because those secrets have moved into KMS. If startup reports that a
SIGID_* secret has moved to sigid-kms, rotate or provision it through the KMS
path instead of adding it back to the process environment.
Auth, Email, Phone, Captcha, And HIBP¶
The [auth] section controls password hashing, brute-force protection, and
registration limits.
| Setting | Purpose |
|---|---|
argon2_memory_kib |
Password hashing memory cost |
argon2_iterations, argon2_parallelism |
Password hashing time and parallelism |
argon2_max_concurrent |
Concurrent Argon2 verification limit |
brute_force_max_attempts, brute_force_lockout_secs |
Account lockout rules |
password_verify_ip_* |
IP-weighted budget for expensive password verification |
registration_rate_limit_* |
Registration rate limiting |
In production on the auth plane, startup enforces the production Argon2 throughput profile, including 64 MiB memory, one parallel lane, bounded iterations, and bounded concurrency.
Production auth-plane deployments also require:
email.provideris notlog- SMTP uses
email.smtp.starttls = truewhenemail.provider = "smtp" phone.provideris notlogcaptcha.enabled = truecaptcha.secret_keyis setcaptcha.fail_modeis notfail-openhibp.enabled = truehibp.fail_modeis notfail-open
For local development, phone.provider = "log" writes only redacted structured
logs unless [phone.log].sink is set. Supported sink values are stdout,
stderr, and file:/path/to/mailbox.ndjson; the file sink appends JSON Lines
with full SMS bodies for browserless simulations. Do not use this provider in
production.
JWT¶
The [jwt] section controls token signing defaults and token lifetimes.
| Setting | Default | Validation |
|---|---|---|
default_algorithm |
ES256 |
Must be ES256 or EdDSA |
access_token_lifetime_human_secs |
900 |
60..=86400 |
access_token_lifetime_agent_secs |
300 |
60..=86400 |
refresh_token_lifetime_human_secs |
604800 |
3600..=7776000 |
refresh_token_lifetime_agent_secs |
86400 |
3600..=7776000 |
id_token_lifetime_secs |
300 |
60..=3600 |
key_rotation_days |
30 |
1..=365 |
Refresh-token lifetimes must be greater than or equal to the matching access
token lifetime. JWT signing-key encryption is handled by sigid-kms in
production.
OIDC, First-Party Origins, And Passkeys¶
The [oidc] section defines the issuer URL and authorization code lifetime.
Production mode requires oidc.issuer_url to use HTTPS.
The [passkey] section configures WebAuthn relying-party settings. Keep the
passkey origin aligned with the browser origin that users actually visit.
The first-party origins in [server] should match the deployed identity and
dashboard frontends:
[server]
identity_app_origin = "https://identity.example.com"
dashboard_app_origin = "https://dashboard.example.com"
Feature Sections¶
Most feature modules have their own configuration section. Keep this page as the server-level map, then use feature guides for behavior and API details.
| Section | Purpose |
|---|---|
[social] |
Global social OAuth settings |
[enterprise_sso] |
Enterprise OIDC SSO state secret and callback settings |
[generic_oauth] |
Database-backed arbitrary OAuth/OIDC providers |
[phone], [sms] |
Phone/SMS OTP delivery |
[email_otp] |
Email OTP settings |
[magic_link] |
Magic link passwordless authentication |
[anonymous] |
Anonymous/guest authentication |
[two_factor] |
TOTP, backup codes, trusted devices |
[adaptive_mfa] |
Risk-based step-up authentication |
[challenge] |
Challenge nonce TTL, agent PoW difficulty, agent limits |
[device_authorization] |
RFC 8628 device flow |
[session_cookie] |
Session limits, cache cookies, binding |
[admin] |
Admin panel roles and bootstrap admin user credentials |
[access_control] |
RBAC/ABAC role, policy, and scope limits |
[proxy] |
Outbound proxy mTLS |
[oauth_proxy] |
Development-only OAuth proxy for redirect callbacks |
[wallet] |
Managed wallet signing |
[[chains]] |
Blockchain RPC configuration |
[siwe] |
Sign-In with Ethereum enablement, domain pin, and accepted EIP-155 chain IDs |
[api_keys] |
API key authentication |
[i18n] |
Localization and message catalogs |
[billing], [commerce] |
Billing, plans, checkout, and payment-of-record |
[dpop] |
DPoP sender-constrained token validation |
[organizations], [invitations], [verified_domains] |
B2B organization and domain settings |
[vault] |
Credential storage limits |
[webhooks] |
Webhook subscription limits |
[scim] |
SCIM 2.0 provisioning |
[telemetry] |
Metrics, tracing, audit batching, client telemetry |
[refresh_family_cache] |
Refresh-token family revocation cache |
[user_self_service] |
Account deletion and password-change behavior |
Observability: Health And Metrics¶
Health probes are available under /health:
| Route | Use | What it checks |
|---|---|---|
GET /health/live |
Liveness probe | Process is running |
GET /health/startup |
Startup probe | Migrations have run and signing keys are loaded |
GET /health/ready |
Readiness probe | Database, signing keys, configured chains, and critical background tasks |
The health response only exposes status. Detailed failing checks are written
to logs.
Metrics are served from GET /metrics in Prometheus format. Authentication
depends on configuration:
| Configuration | Metrics auth behavior |
|---|---|
server.metrics_bearer_token is set |
Accepts Authorization: Bearer <token> |
server.metrics_bearer_token is not set |
Requires a SigID token with metrics:read |
OpenAPI Documentation Endpoints¶
When [openapi].enabled = true, the OpenAPI router serves:
| Route | Purpose |
|---|---|
GET /openapi.json |
Raw OpenAPI JSON |
| router root | Scalar interactive API UI |
Scalar is the browser UI used to explore the generated OpenAPI specification interactively.
Treat OpenAPI as a development and internal review surface. Production mode
rejects openapi.enabled = true because it exposes the full API surface.
Environment Variable Overrides¶
Environment variables take precedence over TOML. Use generic SIGID_ overrides
for ordinary config fields:
SIGID_SERVER__ALLOWED_HOSTS='["identity.example.com","dashboard.example.com"]'
SIGID_SERVER__DIRECT_CLIENT_EXPOSURE=false
SIGID_DEPLOYMENT__DATABASE_TOPOLOGY=split_by_plane
Database URL shortcuts are also supported:
| Variable | TOML equivalent |
|---|---|
SIGID_CONFIG_FILE |
Config file path |
SIGID_RUNTIME_PLANE |
Runtime plane selection |
DATABASE_URL |
[database].url |
SIGID_DATABASE__URL |
[database].url |
DATABASE_IDENTITY_URL |
[database].identity_url |
DATABASE_AUTH_URL |
[database].auth_url |
DATABASE_CONTROL_URL |
[database].control_url |
DATABASE_ASYNC_URL |
[database].async_url |
MIGRATION_DATABASE_URL |
[database].migration_url |
MAINTENANCE_DATABASE_URL |
[database].maintenance_url |
SIGID_SECURITY__PRODUCTION |
[security].production |
SIGID_SERVER__PORT |
[server].port |
SIGID_OPENAPI__ENABLED |
[openapi].enabled |
Use SIGID_CONFIG_FILE=/path/to/sigid.toml when the config file is not in the
working directory.
Database Migrations¶
Run migrations as a separate initialization step:
Use MIGRATION_DATABASE_URL when the migrator should connect with a separate
database principal. MAINTENANCE_DATABASE_URL is optional; when it is not set,
maintenance operations fall back to the migration URL and then the runtime URL.
Production Mode¶
Set security.production = true for non-local deployments. Startup refuses to
continue when non-local indicators, such as public issuer or app origins, are
present without production mode.
Production mode enforces these server-level requirements:
| Area | Startup requirement |
|---|---|
| KMS | [kms] is configured |
| Transport | server.transport is not plain_http |
| Host validation | server.allowed_hosts is populated |
| Proxy trust | server.trusted_proxies is populated, or server.direct_client_exposure = true |
| Timeouts | server.request_timeout_secs and server.shutdown_deadline_secs are greater than 0 |
| Database | database.require_ssl = true unless the URL sets sslmode= |
| OIDC | oidc.issuer_url uses HTTPS |
| OpenAPI | openapi.enabled = false |
| OAuth proxy | oauth_proxy.enabled = false |
| Webhooks | security.webhook_allow_non_standard_ports = false |
| Auth abuse controls | CAPTCHA and HIBP are enabled and do not fail open |
| Email/phone | Providers are not log; SMTP uses STARTTLS |
Production Hardening Checklist¶
Before exposing SigID to production traffic, confirm:
security.production = truesigid-kmsis running and[kms]points to the correct socket and keysserver.transport = "tls_h2_only"is configured with the certificate and key paths required by the direct SigID listenerserver.allowed_hostscontains only expected hostnamesserver.trusted_proxiescontains only your ingress or load balancer ranges, unlessdirect_client_exposure = trueis intentionaloidc.issuer_url, identity origin, dashboard origin, and passkey origin use HTTPS- database connections require TLS through
database.require_sslor URLsslmode= - OpenAPI and OAuth proxy are disabled
- email, phone, CAPTCHA, and HIBP providers are production providers
- webhook delivery is restricted to HTTPS default ports
/health/startup,/health/ready, and/metricsare wired into your monitoring system- migrations run before traffic reaches the new version
Common Startup Errors¶
| Error includes | Meaning | Fix |
|---|---|---|
security.production must be true |
Public/non-local deployment indicators were detected without production mode | Set security.production = true and complete the production checklist |
server.transport = "plain_http" |
Production mode rejects plain HTTP direct listener | Use tls_h2_only or adjust the deployment boundary before enabling production |
server.allowed_hosts |
Host-header validation is not configured | Add expected identity, dashboard, and tenant hostnames |
trusted_proxies |
Proxy headers would be ignored or unsafe | Add trusted proxy CIDRs, or explicitly set direct_client_exposure = true |
database URL is required |
No runtime database URL was configured | Set DATABASE_URL, SIGID_DATABASE__URL, or plane-specific database URLs |
database.require_ssl |
Production database traffic is not marked TLS-protected | Set database.require_ssl = true or include sslmode= in the URL |
kms must be configured |
Production key management is missing | Configure [kms] and start sigid-kms |
openapi.enabled must be false |
OpenAPI docs are enabled in production | Disable [openapi] for production |
captcha.enabled or hibp.enabled |
Auth-plane abuse controls are missing | Configure CAPTCHA and HIBP with fail-closed behavior |
moved to sigid-kms |
A removed secret env var is still set | Provision that secret through KMS and remove the env var |
Next Steps¶
- Security And Audit for business operational controls and incident ownership
- Verify Tokens for backend authorization checks
- Webhooks for webhook receiver operations
- Billing And Production for workspace production readiness