Netatalk 4.5.0 is available!
The Netatalk team is proud to announce the first stable version in the Netatalk 4.5 release series – one of the most feature-packed releases in the history of this project!
This release focuses on three large areas: making Finder search usable out of the box, rebuilding the AFP directory cache for much larger and faster workloads, and tightening security across authentication, filesystem handling, parsers, and build defaults. It also brings a new SRP authentication UAM, a pluggable Spotlight backend architecture, a modernized afpstats interface, and many portability improvements for Unix-like platforms.
All users of previous Netatalk versions are encouraged to upgrade to 4.5.0.
Highlights
- Spotlight-compatible Finder search now works by default. Netatalk enables
spotlightandsearch dbby default, uses the lightweightcnidbackend by default, and can also buildlocalsearchand experimentalxapianbackends. - Directory caching has been substantially rebuilt. The cache now supports ARC eviction, up to 1 million entries, enumerate caching, AppleDouble metadata caching, inter-process cache hints, background maintenance, and optional resource fork caching.
- Security hardening lands throughout the tree. This includes fixes for multiple CVEs, stricter bounds checks in AFP/DSI/CNID/Spotlight paths, constant-time Randnum comparisons, safer privilege transitions, strict symlink validation, and safer defaults for legacy authentication.
- SRP authentication is now available as
uams_srp.so.afppasswdnow manages SRP verifiers by default while retaining explicit legacy Randnum mode with-r. - Classic Mac OS support continues to improve with virtual root
Icon\rsynthesis which enables color icons over AFP. - Build and portability work adds libev support as an alternative to libevent2, new Meson feature switches, mandatory dconf handling for LocalSearch indexing, improved NetBSD/OpenBSD support, and a simpler Unix socket based afpstats implementation.
Spotlight and Search
Netatalk 4.5.0 introduces a pluggable Spotlight search architecture. The AFP Spotlight RPC layer is shared, while each volume can choose a backend through spotlight backend.
The default backend is now cnid. It uses Netatalk’s CNID database for fast filename-oriented Finder search, with no external indexing service beyond the normal CNID backend and the Spotlight parser dependencies. This makes Finder search useful on typical file servers without requiring LocalSearch/Tracker.
The localsearch backend remains available for richer metadata and content search. It now uses dconf keyfiles for indexer configuration; dconf is a mandatory dependency for this backend, and the LocalSearch indexer is started only when a volume is configured to use it.
The new xapian backend is experimental. It maintains a Netatalk-managed per-volume Xapian index for filename, plain-text content, and MIME type search. It is useful for testing and feedback, but is not recommended for production deployments yet.
Spotlight query behavior has also been improved. CNID, SQLite, and MySQL backed searches can return up to 10000 results per query, or as many as fit within a 10-second wall-clock budget. Wildcard queries, timestamps, additional attributes, and macOS Tahoe search paths in nested arrays are handled more robustly. Finder Spotlight filename queries shorter than 3 characters are ignored by the Spotlight backend.
Directory Cache
The directory cache is now a multi-layer cache for directory entries, file metadata, AppleDouble metadata, and optionally resource fork data. The goal is to reduce filesystem I/O during directory enumeration and metadata-heavy AFP workloads, especially on shares with many small files.
The new dircache mode = arc option enables an Adaptive Replacement Cache that learns from both recent and frequent access patterns. ARC is more memory hungry than the default LRU mode, but it is better at resisting sequential scans and backup jobs that would otherwise flush useful cache entries.
Netatalk also gained enumerate caching, AppleDouble support in cache, inter-process cache synchronization between afpd children, a tier-2 resource fork cache, and an idle worker for background cache maintenance. Cache entries are still updated for AFP operations, while dircache validation freq lets administrators tune how aggressively Netatalk validates cached entries against changes made outside AFP.
Security and Compatibility
This release includes fixes and hardening for authentication, Unicode and charset handling, LDAP filter construction, VFS metadata parsing, DSI session handling, Spotlight unmarshalling, CatSearch request parsing, CNID database operations, and papd print job handling.
Notable security-facing changes include:
DHCAST128/uams_dhx.sois no longer part of the defaultuam list. Administrators who still need it for old Classic Mac OS clients must opt in.- The insecure
admin auth useroption has been removed. - Randnum UAM comparisons now use constant-time secret comparison helpers, key material is cleared more deliberately, and Randnum password updates require a valid companion
afppasswd.keyfile. convert appledoubleis nownoby default to avoid paying the migration cost on every filesystem access. Enable it only for on-the-fly migration from AppleDouble v2 metadata to filesystem extended attributes.- Symlink creation and following are stricter. Absolute targets,
..components, paths escaping the volume root, and cross-device targets are rejected. - Nested AFP volume paths are rejected to avoid CNID corruption scenarios.
- Server quantum parsing is stricter, and several wire-format parsers now reject truncated or oversized inputs earlier.
The libatalk ABI changed in this release. cnid_find() gained a bool *more_available out-parameter and now requires a 400-byte minimum result buffer. The libatalk soversion is bumped to v20, so out-of-tree consumers must be rebuilt against the 4.5 headers. The internal server_child_t ABI also changed because the afpstats handler now runs in the parent’s main event loop.
Authentication
Netatalk now includes an SRP (“Secure Remote Password”) UAM as uams_srp.so. SRP uses separate salts and verifiers rather than system passwords, and provides strong password authentication without sending the password over the network.
afppasswd now operates in SRP mode by default and writes the SRP verifier file afppasswd.srp, or the path set with srp passwd file. To manage legacy Randnum credentials, pass afppasswd -r. In Randnum mode, afppasswd -r -c creates or validates the required companion key file.
Randnum and Two-Way Randnum remain available for very old AFP clients, but are discouraged. They require the legacy passwd file and companion key file, and authentication fails until both are present and valid.
CNID and Volume Management
The new global cnid scheme setting lets administrators define the default CNID backend once in [Global], while still allowing per-volume overrides. The sqlite backend continues to mature, MySQL CNID handling has improved charset and TCP behavior, and both MySQL and SQLite now support cnid dev = no.
Volumes can now set a stable UUID explicitly with volume uuid. This is useful when running afpd without permission to write the shared state directory, or when administrators need a fixed volume identity across deployments.
The obsolete last CNID backend has been removed.
Admin Tools
afpstats has been rewritten to use a Unix domain socket instead of D-Bus. This removes the GLib/D-Bus dependency for statistics collection and makes the tool simpler to use in minimal server environments. Runtime statistics are enabled with afpstats = yes; access can be delegated with afpstats group, and afpstats -s can query a non-default socket path. Sessions connected over both TCP/IP and AppleTalk are now reported.
The historical macusers script has been removed. Use afpstats instead.
The nad utility gained mkdir and rmdir, a -F option for reading a custom afp.conf, safer and cleaner ls output, support for ls -a, and improved behavior for operations crossing AFP volume boundaries.
dbd gained -i to invalidate AppleDouble CNID hints.
afp.conf Changes
The most important new and changed afp.conf options in 4.5.0 are:
| Option | Scope | Default | Status |
|---|---|---|---|
spotlight |
G/V | yes |
Changed default; enables Spotlight-compatible Finder search globally or per volume. |
search db |
V | yes |
Changed default; uses CNID database name search for Catalog Search. |
spotlight backend |
G/V | cnid |
New; selects cnid, localsearch, or xapian per volume. |
spotlight attributes |
G | empty | Limits searchable attributes for the localsearch backend only. |
sparql results limit |
G | unlimited | Also applies as the per-query cap for the xapian backend. |
volume uuid |
V | generated | New; assigns a static UUID to a volume. |
cnid scheme |
G/V | build default | New global default with per-volume override for dbd, mysql, or sqlite. |
cnid dev |
V | yes |
MySQL and SQLite now support cnid dev = no. |
dircache size |
G | 65536 |
Replaces dircachesize; accepts 1024 through 1048576 entries. |
dircache validation freq |
G | 1 |
New tuning control; validates every Nth cache access, range 1-100. |
dircache mode |
G | lru |
New; selects lru or arc eviction. |
dircache rfork budget |
G | 0 |
New; total KB budget for resource fork caching, disabled at 0. |
dircache rfork maxsize |
G | 1024 |
New; maximum KB size of a single cached resource fork. |
convert appledouble |
V | no |
Changed default; enable only for dynamic AppleDouble migration. |
follow symlinks |
V | no |
Stricter validation rejects unsafe and cross-device symlink targets. |
uam list |
G | uams_dhx2.so |
uams_srp.so is available; uams_dhx.so/DHCAST128 is no longer default. |
srp passwd file |
G | afppasswd.srp |
New; selects the SRP verifier file used by uams_srp.so. |
passwd file |
G | afppasswd |
Now specifically the legacy Randnum password file. |
afpstats group |
G | unset | Sets group ownership for the afpstats socket. |
Removed options:
admin auth userdircache files- superseded dircache metadata window/threshold parameters
Meson Build Options
Meson v0.62.0 and later is now required, previously v0.61.2.
The most important new and changed Meson options in 4.5.0 are:
| Option | Default | Status |
|---|---|---|
-Dwith-spotlight-backends=cnid,localsearch,xapian |
all three | New; selects which Spotlight backends to build. |
-Dwith-eventloop=libevent or libev |
auto | New; prefers libevent, while libev is now supported as an alternative. |
-Dwith-fce=true/false |
true |
New compile-time switch for Filesystem Change Event support; disable for slight performance gain. |
-Dwith-subprojects=true/false |
false |
New; forces Meson subprojects to build even when a system dependency exists. |
For the localsearch Spotlight backend, dconf is now required in addition to the LocalSearch/Tracker, TinySPARQL, GLib/GIO, D-Bus, flex, bison, and talloc dependencies. For the xapian backend, xapian-core, libmagic/libfile, and talloc are required.
CVEs
A list of CVEs fixed in this release.
CVE-2026-7835, CVE-2026-7836, CVE-2026-7837, CVE-2026-44053, CVE-2026-44056, CVE-2026-44058, CVE-2026-44059, CVE-2026-44061, CVE-2026-44063, CVE-2026-44065, CVE-2026-44067, CVE-2026-44069, CVE-2026-44070, CVE-2026-44071, CVE-2026-44072, CVE-2026-44073, CVE-2026-44074, CVE-2026-44075, CVE-2026-49387, CVE-2026-49388, CVE-2026-49389, CVE-2026-49390
Installation
netatalk-4.5.0.tar.xz is the Netatalk source distribution. See INSTALL for required dependencies, then build with:
# Extract the source
tar -xf netatalk-4.5.0.tar.xz
cd netatalk-4.5.0
# Configure and build
meson setup build
meson compile -C build
# Install
sudo meson install -C build
netatalk-4.5.0.wbm.gz is the Webmin module tarball. To install the module:
# Adjust the path to match your Webmin installation
/usr/share/webmin/install-module.pl netatalk-4.5.0.wbm.gz
What’s Changed
- IPC-Hints: dircache hints relay now batches IPC writes by @andylemin in #2831
- afpd: log TCP buffer sizes at session start and close by @andylemin in #2852
- dircache: increase defer queue to 1024 and make cache hint send non-blocking by @andylemin in #2853
- afpd: silence unwanted warning when legacy icon is unset by @rdmark in #2857
- uams: make PAM UAMs compatible with OpenBSD and OpenPAM by @rdmark in #2854
- meson: fix quota support on NetBSD by detecting libquota correctly by @rdmark in #2858
- libatalk: fix IPv4 interface detection and connectivity on NetBSD by @rdmark in #2859
- afpd: make signal handlers async-signal-safe to fix crash on macOS by @rdmark in #2860
- uams: log explicit warnings on successful ClearText auth by @rdmark in #2861
- libatalk: reject nested volume paths to prevent CNID crash by @rdmark in #2862
- docs: remove ‘include’ parameter description from afp.conf manpage by @rdmark in #2865
- netatalk: support libev as alternative to libevent2 by @rdmark in #2869
- uams: use portable sigaction initialization in PAM SIGCHLD handling by @rdmark in #2864
- id caching: cache getpid() and geteuid() in AFPObj to eliminate redundant syscalls by @andylemin in #2870
- idle_worker: replace condvar with nanosleep to eliminate high cadence syscall and futex by @andylemin in #2874
- meson: make FCE a compile-time build option by @andylemin in #2872
- spotlight: Fix timestamps and add additional attributes by @NJRoadfan in #2878
- docs: fix typos in afp_spectest man page by @rdmark in #2881
- add SRP user authentication method by @rdmark in #2876
- libatalk: map logtype identifiers correctly with the enum by @rdmark in #2898
- afpd: reap idle Spotlight queries to prevent resource leaks by @rdmark in #2901
- afpd: use utimensat when storing kMDItemLastUsedDate for Spotlight by @rdmark in #2897
- afpd: improved Spotlight RPC logic and bugfixes by @rdmark in #2900
- timelord: Fix local time offset when DST is in effect. by @NJRoadfan in #2895
- netatalk: replace gsettings with dconf keyfile for indexer config by @rdmark in #2902
- afpd: handle Spotlight search paths in nested arrays by @rdmark in #2916
- docs: build Doxygen docs for the yacc and lexer code by @rdmark in #2917
- docker: load RandNum/SRP UAMs only when password init succeeds by @rdmark in #2918
- dbd: add -i option to invalidate AppleDouble CNID hints by @rdmark in #2863
- afpd: add support for Spotlight wildcard queries with SPARQL by @rdmark in #2915
- rename legacy icon hagar->viking by @rdmark in #2925
- afpd: Adjust date-time values for Apple II clients. by @NJRoadfan in #2906
- webmin: tweaks and improvements to the Webmin module by @rdmark in #2933
- docs: refine case sensitivity description in afp.conf man page by @rdmark in #2931
- libatalk: fix chained log level config producing inconsistent log output by @rdmark in #2936
- afpd: introduce pluggable Spotlight search backend architecture by @rdmark in #2923
- afpd: Update file attribute handling for AFP 1.1 clients by @NJRoadfan in #2934
- afpd: align invalid reference errors with AFP 3.4 by @rdmark in #2929
- netatalk: leverage D-Bus session bus auto activation for localsearch by @rdmark in #2938
- fix a handful of subtle code quality bugs in spotlight code by @rdmark in #2939
- afpd: ProDOS Info cleanup. by @NJRoadfan in #2944
- testsuite: Add additional ProDOS Info Bit (PDINFO) tests. by @NJRoadfan in #2941
- libatalk: avoid misaligned ifreq access in getifaces by @rdmark in #2943
- introduce a Spotlight backend built on Xapian by @rdmark in #2940
- netacnv: fix off-by-one that dropped the last -o flag by @rdmark in #2954
- spotlight: overhaul localsearch SPARQL generation to bypass libtinysparql crash by @rdmark in #2952
- meson: use normalized localstatedir path for spooldir path by @rdmark in #2960
- meson: put spooldir creation behind statedir creation flag by @rdmark in #2962
- testsuite: Refine when testing against Apple AFP servers. by @NJRoadfan in #2955
- afpd:idle_worker: relax wake interval to 10ms and expand deferred queue by @andylemin in #2967
- spotlight: use the cnid backend in the default configuration by @rdmark in #2968
- meson: refactor D-Bus path detection logic by @rdmark in #2969
- docker: dbus-daemon not needed in production container by @rdmark in #2970
- update Spotlight search capabilities in container readme by @rdmark in #2971
- docker: introduce AFP_UAMS option for fine grained control of UAMS by @rdmark in #2976
- uams: require afppasswd key file for Randnum UAM by @rdmark in #2974
- netatalk: start localsearch indexer only when configured as spotlight backend by @rdmark in #2980
- afpd: harden uam_random_string to return only truly random values by @rdmark in #2983
- docs: flesh out documentation for the server message feature by @rdmark in #2982
- sys/netatalk: validate DDP datagram lengths by @orbisai0security in #2984
- afpd: fix connection limit off-by-one condition by @rdmark in #2985
- post-security patching improvements and bug fixes by @rdmark in #2991
- docs: revise client support details for deprecated UAMs in manual by @rdmark in #2994
- afppasswd: manage Randnum key files programmatically by @rdmark in #2995
- address a handful of code quality bugs flagged by static analysis by @rdmark in #2997
- libatalk/vfs: guard EA name arguments by @rdmark in #2998
- libatalk/util: create constant time helper for safe secrets comparison by @rdmark in #2999
- spotlight/testsuite: raise Spotlight result cap to 10000 with paginated cnid_find by @andylemin in #3001
- cnid: add credits blurb to sqlite implementation by @rdmark in #3004
- testsuite: overhaul DSI test client and expand logintest by @rdmark in #2992
- afpd: harden follow symlinks against cross-device targets by @rdmark in #3006
- docs: list all available legacy icon styles in afp.conf man page by @rdmark in #3007
- docs: touch up language in documentation by @rdmark in #3008
- docs: update default UAM list in Upgrading.md by @rdmark in #3009
- webmin: set standard UAM to DHX2 and read dynamically from defaults by @rdmark in #3010
- afpd: don’t log UAM continuations as failures by @rdmark in #3021
- afpd: let sleeping sessions handle deferred reconnects by @rdmark in #3023
- afpd: rework afpstats to drop D-Bus and reveal ASP sessions by @rdmark in #3018
- cnid: make name search match substrings in DBD backend by @rdmark in #3022
- distrib: pin to specific Webmin version in container build by @rdmark in #3025
- distrib: harden container CNID MySQL setup by @rdmark in #3028
- webmin: Add xapian spotlight backend by @NJRoadfan in #3030
- afpd: report client address in afpstats by @rdmark in #3029
- webmin: centralize select builder options in core library by @rdmark in #3031
- spotlight: drain ready localsearch callbacks on fetch by @rdmark in #3032
- afp.conf: default cnid server host-only port by @rdmark in #3036
- test: report afpd integration checks with TAP by @rdmark in #3037
- meson: introduce a -Dwith-docs-only option by @rdmark in #3039
- docs: import YAML::PP preserve constant directly by @rdmark in #3041
- meson: generate compilation doc on the fly, don’t store in git by @rdmark in #3042
- meson: Fix detection of libatomic by @NJRoadfan in #3044
- docs: improve Japanese localization wordings and grammar by @rdmark in #3047
- move containers readme to repository root by @rdmark in #3048
New Contributors
- @orbisai0security made their first contribution in #2984
Full Changelog: https://github.com/Netatalk/netatalk/compare/netatalk-4-5-0beta…netatalk-4-5-0
Downloads
- netatalk-4.5.0.tar.xz (1.2 MB)
- netatalk-4.5.0.tar.xz.asc (0.0 MB)
- netatalk-4.5.0.tar.xz.sha256sum (0.0 MB)
- netatalk-4.5.0.tar.xz.sha512sum (0.0 MB)
- netatalk-4.5.0.wbm.gz (0.1 MB)
- netatalk-4.5.0.wbm.gz.asc (0.0 MB)
- netatalk-4.5.0.wbm.gz.sha256sum (0.0 MB)
- netatalk-4.5.0.wbm.gz.sha512sum (0.0 MB)
Footnotes
Release published on 2026-05-30
Generated from GitHub Release Notes