Dev Docs Netatalk Configuration

Netatalk Configuration System

Audited against Netatalk d63155e13 on 2026-10-10. This describes the current source checkout; older releases may differ.

Parsing and source

afp.conf is an INI file parsed through iniparser. Build-time selection can use a system dependency or a Meson subproject; it is not an in-tree libatalk/iniparser library.

File Responsibility
config/afp.conf.in Installed configuration template
libatalk/util/netatalk_conf.c Shared option parsing, validation, volume construction, substitution
include/atalk/netatalk_conf.h Public configuration API
include/atalk/iniparser_util.h Compatibility types/macros and section names
include/atalk/globals.h AFPObj, afp_options, global flags/defaults
include/atalk/volume.h Volume structure and flags
etc/afpd/afp_options.c AFP command-line parsing
etc/afpd/afp_config.c Listener, authentication, FCE setup
doc/manpages/man5/afp.conf.5.md Maintained user-facing option reference

Examples below use keys actually consumed by this checkout. Installation paths depend on Meson settings; source defaults containing _PATH_* are build substitutions.

Sections and inheritance

[Global]
server name = My Server
vol preset = defaults

[defaults]
ea = sys
unix priv = yes

[Shared Documents]
path = /srv/documents
valid users = @staff

[Homes]
basedir regex = /home
home name = $u's home

INISEC_GLOBAL and INISEC_HOMES are the special section names. Ordinary sections define volumes; preset sections supply common volume options.

Internal getoption_str(), getoption_strdup(), getoption_bool(), and getoption_int() try the volume section, then the selected preset, then a caller-supplied default. vdgoption_* variants additionally fall back to [Global]. Global inheritance therefore depends on the option’s lookup path; not every volume key placed under Global becomes a volume default.

Some fields use parsed global values as their defaults (for example charsets), and vol dbpath has special Global-path handling. Follow creatvol() for the actual precedence. INIPARSER_GETSTR() returns dictionary-owned strings; duplication helpers transfer a heap copy to the caller.

Loading flow

afp_config_parse() loads the dictionary, initializes logging early, parses Global options, validates numeric bounds/aliases, and sets up charsets and extension mappings. The controller and AFP parent each parse their own configuration; -F is passed to the child process.

load_afp_conf_vols() reads volume sections and builds struct vol through creatvol(). The public loader was formerly named load_volumes().

Load flag Purpose
LV_DEFAULT Session-context loading with authorization filtering
LV_ALL Load definitions without ordinary user access checks
LV_FORCE Force reload despite the timestamp check

creatvol() resolves presets, authorization, paths, storage, charsets, UUIDs, and flags. Duplicate/nested paths and initialization failures are logged and can cause volumes to be skipped.

Identity, authentication, and logging

Global key Field/behavior Default
hostname hostname System hostname
server name servername Hostname fallback
uam list uamlist uams_dhx2.so
uam path uampath _PATH_AFPDUAMPATH
guest account guest nobody
valid shellcheck OPTION_VALID_SHELLCHECK yes
passwd file passwdfile, legacy Randnum _PATH_AFPDPWFILE
srp verifier path srpverifierpath, directory _PATH_AFPSRPVERIFIERPATH
save password, set password passwdbits yes, no
k5 service, k5 realm, k5 keytab, fqdn Kerberos/GSS setup Unset
login message loginmesg Unset
log level logconfig default:note
log file logfile Unset
log microseconds log_us_timestamp yes

admin group, force user, and force group are Global identity controls. Admin-group and forced-identity settings are rejected in single-user mode. LDAP keys configure ACL UUID lookup, not an AFP password-verification UAM. See Authentication.

Network and session controls

Global key Field Default and units
afp port port 548
afp listen listen Unset; address list
afp interfaces interfaces Unset; interface list
max connections connections 200
tickleval tickleval 30 seconds, minimum 1
timeout timeout 4 tickle intervals, minimum 1
sleep time sleep 10 hours, converted to tickles
disconnect time disconnected 24 hours, converted to tickles
tcpsndbuf, tcprcvbuf tcp_sndbuf, tcp_rcvbuf 0; nonzero byte-size socket requests
server quantum server_quantum 1 MiB; 32,000 bytes–256 MiB
dsireadbuf dsireadbuf 32; incoming readahead multiplier
recvfile OPTION_RECVFILE no; requires compiled splice support
use sendfile Inverse OPTION_NOSENDFILE yes; requires an eligible compiled path
splice size splice_size 1 MiB; bounded 4 KiB–8 MiB and page-rounded

configinit() in etc/afpd/afp_config.c creates DSI listeners. afp listen accepts addresses with optional ports (IPv6+port uses [address]:port); afp port supplies the default. Choose either address-based afp listen or afp interfaces, as documented in afp.conf(5). For example:

[Global]
afp listen = 192.168.1.100, ::1
afp port = 548

The configured DSI buffer product is capped at 1 GiB (NETATALK_READBUF_LIMIT), with address-space checks. A multiplier is first bounded to 6–1,024, then can be reduced below 6 to fit a large quantum. Per-session TCP MSS alignment can adjust the quantum within the growth/max bounds and re-clamp the buffer product. See Performance Tuning.

appletalk, ddp address, and ddp zone require an AppleTalk build. zeroconf defaults to yes and controls advertisements; it does not control authorization.

Caching and multi-protocol policy

Global key Field Default
dircache size dircachesize 65,536 entries; runtime 1,024–1,048,576
dircache mode dircache_mode arc (1); lru is 0
dircache validation freq dircache_validation_freq 100; accepted range 1–100
dircache rfork budget dircache_rfork_budget 32,768 KiB; 0 disables
dircache rfork maxsize dircache_rfork_maxentry 1,024 KiB
strict locking OPTION_STRICT_LOCKING no

Resource-fork budget/max-entry hard caps are 10 GiB/10 MiB, with additional 32-bit overflow protection. Runtime resource-fork budget variables are in bytes, while configuration fields are in KiB.

Volume multi protocol = yes applies defaults through apply_multiprotocol_defaults(): process-wide strict locking becomes yes and validation becomes 1 unless explicitly configured. The volume is excluded from resource-fork caching unless the Global budget was explicitly set. Overrides remain effective and can emit warnings. ea = samba selects storage format separately; it does not enable this policy.

See Caching Architecture and Shared Volumes.

Volume options

Key Field/behavior
path, volume name, vol preset Filesystem path, display name, inherited defaults
valid users, invalid users, hosts allow, hosts deny Authorization filtering
read only, rolist, rwlist Write policy
password, veto files, delete veto files Volume password and veto policy
cnid scheme v_cnidscheme; SQLite default, optional MySQL
vol dbpath v_dbpath; volume directory or Global base path
volume uuid v_uuid; generated registry value when unset/empty
ea EA/storage selection: sys, samba, ad, none, or auto when unset
multi protocol AFPVOL_MULTIPROTO; external-writer coherency defaults
unix priv, acls, chmod request Unix/ACL behavior; chmod preserve default, ignore or simple
umask, directory perm, file perm Octal creation-mode settings
vol charset, mac charset, casefold, case sensitive, illegal seq Filename conversion and case handling
time machine, vol size limit Backup capability and reported capacity limit in MiB
spotlight, spotlight backend Search enablement and compiled backend selection
legacy icon Virtual volume-root icon theme
preexec, postexec, preexec close Lifecycle commands/policy
follow symlinks, invisible dots, network ids, cnid dev Filesystem and advertised-identity policy

A Global vol dbpath without variables gets the volume name appended. A volume/preset vol dbpath selects that directory directly; the default base is the configured state directory’s CNID/.

Volume UUIDs also identify CNID tables, rather than being exclusively Time Machine metadata. Changing format/path/UUID can affect persistent identity and requires appropriate migration; changing a config string does not perform that migration.

Homes and substitution

[Homes] requires basedir regex. home name defaults to $u's home and must include $u; optional path selects a home subdirectory.

volxlate() implements substitutions including $b (basename), $c (client address), $d (volume path), $f (GECOS), $g (group), $h (hostname), $i (client IP), $s (server name), $u (user), $v (volume name), and $$. Expansion depends on the available session/user/path context; do not use user-dependent values where the controller must resolve private state before login.

Spotlight, afpstats, and FCE

Spotlight defaults to enabled for volumes when compiled/available; spotlight backend defaults to cnid, with optional localsearch and xapian. spotlight results limit defaults to 10,000; 0 disables the limit, a nonzero limit has a minimum 100 and maximum 16,000,000. The field is spotlight_results_limit, and the control applies to every backend.

afpstats defaults to no and sets OPTION_AFPSTATS. It provides a Unix-domain socket served by the parent’s STATS_FD poll events, not a D-Bus statistics thread. afpstats group configures group access. See etc/afpd/afpstats.c and etc/afpd/afpstats.h.

FCE keys include fce listener, fce coalesce, fce events, fce version, fce ignore names, fce ignore directories, fce notify script, fce holdfmod, and fce sendwait. These configure external notifications through etc/afpd/afp_config.c and etc/afpd/fce_api.c, separate from internal cache hints.

Compatibility names and removed options

Old key Current handling
dircachesize Deprecated alias for dircache size
afp read locks Deprecated alias for strict locking
sparql results limit Deprecated alias for spotlight results limit
srp passwd file Deprecated alias for srp verifier path; value now names a directory
zeroconf name Deprecated alias for server name
cnid listen, cnid server, vol dbnest Removed; nonempty occurrences are logged and ignored

For typed aliases, precedence can also depend on whether a value is valid/usable; do not assume a malformed canonical value must override a valid alias. See parser regression coverage in test/afpd/subtests_conf.c.

Command line and single-user mode

AFP options include -d (foreground/debug flag), -F (config file), -u/--single-user, -v, -V, and -h. -F is not a config-only validation operation.

The controller’s --single-user additionally requires -P with a private absolute PID-file path, private caller-owned config/credential state, SRP-only authentication, SQLite volumes, and at least one valid static volume. It rejects Homes, AppleTalk, afpstats, admin-group/forced identities, and non-CNID Spotlight backends. Details are in Controller Daemon.

18. Configuration Reload

In normal mode, SIGHUP to the controller reloads its volume list/advertisements and signals the AFP parent. The parent resets listeners, frees/reparses configuration, initializes listeners, and forwards SIGHUP to workers. Workers defer handling into their command loop and call load_afp_conf_vols().

creatvol() deliberately retains an existing matching volume’s options during reload. Volumes removed from configuration are handled according to their open/deleted state and close vol. Therefore changed options on an already-loaded volume do not automatically become effective in that session. Reconnect or restart when fresh volume construction is required.

Single-user mode ignores SIGHUP and requires a restart for configuration changes.

Footnotes

Generated from the Netatalk GitHub Wiki

Last updated 2026-10-21