3.0.0 Release Notes
This page summarizes the major changes introduced after v2.1.3 and first published as v3.0.0-beta.1. The newest prerelease is listed first.
Nauthilus 3.0.0 is a major platform release. It introduces the canonical config-v2 surface, the declarative
auth.policydecision layer, split edge/authority identity proxy deployments, native gRPC authority APIs, CBOR authentication, generated OpenAPI contracts, and stronger security and validation defaults. It also contains hard breaking changes for configuration files and Lua policy plugins.
3.0.0-rc.2
Released on May 27, 2026.
Added
Authentication Pipeline
- Master-user login parsing is configured with
auth.pipeline.master_user.user_format. - The format uses target-user and master-user placeholders, for example the default
"{user}*{master_user}".
Auth Policy
- Request policies can now use
request.caller.ip,request.caller.ip.present, andrequest.caller.ip.sourceto match the direct caller seen by Nauthilus. - Request policies can now use
request.local.ip,request.local.ip.present,request.local.port, andrequest.local.port.presentto match the local server endpoint reported by the request adapter. - LDAP authentication records
auth.master_user.activewithmaster_userandtarget_userdetails for master-userauthenticaterequests. - Lua backends can emit the built-in master-user fact through
nauthilus_policy.emit_master_user(...).
Management API
- Brute-force list endpoints expose
limitandoffsetquery parameters. - Brute-force list responses include
pagemetadata withlimit,offset,next_offset, andhas_more.
3.0.0-beta.3
Released on May 21, 2026.
This beta focuses on backend-health-check authentication portability, configuration ergonomics, metrics endpoint hardening, and Lua runtime resilience. It includes all changes from v3.0.0-beta.2.
Added
Backend Health Checks
- Backend health-check targets can now set
auth_mechanismdirectly on each target. - Supported target values are
auto,PLAIN,LOGIN,USERPASS, andBASIC. autodiscovers protocol capabilities where available and selects an executable mechanism through a shared selector.- SMTP and LMTP read
EHLO/LHLOAUTH; IMAP readsCAPABILITYandAUTH=<mech>; POP3 readsCAPA,SASL ..., and nativeUSER; Sieve evaluates post-STARTTLS capabilities; HTTP uses a staticBASICadapter. - Unsupported mechanisms such as
SCRAM-*,OAUTHBEARER,XOAUTH2,EXTERNAL,CRAM-MD5, andDIGEST-MD5are not executable by health checks, even when a backend advertises them.
Configuration Placeholders
- Config values can now use strict
${NAME}expansion after includes and patches have been merged. - Built-in placeholder defaults cover packaged configuration paths such as
NAUTHILUS_CONF_DIRandNAUTHILUS_PLUGINS_DIR, while matching environment variables can override them. - Vim syntax generation was updated for the active placeholder and config-key surface.
Changed
Health-Check Authentication
- Backend health checks now share one mechanism selector across SMTP, LMTP, IMAP, POP3, Sieve, and HTTP instead of each protocol hard-coding its own login path.
- Explicitly configured mechanisms that are not advertised by the backend fail the deep check and log structured mechanism diagnostics without exposing passwords or authentication payloads.
- IMAP and Sieve use SASL initial responses only when
SASL-IRis advertised. - SMTP and LMTP may use initial-response forms for supported mechanisms and retry once with the classic challenge/response form only when the server rejects the command form or syntax.
Observability
/metricscan now be protected with dedicated Basic Auth underobservability.metrics.endpoint_auth.basic.- Metrics endpoint authentication does not reuse bearer-token or backchannel credentials.
- Example Prometheus and nginx configuration were updated for the dedicated metrics credentials.
Fixed
Lua Runtime
- Lua VM leases are now replaced after execution errors or panics so a failed script cannot poison a pooled VM for later backend, hook, action, cache-flush, environment, or subject execution.
- Regression tests cover failed and canceled Lua
requirestate poisoning.
3.0.0-beta.2
Released on May 19, 2026.
This beta contains focused reliability fixes for cache-free brute-force workflows and IdP session cookie handling.
Fixed
Authentication Pipeline
- Brute-force history loading is decoupled from positive password-cache usage.
- Backend execution planning is now explicit, so positive password-cache writes remain tied to the configured backend order while brute-force histories can still load after account resolution without a cache backend.
Identity Provider
- Duplicate secure cookies with the same name no longer let a stale or invalid value shadow a later decodable IdP session cookie.
- Existing empty-session behavior is preserved when no matching cookie can be decoded.
3.0.0-beta.1
Released on May 18, 2026.
This beta is intended for migration testing, integration hardening, and early operator feedback. It is the first public 3.0.0 prerelease and should be treated as the upgrade target for validating 2.1.x deployments before the stable 3.0.0 release.
Read This First
The largest upgrade risk is not binary compatibility; it is configuration and policy semantics.
Before upgrading a production deployment:
- Read the Config v2 Migration Guide.
- Convert legacy single-file YAML with
scripts/convert-config-v1-to-v2.pyfrom the Nauthilus server repository. - Review the generated migration report manually.
- Validate the converted file with
nauthilus --config-check. - Compare canonical non-default output with
nauthilus -n. - Review Auth Policy Reference and Auth Policy Configuration Guide before turning custom policy rules into production authority.
The converter is a migration accelerator, not a promise that every historical local convention can be rewritten without human review.
Breaking Changes
Configuration Is Now Config v2
The public configuration model is now organized around these root sections:
runtimeobservabilitystorageauthidentity
Legacy public roots from the 2.1 line are not part of the current surface anymore:
serverldapluaidprealtime_blackhole_listsrelay_domainsbrute_forcebackend_server_monitoringcleartext_networks
Common path migrations include:
| Before 3.0.0 | 3.0.0 and newer |
|---|---|
server.address | runtime.servers.http.address |
server.tls | runtime.servers.http.tls |
server.timeouts | runtime.timeouts |
server.log | observability.log |
server.redis.master | storage.redis.primary |
server.default_http_request_header | auth.request.headers |
server.basic_auth | auth.backchannel.basic_auth |
server.oidc_auth | auth.backchannel.oidc_bearer |
server.backends | auth.backends.order |
ldap.config | auth.backends.ldap.default |
lua.config | auth.backends.lua.backend.default |
idp.oidc | identity.oidc |
idp.saml2 | identity.saml |
backend_server_monitoring | auth.services.backend_health_checks |
brute_force | auth.controls.brute_force |
realtime_blackhole_lists | auth.controls.rbl |
relay_domains | auth.controls.relay_domains |
cleartext_networks | auth.controls.tls_encryption.allow_cleartext_networks |
Removed legacy aliases include soft_allowlist, soft_whitelist, storage.redis.master, and flat SAML SLO aliases such as identity.saml.slo_enabled. Use the canonical paths documented in Configuration File and Runtime, Observability, and Storage.
Auth Decisions Move To auth.policy
Nauthilus now has a declarative auth decision layer under auth.policy.
The built-in standard_auth policy preserves default authentication behavior when no custom policy rules are authoritative. Custom rules become authoritative per operation and stage when they match through auth.policy.policies.
Important behavior changes:
auth.policy.checkscontrols fact collection, Lua execution scope, auth-state guards, and check ordering.auth.policy.policiescontrols decision effects.mode: observecompares configured policies without changing production output.mode: enforceallows matching custom rules to own their stages.- Policy reports are diagnostic material and do not change HTTP, CBOR, Nginx, gRPC, OIDC, or SAML response shapes.
See Auth Policy Reference for the exact authority boundaries.
Hidden Loopback Bypasses Were Removed
3.0.0 removes hard-coded loopback and empty-client-IP bypasses from pre-auth controls. Lua environment sources, TLS enforcement, relay-domain checks, RBL checks, and brute-force checks now skip only when explicitly configured to skip.
Use auth.policy.scheduler_guards with skip_if when you intentionally want trusted internal traffic to skip a specific check. Guards should be fail-closed and should combine trusted server-derived facts, such as listener, transport, TLS state, or trusted client IP, instead of trusting arbitrary request headers or gRPC metadata.
See the scheduler-guard section in the Config v2 Migration Guide.
Lua Feature And Filter Terminology Is A Hard Cut
The 2.1 Lua policy vocabulary has been replaced with the 3.0 environment/subject vocabulary.
| Before 3.0.0 | 3.0.0 and newer |
|---|---|
lua.features | auth.policy.attribute_sources.lua.environment |
lua.filters | auth.policy.attribute_sources.lua.subject |
lua.actions | auth.policy.obligation_targets.lua.actions |
lua.custom_hooks | auth.controls.lua.hooks |
lua-plugins.d/features | lua-plugins.d/environment |
lua-plugins.d/filters | lua-plugins.d/subject |
nauthilus_call_feature(request) | nauthilus_call_environment(request) |
nauthilus_call_filter(request) | nauthilus_call_subject(request) |
FEATURE_* constants | ENVIRONMENT_* constants |
FILTER_* constants | SUBJECT_* constants |
Legacy Lua scheduler keys such as when_no_auth, when_authenticated, when_unauthenticated, and depends_on are represented in 3.0 through policy check scheduling: operations, run_if.auth_state, and after.
Use Lua Policy Plugins for the new plugin model and Config v2 Migration for the migration mapping.
JSON And CBOR Auth Requests Are Strict
The structured JSON and CBOR auth endpoints now share stricter request semantics.
For /api/v1/auth/json, unknown request fields are rejected. For /api/v1/auth/cbor, Nauthilus also rejects duplicate map keys, CBOR tags, indefinite-length items, oversized bodies, overly deep nesting, and overly large arrays or maps.
This may break loose clients that sent extra fields "just in case". Update clients to send only documented request fields. See REST API.
Production Container Image Uses scratch
The stable production image now uses a scratch runtime image with explicit CA certificates, nsswitch.conf, timezone data, bundled resources, and the nauthilus user/group material copied in.
Operational impact:
- do not expect a shell, package manager,
bash, orcurlinside the stable runtime image; - use the debug image for shell-oriented troubleshooting;
- the stable image defaults to
TZ=UTC; ZONEINFOandSSL_CERT_FILEare set explicitly.
Added
Config v2 Tooling And Diagnostics
- Schema-driven validation and unknown-key diagnostics now report canonical config paths instead of Go struct names.
nauthilus -dprints canonical defaults.nauthilus -nprints canonical non-default values from a loaded config.--dump-format canonical|yaml|json|tomlselects structured dump output.- Secrets are redacted by default and can be shown with
-Pwhen explicitly requested. - Long-form help output was reorganized around the new CLI surface.
Legacy Config Converter
Nauthilus now ships a best-effort converter:
python3 scripts/convert-config-v1-to-v2.py legacy-nauthilus.yml --output nauthilus-v2.yml
Useful options:
--report <path>writes warnings, dropped paths, and conversion details.--validaterunsnauthilus --config-checkagainst the converted output.--dry-run --stdoutprints converted YAML without writing files.
The converter handles the major root migrations, optional LDAP pools, optional Lua backends, published pre-3.0 Lua source names, dotted legacy keys, x-* extension roots, best-effort anchor reuse, mapping order preservation, and generated target auth.policy checks and policies.
See Config v2 Migration Guide.
Declarative Policy Layer
The new policy layer adds:
- typed policy attributes and details;
- a compiler and immutable runtime snapshots;
standard_authdefault behavior through the policy engine;- custom
pre_auth,auth_decision, and non-password operation policies; - observe mode and enforce mode;
- policy reports with redaction;
- policy logs, metrics, and OpenTelemetry spans;
- explicit request facts for HTTP, gRPC, mail protocol, IdP, SAML, TLS, listener, and source-IP context;
- request-header and gRPC-metadata allowlists;
- reusable network and time-window sets;
- scheduler guards for explicit check skipping;
- policy-selected response messages, including
literal,attribute_detail, andi18nsources.
See Auth Policy Configuration Guide.
Policy Localization And Lua i18n
Policy-selected response messages can now use stable i18n keys and fallback text. HTTP, gRPC, and IdP response boundaries resolve localized messages through Accept-Language, gRPC accept-language, or policy-selected response language.
The optional nauthilus_i18n Lua module lets deployments register and read localization catalog overlays without bypassing the policy response-message model.
Policy-Aware Lua Plugins
Lua plugins can emit typed policy facts instead of directly owning final decisions. Bundled helper modules and registry scripts support policy-safe attributes under lua.plugin.*.
Environment sources run before subject identity is known. Subject sources run after backend identity material exists. Lua actions remain obligation targets selected by policy.
Native gRPC Authority APIs
Nauthilus now exposes typed protobuf authority APIs:
nauthilus.auth.v1.AuthServiceAuthenticateLookupIdentityListAccounts
nauthilus.identity.v1.IdentityBackendService- identity snapshots
- MFA state
- TOTP registration and verification
- recovery-code generation, use, and deletion
- WebAuthn credential read, save, update, and delete operations
The gRPC authority listener lives under runtime.servers.grpc.authority. Caller authentication is mandatory through Basic auth or bearer tokens, and non-loopback listeners require TLS. For split deployments, use mTLS.
See gRPC Authority APIs.
Split Identity Proxy Deployments
3.0.0 introduces a first-class split deployment model:
- edge instances terminate public OIDC, SAML, MFA, WebAuthn, and browser flows;
- authority instances own LDAP/Lua/test backend access, MFA secrets, recovery-code hashes, WebAuthn persistent credentials, backend references, and authority-side cache state;
- edges call authorities through hardened gRPC with mTLS and caller tokens;
- edge Redis and authority Redis are intentionally separate state domains;
- remote backend references are opaque, short-lived, authority-owned handles;
- requested OIDC/SAML attributes are released from the authority to the edge only when requested and policy-safe.
See Split Identity Proxy Configuration, Remote Authority Backend, and Building a Distributed Identity Proxy.
CBOR Authentication
/api/v1/auth/cbor is now available for structured authentication requests. It uses the same logical request model as JSON, a strict bounded CBOR decoder, CBOR response rendering, and content negotiation for no-auth and list-account modes.
A Python helper is available in the server repository as contrib/auth-cbor-request.py. See CBOR Auth Request Client.
Generated OpenAPI Contracts
Nauthilus now publishes generated OpenAPI contracts for:
- Management API
- IdP API
The contracts are served by the application and are also used by generated clients, drift checks, and the website API Reference.
Runtime OpenAPI request validation is available as an optional, default-off pilot for selected management operations. It is intentionally enforce-only when enabled; warn-only runtime validation is not supported. See OpenAPI Runtime Request Validation.
The optional /api/v1/auth/basic endpoint has its own tagged OpenAPI overlay and exists only in binaries built with the auth_basic_endpoint Go build tag.
Security.txt And Hook Aliases
The native /.well-known/security.txt endpoint can now be configured under runtime.servers.http.security_txt, including disclosure contacts, expiration handling, policy files, and encryption-key references.
Lua custom hooks can also define an optional http_alias_location. Aliases dispatch back to the canonical hook without overriding registered IdP or API routes.
Changed
Identity Provider And MFA
- TOTP setup and validation now share normalized settings for issuer, period, digits, algorithm, and skew.
- Copied TOTP codes and stored setup URLs are normalized before validation.
- Recovery-code downloads are more readable.
- Delayed-response and device-code failure metadata is preserved for IdP UI rendering.
- OIDC token validation avoids duplicate opaque-token Redis lookups, resolves JWT keys by
kid, and checks denylist state only after successful signature validation. - Policy-selected status messages are bridged into the IdP UI.
Redis And Cluster Safety
- Redis read/write contexts are configurable and applied to token, session, device-code, and signing-key operations.
- Redis client behavior gained additional timeout and pooling controls.
- Global pattern monitoring Lua scripts now use Redis Cluster-safe key handling.
Observability
- Lua execution now emits phase-level tracing spans for execution, wait, merge, and result steps.
- LDAP Lua attribute extraction was corrected to avoid leading empty configured attributes.
- Policy decisions, reports, metrics, and traces use explicit policy vocabulary.
- gRPC auth lifecycle logging was expanded for parity with HTTP auth lifecycle logging.
Release Automation
- Release workflows support prerelease tags such as
v3.0.0-beta.1. - Stable release metadata, package versioning, SBOM generation, artifact attestation, and Docker publishing were aligned with prerelease handling.
- The
auth_basic_endpointOpenAPI contract is generated separately from the default management contract.
Security And Validation Coverage
The new split identity proxy smoke profile is a major part of the 3.0.0 validation story. It covers:
- gRPC caller authentication and mTLS;
- OIDC authorization-code and device-code flows through the edge;
- TOTP registration and login through the authority;
- recovery-code generation and use through the authority;
- WebAuthn registration, login, sign-count persistence, and multi-edge continuity;
- requested OIDC/SAML attribute release;
- separate edge Redis and authority Redis domains;
- default SAML SSO and SP-initiated SLO through a local SAML test SP;
- negative SAML checks for malformed SSO input and invalid SLO payload shape;
- negative OIDC, device-code, CSRF, session, token, and WebAuthn attack paths.
Upgrade Checklist
- Back up your current 2.1.x configuration and Redis data.
- Convert a copy of the configuration with
scripts/convert-config-v1-to-v2.py. - Read the converter report and resolve all warnings or dropped paths.
- Replace legacy roots with
runtime,observability,storage,auth, andidentity. - Move Lua features and filters to environment and subject sources.
- Rename Lua plugin directories, callbacks, and constants.
- Review generated
auth.policychecks and policies. - Add explicit scheduler guards for any intentional internal-source bypasses.
- Validate with
nauthilus --config-check. - Compare
nauthilus -noutput against the intended current config. - Run your IdP, mail-auth, Lua, Redis, OIDC, SAML, and MFA smoke tests.
- If you use the production container image, update operational debugging assumptions for the
scratchruntime. - If you adopt split identity proxy mode, validate edge/authority Redis separation, mTLS, caller-token scopes, backend references, MFA, WebAuthn, OIDC, and SAML before production traffic.
Operator Notes
- Standalone deployments remain supported. Split identity proxy mode is optional.
- OpenAPI runtime request validation is default-off and should be enabled only after verifying the operation allowlist.
auth.policycan be introduced in checks-only form before custom policy decisions become authoritative.mode: observeis useful for comparing custom policy behavior before switching relevant stages to production authority.- The 3.0.0 beta should be validated against real deployment configuration, because the largest risks are migration-specific.