Running Netatalk/AFP in a FreeBSD jail

Describes how to install Netatalk/AFP from binary packages, in a FreeBSD jail. Tested on FreeBSD 10.2-RELEASE. As usual, YMMV; let’s go:

  1. Create a FreeBSD jail. I use ezjail, but the specific way of creating the jail is of no importance. To create a FreeBSD jail named afp, with IP address of, bound to network interface igb0, with the help of ezjail, do

    root@host: ~# ezjail-admin create afp 'igb0|'

    Replace afp with desired jail/server name and with the IP address to be assigned to the jail.

  2. Start the jail and enter inside, do

    root@host: ~# ezjail-admin start afp
    root@host: ~# ezjail-admin console afp
    root@afp: ~# 
  3. Optional: select the correct time-zone, do

    root@afp: ~# tzsetup

    and follow instructions.

  4. Install FreeBSD binary package manager:

    root@afp: ~# pkg bootstrap

    agree and wait for task to complete.

  5. Install Netatalk binary package:

    root@afp: ~# pkg install netatalk3

    once again agree and wait for task to complete (Netatalk sports quite a list of dependencies).

  6. Create initial Netatalk3 configuration file (important parts related to “jailing” AFP are explained below). The name of configuration file would be /usr/local/etc/afp.conf:

     afp interfaces = igb0
     path = /mnt

    The “important” parts:

    • afp interfaces line declares the network interface to bound to; this might or might not be required, in my case it was, possibly because I used VLANs for my Intranet,
    • the rest of the options export /mnt as a share named test.
  7. Create a user to test with (or to keep permanently), run

    root@afp: ~# adduser

    and follow instructions, and remember to pick a password.

  8. Enable and start Netatalk services:

    root@afp: ~# sysrc netatalk_enable=YES
    netatalk_enable:  -> YES
    root@afp: ~# sysrc dbus_enable=YES
    dbus_enable:  -> YES
    root@afp: ~# sysrc avahi_daemon_enable=YES
    avahi_daemon_enable:  -> YES
    root@afp: ~# service dbus start
    Starting dbus.
    root@afp: ~# service avahi-daemon start
    Starting avahi-daemon.
    root@afp: ~# service netatalk start
    Starting netatalk.
    root@afp: ~# 

    Shortly after starting netatalk service, it should be possible to access test network share on your server using newly created user account. Some time later (when name cache expires) this machine will get inaccessible. I believe the reason is, that avahi, when running in a jail, is unable to receive multicast DNS messages, because those packets do not target jail’s IP address. With other words, when clients ask “who is afp” (afp is the Netatalk server name, same as hostname or jail name, by default) avahi wouldn’t be able to hear that question in order to answer.

    Let’s fix that:

  9. Let’s add a firewall rule to forward multicast DNS traffic to the jail’s avahi. Using pf firewall the rules to be added to /etc/pf.conf would be:

    rdr inet proto udp to port mdns -> port mdns

    Again: should be replaced with jail’s IP address.

    Same should be possible using ipfw, but I have no experience with it.

Here are two bonus points:

  • to change server icon in Mac OS Finder create file /usr/local/etc/avahi/services/afpd.service with the following contents:

    <?xml version="1.0" standalone='no'?><!--*-nxml-*-->
    <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
        <name replace-wildcards="yes">%h</name>

    model=Xserve does the magic. Now restart Avahi: service avahi-daemon restart.

  • to enable Time Machine backups append the following to /usr/local/etc/afp.conf:

    [Time Machine]
     path = /usr/home/timemachine
     valid users = timemachine
     time machine = yes
     vol size limit = 500000

    and (using adduser or pw) create an account timemachine with home directory of /usr/home/timemachine (you can pick another user account name or directory path); 500000 limits Time Machine capacity to about 500 gigabytes. Now restart netatalk service (service netatalk restart).