Skip to main content
Version: Next

1.9.x Release Notes

This page summarizes notable changes in the 1.9 minor series. Patch-level releases are listed below.

1.9.12

Date: 2025-10-15

Build and packaging changes focusing on optional Hydra/OIDC integration.

Highlights:

  • Hydra/OIDC is now gated behind a Go build tag: hydra. The default build (no tags) excludes Hydra, OAuth2/OIDC flows, and their dependencies.
  • 2FA (TOTP) and WebAuthn frontend flows are compiled and registered only with the hydra build tag.
  • Docker images are built without Hydra by default. To include Hydra, build your own image with BUILD_TAGS=hydra.
  • OAuth2/Claims processing has been compile-time isolated. Non-hydra builds remain lean and keep JWT-based service authentication fully intact.

How to build:

  • Without Hydra (default):
    • go build -mod=vendor ./server
    • go test ./...
  • With Hydra enabled:
    • go build -mod=vendor -tags hydra ./server
    • go test -tags hydra ./...

Docker build examples:

  • Default (no Hydra):
    • docker build -t nauthilus:1.9.12 .
  • With Hydra enabled:
    • docker build --build-arg BUILD_TAGS=hydra -t nauthilus:1.9.12-hydra .

Operational impact:

  • Endpoints for login/consent/device/webauthn and registration are only present in hydra builds. In non-hydra builds these endpoints are not registered (or return 404 via stubs).
  • Configuration under the oauth2 section is only effective when built with hydra. It is ignored otherwise.
  • Service-internal JWT authentication for REST/Admin endpoints is unaffected and always available.

Documentation updates:

  • See Installation → Compiling for build-tag guidance.
  • See Installation → Docker for Hydra-enabled image builds.

1.9.10

Date: 2025-09-29

Cold-start grace for brute-force (precision, multi-instance safe)

A new mechanism prevents immediate lockouts right after cache flushes or password changes when multiple devices may still send the old password in parallel. The system grants a one-time, per-IP grace for known accounts without negative password history while atomically seeding evidence so that Repeating‑Wrong‑Password can short-circuit concurrent first attempts without inflating generic buckets.

Highlights:

  • One-time grace per scoped IP, then normal enforcement resumes within the configured TTL.
  • Atomic Redis Lua script seeds a per-password key alongside the grace key to eliminate races in parallel scenarios.
  • Safe in multi-instance deployments via shared Redis and EVALSHA script management.

New configuration (disabled by default):

brute_force:
cold_start_grace_enabled: true # Enable one-time grace for known accounts without negative PW history
cold_start_grace_ttl: 120s # Grace window (recommended 60–180s)

Behavior:

  • First failed attempt from an IP (scoped consistently with RWP and IPv6 ip_scoping): learn metadata, do not enforce yet.
  • Concurrent first attempts are recognized via the atomic seed and treated as repeating wrong password.
  • From the next attempt within the TTL: enforcement resumes so complex buckets fill/trigger as usual.

Documentation:

  • Configuration reference updated: /docs/configuration/brute-force#brute_forcecold_start_grace_enabled-v1910

1.9.9

Date: 2025-09-24

Highlights:

  • Brotli response compression middleware, aligned with existing zstd middleware semantics (skipper, exclusions, min_length).
  • Brotli request decompression: Requests with Content-Encoding: br are automatically decompressed when compression is enabled.
  • Algorithm selection by preference order now supports br in addition to zstd and gzip.
  • Configuration options extended with level_brotli to control Brotli compression strength.
  • Deprecated server.compression.level (gzip) in favor of server.compression.level_gzip for consistency.

Configuration changes:

  • server.compression.algorithms may now include "br" (Brotli). Example:
server:
compression:
enabled: true
algorithms: ["br", "zstd", "gzip"]
  • New: server.compression.level_brotli (0..3) maps to middleware levels similar to zstd:
    • 0 = DefaultCompression
    • 1 = BestSpeed
    • 2 = BetterCompression
    • 3 = BestCompression
server:
compression:
enabled: true
algorithms: ["br", "zstd", "gzip"]
level_brotli: 2
  • Deprecated: server.compression.level → Use server.compression.level_gzip instead (still accepted for backward compatibility).
server:
compression:
# Deprecated, prefer level_gzip
level: 6
# New
level_gzip: 6
  • Existing: level_zstd (0..3) and min_length remain available and unchanged.

For the full description of options, see the Server Configuration: /docs/configuration/server-configuration#compression-configuration

Behavior:

  • Only one response compression algorithm is active at a time, chosen by the configured algorithms order and the client’s Accept-Encoding.
  • Request decompression now covers gzip, zstd (zstd/zst/zstandard), and Brotli (br) when compression is enabled.
  • The /metrics endpoint continues to disable response compression to avoid double compression by Prometheus.

Implementation notes:

  • Brotli compression implemented using github.com/andybalholm/brotli.
  • Zstandard compression implemented using github.com/klauspost/compress/zstd.

Migration notes:

  • If you previously set server.compression.level, migrate to server.compression.level_gzip.
  • To enable Brotli for compatible clients, add "br" to server.compression.algorithms and optionally configure level_brotli.

Thanks: Thanks to all contributors and users for feedback leading to this improvement in performance and bandwidth efficiency.

1.9.8

Date: 2025-09-23

Highlights:

  • Zstandard (zstd) response compression via a new middleware (analog to gin-contrib/gzip).
  • Zstandard request decompression: incoming requests with Content-Encoding: zstd/zst/zstandard are automatically decompressed when compression is enabled.
  • Configurable algorithm preference and zstd levels via new configuration keys.

Details:

  • New config keys under server.compression:
    • algorithms: ordered list of enabled algorithms (e.g., ["zstd", "gzip"]). Only one algorithm is applied per response; the first supported by the client wins.
    • level_zstd: integer mapping for zstd encoder levels (0=DefaultCompression, 1=BestSpeed, 2=BetterCompression, 3=BestCompression).
    • min_length: remains supported to avoid compressing very small responses.
  • Gzip keeps using the existing level (1..9). The deprecated content_types remains ignored (since 1.9.2) and should be removed from configs.
  • Implementation uses klauspost/compress v1.18.0 for zstd.
  • The /metrics endpoint keeps compression disabled to avoid double compression with Prometheus.

Docs:

  • Configuration reference updated with algorithms, level_zstd, and examples.
  • Full configuration example updated accordingly.

1.9.5

Date: 2025-09-11

Breaking change (JSON REST): protocol replaces service

  • The JSON authentication endpoint (POST /api/v1/auth/json) now uses the field protocol (e.g., "imap", "smtp", "pop3", "http") to determine the application protocol.
  • The JSON field service no longer controls protocol selection and is ignored by this endpoint.
  • Header-based (/api/v1/auth/header) and form-based (application/x-www-form-urlencoded) endpoints are unchanged.

Migration for JSON clients:

  • Replace "service": "imap" with "protocol": "imap" in request payloads.
  • If you previously relied on service to switch behavior, make sure to provide protocol explicitly. If omitted, Nauthilus will apply internal defaults, which may not match your intended workflow.

Documentation updates:

  • REST API documentation updated to reflect the protocol field and to highlight this change.

1.9.4

Date: 2025-09-11

IPv6 ip_scoping for Repeating‑Wrong‑Password and Tolerations

Two new configuration options allow aggregating IPv6 addresses by network rather than strict /128 in contexts where privacy extensions commonly rotate interface identifiers. This improves stability of detection for IPv6 households and multi-device environments.

Added under brute_force.ip_scoping:

  • rwp_ipv6_cidr — Applies to Repeating‑Wrong‑Password (PW_HIST) lookups and counters.
  • tolerations_ipv6_cidr — Applies to Tolerations keys and housekeeping.

Behavior:

  • When set to a value > 0 (range 1..128), IPv6 addresses are normalized to the configured network CIDR (e.g., 2001:db8::/64) for the respective subsystem. IPv4 behavior is unchanged.
  • Defaults to 0 (disabled) to keep legacy behavior (/128) unless explicitly enabled.

Example:

brute_force:
ip_scoping:
rwp_ipv6_cidr: 64
tolerations_ipv6_cidr: 64

Related changes:

  • Cache flush is aware of ip_scoping: /api/v1/cache/flush now removes both raw (/128) and CIDR-scoped variants of keys so that no scoped keys linger in Redis after a user flush.

Stability fix for Repeating‑Wrong‑Password after cache flush

A logic fix prevents immediate brute-force bucket increments when the negative password history is empty for a known account (e.g., right after a cache flush or first failed attempt). In this situation, the system now gracefully learns client IP metadata (protocol/OIDC) and avoids enforcement that could lead to self-lockout.

Notes:

  • This change only affects the path where the account exists but no negative password history is present.
  • Normal brute-force detection and enforcement remain unchanged in other scenarios.

New option: brute_force.pw_history_for_known_accounts

Reduce PW_HIST write amplification for already‑blocked (cached) requests. When enabled, Nauthilus only writes account‑scoped PW_HIST for verified accounts (no fallback to raw usernames). IP‑wide PW_HIST remains unchanged.

Why this can be useful:

  • Significantly reduces Redis key footprint and write load during credential‑stuffing with rotating/non‑existent usernames.

Minimal risk:

  • After unlock or cache flush, the missing per‑username PW_HIST for unknown usernames removes a small quick‑skip signal for "repeating wrong password". Buckets may increment a bit sooner until context is re‑learned; metrics/forensics for such usernames are less granular.

Config:

brute_force:
pw_history_for_known_accounts: true

Documentation

  • Configuration reference updated to include brute_force.ip_scoping options and examples.
  • Full configuration example extended with ip_scoping.

1.9.3

Maintenance and minor improvements.

1.9.2

Maintenance and minor improvements.

1.9.1

Maintenance and minor improvements.

1.9.0

Initial 1.9 release.