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 (port →
NUCLEUS_PORT); nested keys join segments with a double
underscore (databases.<alias>.url →
NUCLEUS_DATABASES__<ALIAS>__URL).
Lifecycle.
| Tag | Meaning |
|---|---|
stable | Key name and semantics are contract surfaces on the v1.x line. |
transitional | Supported, but semantics may still refine before freezing. |
experimental | No compatibility guarantee yet. |
removed | No 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
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
host | 0.0.0.0 | stable | Bind host. |
port | 8080 | stable | Bind port. |
read_timeout | 30s | stable | HTTP read timeout. |
write_timeout | 60s | stable | HTTP write timeout. |
idle_timeout | 120s | stable | HTTP idle timeout. |
request_timeout | 30s | transitional | Per-request handler deadline: past it the client receives a 503 and the handler's context is cancelled. 0 keeps the default; a negative value (-1s) disables the timeout on every route. Streaming routes are better exempted with timeout_exempt_paths. Before this key existed the deadline silently reused read_timeout. |
timeout_exempt_paths[] | [] | transitional | URL path prefixes served without the request timeout and with the raw response writer (Flush/Hijack work): server-sent events, long polls, large downloads. Requests whose Accept header asks for text/event-stream are exempt without listing them. |
tls_cert_file | "" | transitional | PEM 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 | "" | transitional | PEM private-key file paired with tls_cert_file. |
Database
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
database_default | default | stable | Primary DB alias used by app.DB. |
databases.<alias>.url | databases.default.url=sqlite://nucleus.db | stable + experimental | Stable schemes: sqlite://, postgres://, postgresql://, mysql://; exploratory schemes: sqlserver:///mssql://, oracle://. |
databases.<alias>.max_open | 25 | stable | Per-alias pool max open conns (inherits primary if omitted). |
databases.<alias>.max_idle | 5 | stable | Per-alias pool max idle conns (inherits primary if omitted). |
databases.<alias>.max_lifetime | 5m | stable | Per-alias conn max lifetime (inherits primary if omitted). |
MultiSite and MultiTenant
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
multisite.enabled | false | stable | Enable host-based site resolution. |
multisite.default_site | default | stable | Fallback site when host does not match configured patterns. |
multisite.sites.<site>.hosts[] | [] | stable | Exact host or wildcard (*.example.com) patterns per site. |
multisite.sites.<site>.database | database_default | stable | Default DB alias for the site. |
multisite.sites.<site>.tenant_database_alias_template | "" | stable | Optional per-site tenant DB alias template (tenant_%s or {tenant}). |
multitenant.enabled | false | stable | Enable tenant resolution. |
multitenant.resolver | subdomain | stable | subdomain or header. |
multitenant.header | X-Tenant-ID | stable | Header used when resolver is header. |
multitenant.default_tenant | "" | stable | Optional fallback tenant id. |
multitenant.require_isolated_db | true | stable | Security-by-default guard: rejects shared DB alias routing across tenants. |
multitenant.require_tenant_storage | false | stable | Storage operations with no tenant in context fail (storage.ErrNoTenantInContext) instead of silently using the shared unprefixed key space. Off: the first degradation logs one WARN. |
multitenant.database_alias_template | tenant_%s | stable | Global tenant DB alias template (%s or {tenant}). |
multitenant.tenants.<tenant>.site | "" | stable | Optional site binding for a tenant mapping. |
multitenant.tenants.<tenant>.database | "" | stable | Explicit tenant DB alias mapping. |
Redis and Sessions
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
redis_url | "" | stable | Optional Redis endpoint for queue/session features. |
session_lifetime | 72h | stable | Server-side session lifetime. |
session_store | memory | stable | Supported values: memory, sql, redis. |
session_redis_url | "" | stable | Redis override for session backend. |
session_table | nucleus_sessions | stable | SQL session table name. |
session_cookie_name | session | stable | Session cookie name. |
session_cookie_domain | "" | stable | Session cookie domain. |
session_cookie_path | / | stable | Session cookie path. |
session_cookie_secure | true | stable | Session 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_samesite | lax | stable | SameSite policy string. |
session_idle_timeout | 0 | stable | Optional idle timeout override. |
session_redis_prefix | nucleus:sessions: | stable | Session Redis key prefix. |
session_memcached_servers[] | [] | transitional | host:port list for session_store: memcached. |
Auth
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
jwt_secret | "" | stable | Single-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_expiry | 24h | stable | JWT lifetime default. |
jwt_issuer | "" | stable | Issuer claim (iss) stamped into every token minted by App.JWT. Used by both single-secret and multi-key managers. |
jwt_audience | "" | transitional | Audience stamped into every token the app mints and required of every token it accepts; empty leaves aud unchecked. The issuer is always verified. |
jwt_keys[] | [] | stable | Ordered 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 | "" | stable | kid 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:
| Field | Type | Notes |
|---|---|---|
kid | string | Unique key identifier stamped in token kid header. Required. |
algorithm | string | HS256, RS256, or ES256. Required. |
secret_env | string | Resolver reference to the HMAC secret (HS256 only). See reference forms below. |
pem_path | string | Filesystem 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_env | string | Resolver 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):
| Reference | Resolved from |
|---|---|
MY_VAR | environment variable MY_VAR (historical behaviour) |
env:MY_VAR | environment 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
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
rbac_policy_file | "" | stable | Path 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 | "" | removed | Removed in v0.12.0. Use rbac_policy_file |
Admin (removed — moved to the orbit module)
| Key | Former default | Lifecycle | Migration |
|---|---|---|---|
admin_prefix | /admin | removed | Use modules.orbit.prefix (see orbit module docs). |
admin_title | Nucleus Admin | removed | Use modules.orbit.title. |
admin_auth_database | "" | removed | Use modules.orbit.auth_database. |
admin_bootstrap_username | "" | removed | Use modules.orbit.bootstrap_username. |
admin_bootstrap_email | "" | removed | Use modules.orbit.bootstrap_email. |
admin_bootstrap_password | "" | removed | Use modules.orbit.bootstrap_password. |
admin_live_exclude_patterns[] | [/admin] | removed | Use modules.orbit.live_exclude_patterns. |
admin_cluster_enabled | false | removed | Use modules.orbit.cluster_enabled. |
admin_cluster_redis_url | "" | removed | Use modules.orbit.cluster_redis_url. |
admin_cluster_channel | nucleus:admin:live:v1 | removed | Use modules.orbit.cluster_channel. |
admin_cluster_node_id | "" | removed | Use modules.orbit.cluster_node_id. |
admin_cluster_token | "" | removed | Use modules.orbit.cluster_token. |
admin_trace_url_template | "" | removed | Use modules.orbit.trace_url_template. |
Mail
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
mail_driver | noop | stable | Built-in and plugin-backed provider selection. |
mail_from | noreply@localhost | stable | Default sender. |
smtp_host | "" | stable | SMTP host. |
smtp_port | 587 | stable | SMTP port. |
smtp_user | "" | stable | SMTP user. |
smtp_pass | "" | stable | SMTP password. |
mail_circuit_breaker.enabled | true | stable | Wrap 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_threshold | 5 | stable | Consecutive Send failures required to trip the breaker open. |
mail_circuit_breaker.cooldown | 30s | stable | Time the breaker stays open before admitting half-open probes. |
mail_circuit_breaker.half_open_max_concurrent | 1 | stable | In-flight probe budget while half-open. |
Module Jobs and Webhooks
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
jobs_provider | memory | stable | pkg/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 | "" | stable | Redis 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_concurrency | 4 | stable | Number of concurrent job workers. 0 uses the provider default. Added in v1.4.0. |
jobs_scheduler_lock | true | stable | Leader election for the asynq scheduler over a Redis lock (SET NX + TTL): with multiple replicas exactly one process ticks the cron entries; workers run on every replica either way. false opts out and the boot log WARNs that each replica fires every job. Ignored by the memory provider. |
webhooks_prefix | /webhooks | stable | URL 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.*)
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
outbox.enabled | false | transitional | Enables the outbox: the table lives on the default database and the leasing dispatcher starts with the app. |
outbox.table_name | nucleus_outbox | transitional | Name of the outbox table. |
outbox.lease_duration | 30s | transitional | How long a claimed message stays leased to one dispatcher instance before another may claim it. |
outbox.max_retries | 5 | transitional | Delivery attempts before a message is marked failed. |
outbox.retry_backoff | 1s | transitional | Base delay for the exponential retry backoff. |
outbox.lease_owner | `` (per-instance) | transitional | Identifies 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_policy | error | transitional | What 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>.name | — | transitional | Bridge 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>.type | — | transitional | Bridge type. webhook is the delivering implementation; kafka is disabled and fails boot. |
outbox.bridges.<n>.config.url | — | transitional | Webhook bridge: delivery endpoint URL (required). |
outbox.bridges.<n>.config.pattern | * | transitional | Webhook bridge: topic pattern routed to this bridge (e.g. orders.*). |
outbox.bridges.<n>.config.headers | — | transitional | Webhook 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 | "" | transitional | Webhook 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_encoding | base64 | transitional | Webhook 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
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
log_level | info | stable | Logger level selector. |
log_format | json | stable | json/text formatter contract. |
log_redact_extra_keys[] | [] | transitional | Additional 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 | "" | stable | Optional OTLP-HTTP push endpoint for traces + metrics. Requires the exporters/otlp module (nucleus add otlp): the core keeps the OpenTelemetry SDK and links no exporter, so a non-empty endpoint without the module stops startup with the import to add. Coexists with metrics_path — when both are set, the MeterProvider feeds both readers. |
metrics_path | /metrics | stable | Mount path for the Prometheus / OpenMetrics scrape endpoint. Empty string disables the endpoint. Requires the exporters/prometheus module (nucleus add prometheus); the core links no exporter. When the module is imported and the path is non-empty, App.New attaches a Prometheus reader to the OTel MeterProvider and serves it at this path with application/openmetrics-text content type. Without the module: a path you wrote yourself stops startup with the import to add, while the untouched default only logs at startup that metrics are not being served and the application boots with the path answering 404. 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_public | true | stable | Whether 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_instrumentation | false | stable | Opt-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_requests | 0 | stable | Sustained rate budget (0 disables). |
rate_limit_window | 1m | stable | Rate limit refill window. |
rate_limit_burst | 0 | stable | Burst capacity over sustained budget. |
rate_limit_by_route | false | stable | Per-route token bucket partitioning. |
rate_limit_by_role | false | stable | Per-role token bucket partitioning. |
cors_origins[] | [] (empty) | stable | CORS 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_credentials | false | stable | Emit Access-Control-Allow-Credentials: true. Only honored when cors_origins is non-empty — the Fetch standard forbids credentials with the * wildcard. |
csrf_enabled | false | stable | Mounts 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[] | [] | stable | URL path prefixes excluded from CSRF validation (Bearer-only subtrees such as /api/, signature-authenticated webhook receivers). Only meaningful with csrf_enabled: true. |
csrf_insecure_cookie | false | stable | Development-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) | stable | Upstream 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. |
auth_backends[] | [] (empty) | stable | ORDERED list of authentication backend names (registered with auth.RegisterBackend; the application's own user table appears here under the name given to WithUserProvider, local by default). Order is meaningful: [ldap, local] consults the directory first and falls through to the local table when the directory cannot be reached — a backend that is UNAVAILABLE is skipped, one that REJECTS ends the attempt. A name that is not registered fails at boot; a repeated name is rejected because the list is a chain, not a set. Empty means no chain is built. |
storage.<provider>.* | — | stable | Configuration subtree of a REGISTERED third-party storage provider (storage.RegisterProvider). The framework validates only that the section belongs to a registered name — a misspelled section is still an unknown key; the provider validates its own contents through storage.Config.BindProvider, where a key its struct does not declare is an error. Built-in providers use their typed sections (storage.s3.*, storage.local.*, …) instead. |
auth.<backend>.* | — | stable | Configuration subtree of a REGISTERED authentication backend (auth.RegisterBackend), keyed by the name used in auth_backends. Same rule as storage.<provider>.*: the framework validates only that the section belongs to a registered name — a misspelled section is still an unknown key — and the backend validates its own contents through auth.BackendConfig.Bind, where a key its struct does not declare is an error. A backend that needs no settings needs no section. A section whose backend is NOT listed in auth_backends is an ERROR: the chain is its only consumer, so it would boot clean and be read by nobody. Added in v1.15.0. |
auth_federated[] | [] (empty) | stable | Browser-redirect identity providers (OIDC, SAML). Each entry declares name (the INSTANCE: its URL segment, its auth.<name>.* subtree and its sign-in button), provider (the registered protocol type) and an optional display_name. Instance and type are separate fields because two identity providers of the same protocol — a corporate tenant and a partner one — is an ordinary configuration. Independent of auth_backends: a federated flow has no credentials to hand to a chain. A provider nobody registered fails at boot, naming what is registered; two entries sharing a name fail, because they would share a callback URL. Added in v1.17.0. |
public_base_url | "" (empty) | stable | The address the BROWSER reaches this application at, without a trailing slash. REQUIRED when auth_federated is non-empty: the callback URL an operator registers with their identity provider is derived from it, and behind a reverse proxy or in a container it is not the address the process binds. The resolved callback URLs are logged at startup. Added in v1.17.0. |
http_interceptors[] | [] (empty) | stable | ORDERED list of registered request interceptors (interceptor.Register), outermost first: the first name sees the request first and the response last. Order is the behaviour, not a detail — authentication before rate limiting and rate limiting before authentication are different systems. A name that is not registered fails at boot naming what is, a factory that errors fails boot, and a repeated name is rejected. Interceptors mount INSIDE the framework's own middleware, after the request ID, the session and the observability hook. Added in v1.17.0. |
interceptors.<name>.* | — | stable | Configuration subtree of a REGISTERED request interceptor, keyed by the name used in http_interceptors — the same pairing as auth_backends with auth.<backend>.*: the list orders, the subtree configures. The framework validates only that the section belongs to a registered name; the interceptor validates its own contents through interceptor.Config.Bind, where a key its struct does not declare is an error. Added in v1.17.0. |
Localization, Static, Storage, Environment
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
default_locale | en | stable | Default i18n locale. Read by the i18n CLI pair and by the runtime: when compiled catalogs are loaded, a request whose Accept-Language matches no catalog locale falls back to this locale (see pkg/i18n). |
locales_path | locales/ | stable | Locale catalog path. makemessages/compilemessages write catalogs here; at startup the app loads any compiled JSON bundles under it and, when at least one locale exists, mounts the Accept-Language negotiation middleware. |
static_prefix | /static/ | stable | Static route prefix. |
templates_dir | internal/web/templates | stable | Root 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_root | static/ | stable | Static collection target root. |
storage_driver | — | removed | Removed in v0.12.0. Use storage.provider |
storage_path | — | removed | Removed in v0.12.0. Use storage.local.path |
env | development | stable | Environment mode (development/production). |
debug | false | stable | Debug feature toggles. |
profile | `` (none) | stable | Named 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.*)
| Key | Default | Lifecycle | Notes |
|---|---|---|---|
storage.provider | local | stable | Backend: local (built in), or s3, gcs, azure — each a module of its own (`providers/storage-s3 |
storage.default | private | stable | Default object visibility (private/public). |
storage.public_url_base | "" | stable | Base URL for public objects (CDN or provider). |
storage.public_paths | {} | stable | Maps URL paths to storage key prefixes. |
storage.s3.endpoint | "" | stable | Custom S3 endpoint (MinIO, R2). Empty = AWS. |
storage.s3.bucket | "" | stable | Primary S3 bucket name. |
storage.s3.region | "" | stable | AWS region. |
storage.s3.access_key_id | "" | stable | AWS 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 | "" | stable | AWS secret key. Plain string or credential-source shape (value/env_var/file/secret_manager). |
storage.s3.session_token | "" | stable | AWS session token for temporary credentials. Plain string or credential-source shape. |
storage.s3.use_path_style | false | stable | Path-style URLs (required for MinIO). |
storage.s3.public_bucket | "" | stable | Dedicated public bucket name. |
storage.s3.create_bucket_if_missing | false | stable | Provision 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 | "" | stable | Primary GCS bucket. |
storage.gcs.public_bucket | "" | stable | Dedicated public GCS bucket. |
storage.gcs.credentials | "" | stable | GCS service-account credentials. Plain string or credential-source shape (typically file: for the mounted SA JSON); empty = Application Default Credentials. |
storage.azure.account_name | "" | stable | Azure storage account name. Plain string or credential-source shape. |
storage.azure.account_key | "" | stable | Azure storage account key. Plain string or credential-source shape. |
storage.azure.container | "" | stable | Primary container name. |
storage.azure.public_container | "" | stable | Public container name. |
storage.local.path | storage/ | stable | Local filesystem root (dev only). |
storage.cleanup.enabled | false | stable | Enable automatic temp file cleanup. |
storage.cleanup.interval | 1h | stable | Cleanup run frequency. |
storage.cleanup.prefix | _tmp/ | stable | Prefix for temporary objects. |
storage.cleanup.max_age | 24h | stable | Max age before temp files are purged. |
storage.circuit_breaker.enabled | true | stable | Wrap 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_threshold | 5 | stable | Consecutive op failures required to trip the breaker open. |
storage.circuit_breaker.cooldown | 30s | stable | Time the breaker stays open before admitting half-open probes. |
storage.circuit_breaker.half_open_max_concurrent | 1 | stable | In-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.