Skip to main content
Version: 1.11.0

Configuration reference

This page lists every configuration key the framework recognizes, with its default value and lifecycle. For how configuration is loaded and merged — file formats, the multi-file loader, list operators, module config — see Concepts → Configuration.

How to read this page

Precedence. Values are resolved lowest-to-highest:

struct defaults < config file(s) < NUCLEUS_* env vars

Environment variables. Every key maps to a NUCLEUS_-prefixed variable. Flat keys use one underscore (portNUCLEUS_PORT); nested keys join segments with a double underscore (databases.<alias>.urlNUCLEUS_DATABASES__<ALIAS>__URL).

Lifecycle.

TagMeaning
stableKey name and semantics are contract surfaces on the v1.x line.
transitionalSupported, but semantics may still refine before freezing.
experimentalNo compatibility guarantee yet.
removedNo longer accepted; the notes name the replacement.

To see the value every key actually resolves to in a running deployment — and which file or variable set it — use nucleus config print --effective (CLI overview).

Server

KeyDefaultLifecycleNotes
host0.0.0.0stableBind host.
port8080stableBind port.
read_timeout30sstableHTTP read timeout.
write_timeout60sstableHTTP write timeout.
idle_timeout120sstableHTTP idle timeout.
tls_cert_file""transitionalPEM certificate (chain) file. When both tls_cert_file and tls_key_file are set, App.Run serves HTTPS directly (ListenAndServeTLS); when either is empty the server speaks plain HTTP (terminate TLS at a reverse proxy instead).
tls_key_file""transitionalPEM private-key file paired with tls_cert_file.

Database

KeyDefaultLifecycleNotes
database_defaultdefaultstablePrimary DB alias used by app.DB.
databases.<alias>.urldatabases.default.url=sqlite://nucleus.dbstable + experimentalStable schemes: sqlite://, postgres://, postgresql://, mysql://; exploratory schemes: sqlserver:///mssql://, oracle://.
databases.<alias>.max_open25stablePer-alias pool max open conns (inherits primary if omitted).
databases.<alias>.max_idle5stablePer-alias pool max idle conns (inherits primary if omitted).
databases.<alias>.max_lifetime5mstablePer-alias conn max lifetime (inherits primary if omitted).

MultiSite and MultiTenant

KeyDefaultLifecycleNotes
multisite.enabledfalsestableEnable host-based site resolution.
multisite.default_sitedefaultstableFallback site when host does not match configured patterns.
multisite.sites.<site>.hosts[][]stableExact host or wildcard (*.example.com) patterns per site.
multisite.sites.<site>.databasedatabase_defaultstableDefault DB alias for the site.
multisite.sites.<site>.tenant_database_alias_template""stableOptional per-site tenant DB alias template (tenant_%s or {tenant}).
multitenant.enabledfalsestableEnable tenant resolution.
multitenant.resolversubdomainstablesubdomain or header.
multitenant.headerX-Tenant-IDstableHeader used when resolver is header.
multitenant.default_tenant""stableOptional fallback tenant id.
multitenant.require_isolated_dbtruestableSecurity-by-default guard: rejects shared DB alias routing across tenants.
multitenant.database_alias_templatetenant_%sstableGlobal tenant DB alias template (%s or {tenant}).
multitenant.tenants.<tenant>.site""stableOptional site binding for a tenant mapping.
multitenant.tenants.<tenant>.database""stableExplicit tenant DB alias mapping.

Redis and Sessions

KeyDefaultLifecycleNotes
redis_url""stableOptional Redis endpoint for queue/session features.
session_lifetime72hstableServer-side session lifetime.
session_storememorystableSupported values: memory, sql, redis.
session_redis_url""stableRedis override for session backend.
session_tablenucleus_sessionsstableSQL session table name.
session_cookie_namesessionstableSession cookie name.
session_cookie_domain""stableSession cookie domain.
session_cookie_path/stableSession cookie path.
session_cookie_securetruestableSession cookie Secure attribute. Secure-by-default — the cookie refuses to ride over plain HTTP. Local development over http:// must opt out with session_cookie_secure: false. Mirrors the CSRF cookie posture.
session_cookie_samesitelaxstableSameSite policy string.
session_idle_timeout0stableOptional idle timeout override.
session_redis_prefixnucleus:sessions:stableSession Redis key prefix.

Auth

KeyDefaultLifecycleNotes
jwt_secret""stableSingle-secret HS256 used as legacy fallback when jwt_keys is empty. Must be at least 32 bytes when set — a shorter secret is a boot error (enforced since v1.2.0; generate one with openssl rand -base64 32). Tokens carry no kid header. When jwt_keys[] is non-empty this key is ignored. See jwt_keys[] for the production multi-key path.
jwt_expiry24hstableJWT lifetime default.
jwt_issuer""stableIssuer claim (iss) stamped into every token minted by App.JWT. Used by both single-secret and multi-key managers.
jwt_keys[][]stableOrdered keyset consumed by App.New to build a *auth.JWTManager via auth.NewJWTManagerFromKeys. Each entry is a JWTKeySpec sub-object — see table below. When non-empty, jwt_secret is ignored.
jwt_current_kid""stablekid value that identifies the active signing key within jwt_keys[]. Must match one entry's kid. New tokens are signed with this key; all keyset keys remain valid for validation.

jwt_keys[] entry fields (JWTKeySpec)

Exactly one of secret_env / pem_path / pem_env must be set per entry — key material is never read from tracked config files:

FieldTypeNotes
kidstringUnique key identifier stamped in token kid header. Required.
algorithmstringHS256, RS256, or ES256. Required.
secret_envstringResolver reference to the HMAC secret (HS256 only). See reference forms below.
pem_pathstringFilesystem path to a PEM-encoded private key (RS256: RSA, PKCS#1/PKCS#8; ES256: ECDSA P-256, SEC1/PKCS#8). Rejects PEM with trailing content.
pem_envstringResolver reference to PEM bytes (RS256 / ES256). See reference forms below.

Reference forms accepted by secret_env and pem_env (plain names read the environment; the aws-sm: scheme reads AWS Secrets Manager via the standard credential chain):

ReferenceResolved from
MY_VARenvironment variable MY_VAR (historical behaviour)
env:MY_VARenvironment variable MY_VAR (explicit form)
aws-sm:<secret-id>AWS Secrets Manager secret <secret-id>
aws-sm:<secret-id>#<json-key>one string field of a JSON-object AWS secret

RBAC

KeyDefaultLifecycleNotes
rbac_policy_file""stablePath to Casbin RBAC CSV policy file. Feeds the core authz enforcer (pkg/authz.Enforcer). CSV rows require a 4th column (allow / deny) — the model uses deny-override semantics. Programmatic callers use Enforcer.AddPolicy (auto-stamps allow) and Enforcer.Deny. Auto-discovered at rbac_policy.csv, config/rbac_policy.csv, or rbac/rbac_policy.csv when the key is empty.
admin_rbac_policy_file""removedRemoved in v0.12.0. Use rbac_policy_file

Admin (removed — moved to the orbit module)

KeyFormer defaultLifecycleMigration
admin_prefix/adminremovedUse modules.orbit.prefix (see orbit module docs).
admin_titleNucleus AdminremovedUse modules.orbit.title.
admin_auth_database""removedUse modules.orbit.auth_database.
admin_bootstrap_username""removedUse modules.orbit.bootstrap_username.
admin_bootstrap_email""removedUse modules.orbit.bootstrap_email.
admin_bootstrap_password""removedUse modules.orbit.bootstrap_password.
admin_live_exclude_patterns[][/admin]removedUse modules.orbit.live_exclude_patterns.
admin_cluster_enabledfalseremovedUse modules.orbit.cluster_enabled.
admin_cluster_redis_url""removedUse modules.orbit.cluster_redis_url.
admin_cluster_channelnucleus:admin:live:v1removedUse modules.orbit.cluster_channel.
admin_cluster_node_id""removedUse modules.orbit.cluster_node_id.
admin_cluster_token""removedUse modules.orbit.cluster_token.
admin_trace_url_template""removedUse modules.orbit.trace_url_template.

Mail

KeyDefaultLifecycleNotes
mail_drivernoopstableBuilt-in and plugin-backed provider selection.
mail_fromnoreply@localhoststableDefault sender.
smtp_host""stableSMTP host.
smtp_port587stableSMTP port.
smtp_user""stableSMTP user.
smtp_pass""stableSMTP password.
mail_circuit_breaker.enabledtruestableWrap mail.Sender.Send with a pkg/circuit breaker. noop driver is never wrapped. Healthy (SMTP HELO probe) bypasses the breaker so /healthz observes recovery.
mail_circuit_breaker.failure_threshold5stableConsecutive Send failures required to trip the breaker open.
mail_circuit_breaker.cooldown30sstableTime the breaker stays open before admitting half-open probes.
mail_circuit_breaker.half_open_max_concurrent1stableIn-flight probe budget while half-open.

Module Jobs and Webhooks

KeyDefaultLifecycleNotes
jobs_providermemorystablepkg/tasks provider that executes module jobs: memory (in-process scheduler + workers; pending jobs are lost on restart) or asynq (Redis-backed, durable; requires jobs_redis_url). Added in v1.4.0.
jobs_redis_url""stableRedis connection URL for the asynq jobs provider (e.g. redis://localhost:6379/0). Required when jobs_provider: asynq — validated at boot; ignored by memory. Added in v1.4.0.
jobs_concurrency4stableNumber of concurrent job workers. 0 uses the provider default. Added in v1.4.0.
webhooks_prefix/webhooksstableURL prefix under which module webhook routes mount: <prefix>/<module-name><path>. With csrf_enabled: true the framework exempts this prefix from CSRF automatically — webhooks authenticate by HMAC signature (X-Nucleus-Signature), not by CSRF token. Added in v1.4.0.

Transactional Outbox (outbox.*)

KeyDefaultLifecycleNotes
outbox.enabledfalsetransitionalEnables the outbox: the table lives on the default database and the leasing dispatcher starts with the app.
outbox.table_namenucleus_outboxtransitionalName of the outbox table.
outbox.lease_duration30stransitionalHow long a claimed message stays leased to one dispatcher instance before another may claim it.
outbox.max_retries5transitionalDelivery attempts before a message is marked failed.
outbox.retry_backoff1stransitionalBase delay for the exponential retry backoff.
outbox.lease_owner`` (per-instance)transitionalIdentifies this instance in lease rows. Empty derives nucleus-<hostname>-<pid>; set explicitly for a stable identity (e.g. a k8s pod name). Before v1.8.2 every process shared the literal nucleus-app.
outbox.missing_route_policyerrortransitionalWhat a dispatcher does with a leased message whose topic has no registered bridge: error fails it; ignore releases it for the instance that can deliver it (heterogeneous fleets). Invalid values fail startup.
outbox.bridges.<n>.nametransitionalBridge instance name (required; also the routing target name). Bridge entries are configured in files only: the NUCLEUS_* double-underscore mapping has no list-index syntax, so per-entry env overrides do not apply.
outbox.bridges.<n>.typetransitionalBridge type. webhook is the delivering implementation; kafka is disabled and fails boot.
outbox.bridges.<n>.config.urltransitionalWebhook bridge: delivery endpoint URL (required).
outbox.bridges.<n>.config.pattern*transitionalWebhook bridge: topic pattern routed to this bridge (e.g. orders.*).
outbox.bridges.<n>.config.headerstransitionalWebhook bridge: extra HTTP headers sent on every delivery (e.g. an Authorization value). The contract headers X-Outbox-Payload-Encoding and X-Nucleus-Signature cannot be overridden.
outbox.bridges.<n>.config.secret""transitionalWebhook bridge: HMAC-SHA256 signing secret. When set, every delivery carries X-Nucleus-Signature: sha256=<hex> over the exact body — the same scheme module webhooks verify, so consumers share one verifier. Empty: deliveries are unsigned and the boot log WARNs once per bridge. Added after v1.4.0.
outbox.bridges.<n>.config.payload_encodingbase64transitionalWebhook bridge: wire shape of the body's payload field. base64 (default) is the classic shape every release up to v1.4.0 emits (the payload as a base64 JSON string); json opts in to embedding the payload's JSON document verbatim. Every delivery declares its actual shape in X-Outbox-Payload-Encoding, whatever the mode. Added after v1.4.0.

Observability and Security

KeyDefaultLifecycleNotes
log_levelinfostableLogger level selector.
log_formatjsonstablejson/text formatter contract.
log_redact_extra_keys[][]transitionalAdditional log attribute keys whose values the structured logger redacts, on top of the built-in denylist (observe.DefaultRedactedKeys). Case-insensitive. Use it for app-specific sensitive fields (ssn, card_number, …). There is intentionally no config key to disable redaction — redaction is on by default and turning it off requires an explicit code-level opt-out via observe.NewLoggerWithRedaction
otlp_endpoint""stableOptional OTLP-HTTP push endpoint for traces + metrics. Coexists with metrics_path — when both are set, the MeterProvider feeds both readers.
metrics_path/metricsstableMount path for the Prometheus / OpenMetrics scrape endpoint. Empty string disables the endpoint. When non-empty, App.New attaches a Prometheus reader to the OTel MeterProvider and serves it at this path with application/openmetrics-text content type. The endpoint carries no authentication of its own: when enabled, restrict access at the network / reverse-proxy layer (allow-list your scraper) or mount your own guard middleware in front of it.
metrics_publictruestableWhether the metrics endpoint is seeded into the anonymous bootstrap allow-list. true (default, the historical behaviour) lets Prometheus scrape without credentials — pair it with network-layer restrictions. false keeps /metrics OUT of the allow-list, so the default-deny RBAC enforcer gates it like any user route: grant your scraper an explicit policy (e.g. p, metrics-scraper, /metrics, *) plus JWT auth, or use a reverse-proxy guard. Added in v1.3.0.
sql_driver_instrumentationfalsestableOpt-in driver-level SQL instrumentation. false (default): the observability live SQL feed shows only model.CRUD traffic and the database/sql driver is not wrapped — zero hot-path cost. true: the driver is wrapped so direct db.QueryContext/ExecContext statements that bypass CRUD (outbox dispatch, SQL session stores, migrations, raw SQL) also reach the feed. CRUD statements are not double-recorded (de-duplicated by a context marker). Adds a small per-direct-statement cost when enabled; the expensive sanitize+emit still runs only when a subscriber is attached. Added in v1.3.0.
rate_limit_requests0stableSustained rate budget (0 disables).
rate_limit_window1mstableRate limit refill window.
rate_limit_burst0stableBurst capacity over sustained budget.
rate_limit_by_routefalsestablePer-route token bucket partitioning.
rate_limit_by_rolefalsestablePer-role token bucket partitioning.
cors_origins[][] (empty)stableCORS allow-list. Empty (the default) DENIES cross-origin requests — no CORS headers are emitted. A non-empty list restricts CORS to exactly these origins; the historical allow-all is the explicit opt-in ["*"].
cors_allow_credentialsfalsestableEmit Access-Control-Allow-Credentials: true. Only honored when cors_origins is non-empty — the Fetch standard forbids credentials with the * wildcard.
csrf_enabledfalsestableMounts the router's CSRF middleware (router.WithCSRF): Sec-Fetch-Site origin verification with a double-submit token fallback. Opt-in because CSRF protection only applies to cookie/session-authenticated browser routes — a pure Bearer-token API does not need it. The mvc scaffold ships with true. Added in v1.3.0.
csrf_exempt_paths[][]stableURL path prefixes excluded from CSRF validation (Bearer-only subtrees such as /api/, signature-authenticated webhook receivers). Only meaningful with csrf_enabled: true.
csrf_insecure_cookiefalsestableDevelopment-only opt-out: disables the Secure attribute on the CSRF cookies so the double-submit flow works for plain-HTTP non-browser clients (Go cookiejar over http://127.0.0.1). Mirrors session_cookie_secure: false. Never enable in production.
trusted_proxies[][] (empty)stableUpstream proxy addresses (IPs or CIDRs) whose X-Forwarded-For / X-Real-IP headers the RealIP middleware honors. Empty (the default) IGNORES forwarding headers and uses the immediate peer (r.RemoteAddr) as the client IP, preventing header-spoofed rate-limit evasion and audit-log poisoning. Set to your load balancer / reverse-proxy ranges (e.g. ["10.0.0.0/8"]) when Nucleus runs behind one.

Localization, Static, Storage, Environment

KeyDefaultLifecycleNotes
default_localeenstableDefault i18n locale.
locales_pathlocales/stableLocale catalog path.
static_prefix/static/stableStatic route prefix.
templates_dirinternal/web/templatesstableRoot of the HTML template tree. Loaded recursively at startup (since v1.8.2): every .html registers under its path relative to this dir with forward slashes (fieldservice/index.html); root files keep their flat name (base.html); {{define}} blocks register under their declared names. The startup log reports templates loaded with the count; a present-but-empty dir logs a WARN.
static_rootstatic/stableStatic collection target root.
storage_driverremovedRemoved in v0.12.0. Use storage.provider
storage_pathremovedRemoved in v0.12.0. Use storage.local.path
envdevelopmentstableEnvironment mode (development/production).
debugfalsestableDebug feature toggles.
profile`` (none)stableNamed preset applied over the loaded config. dev swaps every backing-service selection for its no-dependency counterpart — SQLite database (extra aliases dropped; an already-SQLite URL is kept), in-memory sessions and jobs, local filesystem storage, no-op mailer — so the same file boots with zero external services. Unknown values fail config load.

Unified Storage (storage.*)

KeyDefaultLifecycleNotes
storage.providerlocalstableBackend: s3, gcs, azure, local.
storage.defaultprivatestableDefault object visibility (private/public).
storage.public_url_base""stableBase URL for public objects (CDN or provider).
storage.public_paths{}stableMaps URL paths to storage key prefixes.
storage.s3.endpoint""stableCustom S3 endpoint (MinIO, R2). Empty = AWS.
storage.s3.bucket""stablePrimary S3 bucket name.
storage.s3.region""stableAWS region.
storage.s3.access_key_id""stableAWS access key. Accepts a plain string (literal value) or the credential-source shape: value / env_var / file / secret_manager sub-keys.
storage.s3.secret_access_key""stableAWS secret key. Plain string or credential-source shape (value/env_var/file/secret_manager).
storage.s3.session_token""stableAWS session token for temporary credentials. Plain string or credential-source shape.
storage.s3.use_path_stylefalsestablePath-style URLs (required for MinIO).
storage.s3.public_bucket""stableDedicated public bucket name.
storage.s3.create_bucket_if_missingfalsestableProvision the bucket(s) at startup when missing. Opt-in; without it a missing bucket fails app.New loudly. Was advertised by the startup error but rejected by the loader until v1.8.1.
storage.gcs.bucket""stablePrimary GCS bucket.
storage.gcs.public_bucket""stableDedicated public GCS bucket.
storage.gcs.credentials""stableGCS service-account credentials. Plain string or credential-source shape (typically file: for the mounted SA JSON); empty = Application Default Credentials.
storage.azure.account_name""stableAzure storage account name. Plain string or credential-source shape.
storage.azure.account_key""stableAzure storage account key. Plain string or credential-source shape.
storage.azure.container""stablePrimary container name.
storage.azure.public_container""stablePublic container name.
storage.local.pathstorage/stableLocal filesystem root (dev only).
storage.cleanup.enabledfalsestableEnable automatic temp file cleanup.
storage.cleanup.interval1hstableCleanup run frequency.
storage.cleanup.prefix_tmp/stablePrefix for temporary objects.
storage.cleanup.max_age24hstableMax age before temp files are purged.
storage.circuit_breaker.enabledtruestableWrap remote provider ops (Put/Get/Delete/Exists/List/Copy/SignedURL) with a pkg/circuit breaker. Local provider is never wrapped. PublicURL is pass-through. ErrNotFound is not counted as a failure.
storage.circuit_breaker.failure_threshold5stableConsecutive op failures required to trip the breaker open.
storage.circuit_breaker.cooldown30sstableTime the breaker stays open before admitting half-open probes.
storage.circuit_breaker.half_open_max_concurrent1stableIn-flight probe budget while half-open.

Module configuration (modules.*)

The modules.<name>.* namespace is reserved for mounted modules. Each module owns its own schema, declared as struct tags on its typed config — the framework does not validate those keys against the tables above. Two practical limits: the NUCLEUS_MODULES__* env-var pattern is not applied (module config comes from files or code), and nucleus config print --effective excludes modules.* values (module schemas are open-ended and may carry secrets). See Concepts → Configuration → Module-specific configuration for the full authoring guide.