Running Samba in a FreeBSD jail

Describes how to install Samba 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 samba, with IP address of 192.168.0.231, bound to network interface igb0, with the help of ezjail, do

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

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

  2. Start the jail and enter inside, do

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

    root@samba: ~# tzsetup

    and follow instructions.

  4. Install FreeBSD binary package manager:

    root@samba: ~# pkg bootstrap

    agree and wait for task to complete.

  5. Install Samba binary package:

    root@samba: ~# pkg install samba43

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

  6. Create initial Samba configuration file (important parts related to “jailing” Samba are explained below). For Samba 4.x the name of configuration file would be /usr/local/etc/smb4.conf:

    [global]
     interfaces = 192.168.0.231
     bind interfaces only = yes
     remote announce = 192.168.0.255
     map to guest = bad user
    
    [test]
     path = /mnt
     read only = yes
     guest ok = yes
    

    The important parts:

    • interfaces line declares IP address visible to the clients: jail’s public IP address (192.168.0.231 in this example, something else in your case),
    • bind interfaces only = yes tells Samba to bind only to addresses listed in interfaces clause,
    • remote announce = 192.168.0.255 tells Samba to advertise itself on the given broadcast address, since, by default, jails use /32 mask and the broadcast address equals to the jail’s IP address. Put the correct broadcast address here, depending on the subnet in use!
    • the rest of the options allow guest access and declare a single share, named test, exporting /mnt for read-only.
  7. Enable and start Samba services:

    root@samba: ~# sysrc samba_server_enable=YES
    samba_server_enable:  -> YES
    root@samba: ~# service samba_server start
    Performing sanity check on Samba configuration: OK
    Starting nmbd.
    Starting smbd.
    root@samba: ~# 
    

    Verify if Samba is running:

    root@samba: ~# service samba_server status
    nmbd is running as pid 93309.
    smbd is running as pid 93315.
    root@samba: ~# 
    

    If either service is not running check log.nmbd and/or log.smbd for errors (both in /var/log/samba/). Verify if jail’s IP address is correctly specified at interfaces clause in /usr/local/etc/smb4.conf.

    At this moment, if the services are running, it should be possible to access Samba by its IP address (like \\192.168.0.231 from Windows or smb://192.168.0.231 from Mac OS), but not by its name. I believe the reason is, that nmbd, when running in a jail, is unable to receive broadcasts, because those packets do not target jail’s IP address. With other words, when clients ask “who is samba” (samba is the Samba server name, by default same as hostname or jail name) nmbd wouldn’t be able to hear that question and won’t answer.

    Let’s fix that:

  8. Let’s add a firewall rule to forward broadcast traffic to the jail’s nmbd. Using pf firewall the rules to be added to /etc/pf.conf would be:

    rdr inet proto udp to 192.168.0.255 port netbios-dgm -> 192.168.0.231 port netbios-dgm
    rdr inet proto udp to 192.168.0.255 port netbios-ns  -> 192.168.0.231 port netbios-ns
    

    Again: 192.168.0.231 should be replaced with jail’s IP address and 192.168.0.255 should be replaced with the correct broadcast address for subnet in use.

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

That’s it! At least in my case. YMMV.