Env-var reference
Every NESTRS_* environment variable, by namespace — the dual-path rule means each one also has a pinned-struct field.
Every framework module reads its config from a namespaced env prefix
and from a pinned struct — the framework-wide dual-path rule
(Configuration). The variable name is
NESTRS_<NAMESPACE>__<KEY> (double underscore between namespace and key). This
page lists the variables; each maps one-to-one to a field on the module’s
config struct, so anything here is also settable in code — and, because the
override is per field, setting one here works even when the app pins its
neighbours in module.rs.
NESTRS is the default prefix. An app that declared its own
(Your own prefix) reads every name below
with that prefix instead — ACME_HTTP__PORT, ACME_LOG — and the NESTRS_
spellings resolve nothing.
The namespace is the path of the crate that parses it — never chosen. It is
the same stem the config type is named from: the crate’s word, then the
binding folder’s when the config sits in one, joined by __. HttpConfig reads
NESTRS_HTTP__*; SeaOrmConfig reads NESTRS_SEAORM__*; RedisWorkerConfig
(in nest-rs-redis’s worker/ folder) reads NESTRS_REDIS__WORKER__*;
SocialGithubConfig reads NESTRS_SOCIAL__GITHUB__*. So from any variable on
this page you can name the type and the file that parse it, and from any
<X>Module::for_root in a composition root you can name its variables: the
vendor is in the variable exactly when it is in the type. That is also why there
is no NESTRS_DATABASE__URL — the universal convention, but a word that names
neither the crate nor the type, so a reader could not find the code from it.
Logging — NESTRS_LOG*
Section titled “Logging — NESTRS_LOG*”The baseline console logger is part of nest-rs-core — no module to
import, no config struct. It reads two process-level variables:
| Key | Meaning |
|---|---|
NESTRS_LOG | tracing filter (e.g. info, debug,hyper=warn); falls back to RUST_LOG, default info |
NESTRS_LOG_FORMAT | json (the release default) or text (the dev default) |
NESTRS_LOG_SOURCE_LOCATION | append the emitting file:line to each event — default false |
An app that installs its own subscriber first (e.g. through OpenTelemetry) keeps it — the baseline logger only activates when none is set. The same three variables drive the console layer of the OpenTelemetry subscriber too, so log config survives adopting or dropping the observability stack.
http — NESTRS_HTTP__*
Section titled “http — NESTRS_HTTP__*”| Key | Meaning |
|---|---|
HOST | listen address (default 0.0.0.0) |
PORT | listen port |
GLOBAL_PREFIX | path prefix for every route (unset ⇒ none) |
MAX_BODY_BYTES | request body cap |
REQUEST_TIMEOUT_SECS | per-request timeout — default 30, 0 ⇒ no timeout. An overrun answers 503 with a Retry-After, not 504: this transport is the origin, not a gateway |
FAIL_SECURE_STRICT | fail boot (vs warn) on an unguarded self-mount under global guards — default true |
SECURITY_HEADERS | master switch for the secure-by-default response headers |
HSTS · FRAME_OPTIONS · CONTENT_TYPE_OPTIONS · SERVER_HEADER | individual security-header controls |
REFERRER_POLICY · CROSS_ORIGIN_OPENER_POLICY · CROSS_ORIGIN_RESOURCE_POLICY | the rest of the default-on set — strict-origin-when-cross-origin, same-origin, same-origin; an empty value drops one |
CONTENT_SECURITY_POLICY · CROSS_ORIGIN_EMBEDDER_POLICY · PERMISSIONS_POLICY | settable, off by default — each governs a document whose sources the framework cannot speak for; see HTTP configuration |
TLS_CERT / TLS_KEY | PEM cert + key for HTTPS (inline); TLS_CERT_FILE / TLS_KEY_FILE read from a path instead. Unset ⇒ plain HTTP |
TLS_RELOAD_SECS | how often a file-sourced pair is re-read, so a renewal swaps in without a restart — default 60, 0 disables |
VERSIONING | how a caller selects an API version — uri (default), header, media_type |
VERSION_HEADER | the header the header strategy reads — default X-API-Version |
DEFAULT_VERSION | the version served to a caller that states none; unset ⇒ the unversioned routes |
CORS_ORIGINS | comma-separated allowed origins; unset ⇒ no CORS layer |
CORS_METHODS | comma-separated allowed request methods |
CORS_HEADERS | comma-separated allowed request headers |
CORS_EXPOSED | comma-separated response headers exposed to the browser |
CORS_CREDENTIALS | allow credentialed requests — default false |
CORS_MAX_AGE | preflight cache lifetime in seconds |
COMPRESSION | negotiate response compression from Accept-Encoding — default false (leave it to the proxy unless the app terminates responses) |
SSE_MAX_CONNECTION_SECS | how long an #[sse] stream may stay open before the server ends it and the client reconnects — default 14400 (4 h), 0 ⇒ unlimited. A security control: the stream authenticates once, at the request |
SSE_KEEP_ALIVE_SECS | keep-alive comment interval on an #[sse] stream, so an idle feed is not dropped by an intermediary — default 15, 0 ⇒ none sent |
ACCESS_LOG | emit one access-log event per request on nest_rs::operation — default true. Owned by the HTTP transport, so it needs no observability crate; trace_id joins the line only when one is mounted |
TRUSTED_PROXIES | comma-separated reverse-proxy IPs whose Forwarded (RFC 7239) / X-Forwarded-For / X-Real-IP / traceparent / X-Request-Id are believed. Empty (the default) ⇒ none is read, every caller is its transport peer, and every inbound trace is restarted. Shared by ClientIp, the throttler and the trace context; an unparseable entry aborts the boot |
seaorm — NESTRS_SEAORM__*
Section titled “seaorm — NESTRS_SEAORM__*”The one pool every SeaORM binding shares, opened by SeaOrmModule::for_root.
The engine is in the URL’s scheme (postgres://, mysql://, sqlite://) —
sea-orm picks it, the variable does not change.
| Key | Meaning |
|---|---|
URL | database connection string |
MAX_CONNECTIONS | pool maximum connections (unset ⇒ SeaORM default) |
MIN_CONNECTIONS | pool minimum connections (unset ⇒ SeaORM default) |
CONNECT_TIMEOUT_SECS | connection-acquire timeout in seconds |
SQLX_LOGGING | log SQL statements |
OBSERVE_SERIALIZATION_CONFLICTS | tag commit-time serialization conflicts at warn |
redis — NESTRS_REDIS__*
Section titled “redis — NESTRS_REDIS__*”The one Redis connection every Redis binding shares — the queue producer, the
worker and the rate-limit store — opened by RedisModule::for_root. One
connection, one variable: a throttler-only app sets the same URL a queue app
does.
| Key | Meaning |
|---|---|
URL | Redis connection string |
CONNECT_TIMEOUT_SECS | boot budget for reaching Redis before failing with a named error; defaults to 10, and 0 is rejected. Each attempt warns on nest_rs::redis, so an unreachable backend is a bounded boot failure rather than a process that never becomes healthy and never crashes |
redis__worker — NESTRS_REDIS__WORKER__*
Section titled “redis__worker — NESTRS_REDIS__WORKER__*”The consumer binding’s own settings, resolved by RedisWorkerModule::for_root.
Two segments because the config sits in the crate’s worker/ folder: the
crate’s word, then the binding’s — exactly the stem RedisWorkerConfig is named
from.
| Key | Meaning |
|---|---|
SHUTDOWN_TIMEOUT_SECS | how long the worker waits for in-flight jobs after a shutdown signal; defaults to 30 |
storage — NESTRS_STORAGE__*
Section titled “storage — NESTRS_STORAGE__*”| Key | Meaning |
|---|---|
ENDPOINT | S3 endpoint (empty ⇒ real AWS S3) |
REGION | region |
ACCESS_KEY / SECRET_KEY | static credentials |
BUCKET | target bucket |
FORCE_PATH_STYLE | path-style vs virtual-hosted addressing |
ALLOW_HTTP | reach the endpoint over plain http:// — default true in dev/test, false in staging/production so credentials never travel unencrypted by omission. false + an http:// ENDPOINT fails boot, naming the variable; the refusal covers presigned URLs, which are signed locally and would otherwise ship a working plaintext URL |
opentelemetry — NESTRS_OPENTELEMETRY__*
Section titled “opentelemetry — NESTRS_OPENTELEMETRY__*”| Key | Meaning |
|---|---|
SERVICE_NAME | service name; overrides the name passed to OpenTelemetry::init |
OTLP_ENDPOINT | collector endpoint (unset ⇒ no export) |
SAMPLE_RATIO | trace sampling ratio, 0.0–1.0 (default 1.0) |
METRIC_INTERVAL_SECS | metric export period (default 60; 0 keeps the default). Traces and logs export immediately — metrics wait for this flush |
SERVICE_VERSION · SERVICE_ENVIRONMENT · SERVICE_INSTANCE_ID | resource attributes |
The console layer reads the NESTRS_LOG* family
above — there are no OTel-specific log variables.
authn — NESTRS_AUTHN__*
Section titled “authn — NESTRS_AUTHN__*”JWT key material and validation for nest-rs-authn. A resource server sets only
the verification side (SECRET or PUBLIC_KEY); the issuer app also sets the
signing side.
| Key | Meaning |
|---|---|
SECRET | HS256 shared secret (≥ 32 bytes) — signs and verifies |
PRIVATE_KEY | EdDSA private key (PEM) — issuer only, to sign |
PUBLIC_KEY | EdDSA public key (PEM) — to verify |
ISSUER | expected iss claim (unset ⇒ no issuer check) |
AUDIENCE | expected aud claim. Set ⇒ the claim is mandatory and must name this app. Unset does not disable the check: a token carrying an aud this app is not named in is refused either way (RFC 7519 §4.1.3) |
ALLOW_ANY_AUDIENCE | opt out of that clause and accept a token minted for another service (default false). Refused beside AUDIENCE, and reported at warn once per boot |
LEEWAY_SECS | clock-skew leeway in seconds (default 30) |
EXPIRES_IN_SECS | minted-token lifetime in seconds (default 3600) |
EXPLICIT_TYPING | require the JWT typ header to name the token’s type (default true) |
oauth_client — NESTRS_OAUTH_CLIENT__*
Section titled “oauth_client — NESTRS_OAUTH_CLIENT__*”The login flow’s provider endpoints, read by OAuthClientConfig in
nest-rs-oauth-client. Every field is required, so an unconfigured app fails
boot naming the field:
| Key | Meaning |
|---|---|
CLIENT_ID / CLIENT_SECRET | the registered OAuth2 client credentials |
AUTH_URL | provider authorization endpoint (where the user consents) |
TOKEN_URL | provider token endpoint (code → tokens) |
REDIRECT_URL | this app’s callback the provider returns to |
USERINFO_URL | provider endpoint the profile is fetched from |
SCOPES | comma-separated scopes requested at authorization (empty by default) |
oauth_resource — NESTRS_OAUTH_RESOURCE__*
Section titled “oauth_resource — NESTRS_OAUTH_RESOURCE__*”OAuthResourceModule is what turns the app into a conformant OAuth 2.1
resource server (RFC 9728) and what an MCP server needs. Importing it makes
NESTRS_AUTHN__AUDIENCE mandatory: the boot fails without it rather than
leaving the app unable to say which tokens are its own. (A token minted for
another named audience is refused with or without the module — that is
RFC 7519 §4.1.3. What the module adds is that a token carrying no aud at all
is refused too.)
| Key | Meaning |
|---|---|
RESOURCE | this deployment’s canonical resource URI — the value tokens must carry as aud. Required under the module |
AUTHORIZATION_SERVERS | comma-separated issuer identifiers allowed to mint tokens for it. At least one required |
SCOPES_SUPPORTED | comma-separated minimal scope set, advertised in the metadata document and the WWW-Authenticate challenge |
BEARER_METHODS_SUPPORTED | how a token may be presented — defaults to header, the only form accepted |
RESOURCE_NAME | human-readable name for a consent screen |
RESOURCE_DOCUMENTATION | URL of developer documentation for this resource |
RESOURCE_POLICY_URI | URL of this resource’s privacy policy, advertised in the metadata document |
RESOURCE_TOS_URI | URL of this resource’s terms of service, advertised in the metadata document |
mcp — NESTRS_MCP__*
Section titled “mcp — NESTRS_MCP__*”| Key | Meaning |
|---|---|
ALLOWED_HOSTS | comma-separated Host authorities accepted (anti-DNS-rebinding). Defaults to loopback, so a public deployment must name itself; an empty list disables the check and is reported at warn |
LEGACY_SESSION_MODE | keep sessions alive for protocol revisions older than 2026-07-28 — default true |
JSON_RESPONSE | answer simple operations with application/json instead of an SSE stream — default false |
SSE_KEEP_ALIVE_SECS | SSE keep-alive ping interval (0 ⇒ none) — default 15 |
SSE_RETRY_SECS | retry: interval advertised on SSE priming events (0 ⇒ none) — default 3 |
MAX_REQUEST_BODY_BYTES | cap on a single POST body, enforced while streaming — default 4 MiB |
STATELESS_PROTOCOL_METADATA_REQUIRED | require per-request protocol metadata on stateless POSTs (SEP-2243) — default false |
social — NESTRS_SOCIAL__<PROVIDER>__*
Section titled “social — NESTRS_SOCIAL__<PROVIDER>__*”One sub-namespace per provider (GITHUB, GOOGLE). Credentials decide the
provider’s fate: complete ⇒ active, absent ⇒ inert with a boot warn,
partial ⇒ the boot fails naming the provider.
| Key | Meaning |
|---|---|
CLIENT_ID / CLIENT_SECRET | the provider’s OAuth app credentials |
REDIRECT_URL | the registered callback this app is returned to |
SCOPES | comma-separated scopes; each provider has a sensible default when unset |
The endpoint URLs are provider constants, not config — see Social login.
Other namespaces
Section titled “Other namespaces”These read their own NESTRS_<NAMESPACE>__* keys. The rule is uniform: the
struct’s field name uppercased is the key. Two namespaces are not spelled the
way their section is, so the page is named rather than left to a search:
| Namespace | Documented on |
|---|---|
graphql | GraphQL configuration |
openapi | OpenAPI |
health | Health |
throttler | Rate limiting |
ws | WebSockets |
issuer | the demo feature library — the Publish workspace |
The .env cascade
Section titled “The .env cascade”Values resolve highest-first: real env > pinned in module.rs >
.env.<NESTRS_ENV>.local > .env.local > .env.<NESTRS_ENV> > .env. See
the env cascade for the files and
the dual-path rule for where a pinned
value sits.
Going further
Section titled “Going further”- Configuration — the typed
#[config]derive and dual-path rule. - The env cascade — layering and precedence.