Skip to main content
Version: Next

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.policy decision 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, and request.caller.ip.source to match the direct caller seen by Nauthilus.
  • Request policies can now use request.local.ip, request.local.ip.present, request.local.port, and request.local.port.present to match the local server endpoint reported by the request adapter.
  • LDAP authentication records auth.master_user.active with master_user and target_user details for master-user authenticate requests.
  • Lua backends can emit the built-in master-user fact through nauthilus_policy.emit_master_user(...).

Management API

  • Brute-force list endpoints expose limit and offset query parameters.
  • Brute-force list responses include page metadata with limit, offset, next_offset, and has_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_mechanism directly on each target.
  • Supported target values are auto, PLAIN, LOGIN, USERPASS, and BASIC.
  • auto discovers protocol capabilities where available and selects an executable mechanism through a shared selector.
  • SMTP and LMTP read EHLO/LHLO AUTH; IMAP reads CAPABILITY and AUTH=<mech>; POP3 reads CAPA, SASL ..., and native USER; Sieve evaluates post-STARTTLS capabilities; HTTP uses a static BASIC adapter.
  • Unsupported mechanisms such as SCRAM-*, OAUTHBEARER, XOAUTH2, EXTERNAL, CRAM-MD5, and DIGEST-MD5 are 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_DIR and NAUTHILUS_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-IR is 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

  • /metrics can now be protected with dedicated Basic Auth under observability.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 require state 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:

  1. Read the Config v2 Migration Guide.
  2. Convert legacy single-file YAML with scripts/convert-config-v1-to-v2.py from the Nauthilus server repository.
  3. Review the generated migration report manually.
  4. Validate the converted file with nauthilus --config-check.
  5. Compare canonical non-default output with nauthilus -n.
  6. 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:

  • runtime
  • observability
  • storage
  • auth
  • identity

Legacy public roots from the 2.1 line are not part of the current surface anymore:

  • server
  • ldap
  • lua
  • idp
  • realtime_blackhole_lists
  • relay_domains
  • brute_force
  • backend_server_monitoring
  • cleartext_networks

Common path migrations include:

Before 3.0.03.0.0 and newer
server.addressruntime.servers.http.address
server.tlsruntime.servers.http.tls
server.timeoutsruntime.timeouts
server.logobservability.log
server.redis.masterstorage.redis.primary
server.default_http_request_headerauth.request.headers
server.basic_authauth.backchannel.basic_auth
server.oidc_authauth.backchannel.oidc_bearer
server.backendsauth.backends.order
ldap.configauth.backends.ldap.default
lua.configauth.backends.lua.backend.default
idp.oidcidentity.oidc
idp.saml2identity.saml
backend_server_monitoringauth.services.backend_health_checks
brute_forceauth.controls.brute_force
realtime_blackhole_listsauth.controls.rbl
relay_domainsauth.controls.relay_domains
cleartext_networksauth.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.checks controls fact collection, Lua execution scope, auth-state guards, and check ordering.
  • auth.policy.policies controls decision effects.
  • mode: observe compares configured policies without changing production output.
  • mode: enforce allows 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.03.0.0 and newer
lua.featuresauth.policy.attribute_sources.lua.environment
lua.filtersauth.policy.attribute_sources.lua.subject
lua.actionsauth.policy.obligation_targets.lua.actions
lua.custom_hooksauth.controls.lua.hooks
lua-plugins.d/featureslua-plugins.d/environment
lua-plugins.d/filterslua-plugins.d/subject
nauthilus_call_feature(request)nauthilus_call_environment(request)
nauthilus_call_filter(request)nauthilus_call_subject(request)
FEATURE_* constantsENVIRONMENT_* constants
FILTER_* constantsSUBJECT_* 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, or curl inside the stable runtime image;
  • use the debug image for shell-oriented troubleshooting;
  • the stable image defaults to TZ=UTC;
  • ZONEINFO and SSL_CERT_FILE are 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 -d prints canonical defaults.
  • nauthilus -n prints canonical non-default values from a loaded config.
  • --dump-format canonical|yaml|json|toml selects structured dump output.
  • Secrets are redacted by default and can be shown with -P when 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.
  • --validate runs nauthilus --config-check against the converted output.
  • --dry-run --stdout prints 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_auth default 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, and i18n sources.

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.AuthService
    • Authenticate
    • LookupIdentity
    • ListAccounts
  • 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_endpoint OpenAPI 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

  1. Back up your current 2.1.x configuration and Redis data.
  2. Convert a copy of the configuration with scripts/convert-config-v1-to-v2.py.
  3. Read the converter report and resolve all warnings or dropped paths.
  4. Replace legacy roots with runtime, observability, storage, auth, and identity.
  5. Move Lua features and filters to environment and subject sources.
  6. Rename Lua plugin directories, callbacks, and constants.
  7. Review generated auth.policy checks and policies.
  8. Add explicit scheduler guards for any intentional internal-source bypasses.
  9. Validate with nauthilus --config-check.
  10. Compare nauthilus -n output against the intended current config.
  11. Run your IdP, mail-auth, Lua, Redis, OIDC, SAML, and MFA smoke tests.
  12. If you use the production container image, update operational debugging assumptions for the scratch runtime.
  13. 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.policy can be introduced in checks-only form before custom policy decisions become authoritative.
  • mode: observe is 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.