Netatalk v4.2.0 on a Rootless Docker Install

Submitted by Tom Thorp on Friday, May 2, 2025 - 23:28
Modified on Saturday, May 10, 2025 - 12:07
Image
Netatalk v4.2.0 on Rootless Docker
Body

Here’s a comprehensive knowledgebase article for deploying Netatalk in a rootless Docker container on Fedora 41, covering SELinux, UID/GID mapping, Netatalk configuration, networking/firewall, and macOS Time Machine integration.

Summary

You will configure Fedora 41 for rootless Docker, adjust SELinux volume labels, and map host ↔ container UIDs/GIDs correctly. Then you’ll deploy Netatalk with a custom afp.conf and docker-compose.yml, open AFP ports in firewalld, and optionally enable Avahi for service discovery. Finally, you’ll configure macOS Time Machine to use the AFP share, including creating and troubleshooting sparsebundle images.


Prerequisites

  • A Fedora 41 server with kernel ≥ 5.11 and Podman/Docker rootless support.

  • Your user added to /etc/subuid and /etc/subgid for sub-UID/GID ranges rootlesscontaine.rs.

  • Docker Engine installed in rootless mode (e.g., via dnf install docker-ce --allowerasing) netatalk.io.


1. Rootless Docker & UID/GID Mapping

1.1 Configure SubUID/SubGID

Ensure /etc/subuid and /etc/subgid contain lines like

youruser:100000:65536

This allocates 65 536 subuids/subgids for “youruser,” used by newuidmap/newgidmap rootlesscontaine.rs.

1.2 Understanding UID/GID Mismatch

  • Host UID (e.g., 1000) maps to container root (UID 0).

  • Other container UIDs/GIDs shift by your subuid start.

  • Files created by root in container become owned by your host user Stack Overflow.
     

1.3 Set Rootless Docker to access a restricted port range

As Netatalk uses TCP port 548, Rootless Docker (by default) won't have access to the restricted port. (Restricted port range is 0 - 1024.) To enable Rootless Docker access to the restricted port (TCP port 548), a change needs to be made to the account running the Docker Service. You can set this up using two methods : 

a) Environment variables in your shell

export ROOTLESSKIT_PORT_DRIVER=slirp4netns
export ROOTLESSKIT_PORT_DRIVER_FLAGS="--port-range=548:65535"

You can add these to your ~/.bashrc, ~/.zshrc, or systemd user service (see below) to persist them.

b) Systemd --user Service

Create or edit the override file:

systemctl --user edit docker

Add the following section:

[Service]
Environment=ROOTLESSKIT_PORT_DRIVER=slirp4netns
Environment=ROOTLESSKIT_PORT_DRIVER_FLAGS=--port-range=548:65535

Then reload and restart:

systemctl --user daemon-reexec
systemctl --user restart docker

2. SELinux Compatibility with Docker Volumes

Fedora’s default SELinux policy blocks container access to bind mounts. To allow write access:

services:
  netatalk:
    volumes:
      - ./data:/srv/afp:Z

The :Z flag relabels ./data to container_file_t, permitting read/write prefetch.net.
Alternatively, use :z for shared labels across containers discussion.fedoraproject.org.


3. Deploying Netatalk in Docker

3.1 AFP Configuration (afp.conf)

Create afp.conf in your project:

[Global]
  log file = /var/log/afpd.log
  mimic model = TimeCapsule6,106
  time machine = yes
  time machine max size = 1T
[MyBackup]
  path = /srv/afp/backups
  valid users = tmuser
  time machine alphasize = 64 
 

This tells Netatalk to present a Time Machine–compatible volume netatalk.io.

3.2 Docker Compose Example (docker-compose.yml)

services:
  netatalk:
    image: cptactionhank/netatalk:latest
    user: "${UID}:${GID}"
    network_mode: bridge
    ports:
      - "548:548"
    volumes:
      - ./afp.conf:/etc/netatalk/afp.conf:Z
      - ./backups:/srv/afp/backups:Z
    environment:
      - AFP_USER=tmuser
      - AFP_PASS=StrongPass123
      - AVAHI=1
 
  • user: "${UID}:${GID}" ensures files created by Netatalk are owned by your host user Docker Community Forums.

  • AVAHI=1 enables mDNS service discovery if you prefer not to use host network GitHub.

  • You can also mount a separate CNID SQL backend following the Netatalk Docker docs GitHub.


4. Firewalld Configuration

4.1 Open AFP Port

firewall-cmd --permanent --add-service=afp
firewall-cmd --reload

Or explicitly:

firewall-cmd --permanent --add-port=548/tcp
firewall-cmd --reload

This opens port 548 for AFP traffic The world's open source leaderfirewalld.

4.2 Enable mDNS (if using Avahi)

firewall-cmd --permanent --add-service=mdns
firewall-cmd --reload
 

5. Connecting macOS Time Machine

5.1 Mounting the AFP Share

On your Mac:

  1. Finder > Connect to Server (Cmd+K).

  2. Enter afp://fmhost.local/backups.

  3. Provide tmuser / StrongPass123 and save to Keychain openwrt.org.

5.2 Creating and Managing Sparsebundles

  • macOS will auto-create Backups of YourMac.sparsebundle inside /srv/afp/backups.

  • If you need a custom size:

    hdiutil create -size 500g \
      -fs HFS+J -type SPARSEBUNDLE \
      -volname "Backups of YourMac" \
      /path/to/backups/YourMac.sparsebundle
     
  • Troubleshooting:

    • If you see MachineID.plist missing, delete the old bundle and let Time Machine re-create it netatalk.io.

    • Ensure Keychain Access permissions allow backupd and backupd-helper to read the password.


6. Additional Considerations

  • avahi-daemon: For Zeroconf/mDNS advertisement, ensure AVAHI=1 and open UDP port 5353.

  • Spotlight Indexing: You can mount volumes with -v hostpath:containerpath:Z to allow Netatalk to index via Spotlight.

  • Container Logs: Check /var/log/afpd.log inside container for AFP errors.

  • Resource Limits: Adjust Docker resource quotas if backups are large.

  • Backups over TLS: Netatalk supports TLS encryption; see afp.conf for tls keyfile = ... options.


Categories

 

About the author

Tom Thorp
Tom Thorp is an IT Consultant living in Miami on Queensland's Gold Coast. With more than 30 years working in the IT industry, he has extensive experience. The IT services provided to clients include:
 
Website development and hosting,
Database Administration,
Server Administration (Windows, Linux, Apple),
PBX Hosting and Administration,
Helpdesk Support (end-user & technical).
  If you like any of my content, consider a donation via Crypto by clicking on one of the payment methods:.