Contrary to advertising pitches of many, hosting one's own Internet services has many advantages over using publicly available ones. Besides having the ability to preserve control over important aspects of our digital lives, it also make for great learning platform. In the following series, "Host Your Own Services With FreeBSD Jails", I will provide detailed information about setting various Internet services, such as DNS, email, web, LDAP, database and other services using FreeBSD jails.

I will be using "fat" jails, which include complete FreeBSD distribution. I won't be using any jail management tools such as iocage, CBSD or now obsolete, but still somewhat functional ezjail. Jails will be configured exclusively through jail.conf. I will be using Jails with traditional networking, as opposed to newer VNET jails, which means their IP addresses will be aliases on host's physical network interface. Complete setup will be IPv4 only. Sorry, I know I am long overdue with at least testing IPv6 but my ISPs don't provide IPv6 addresses. Throughout the tutorials I will try to be as descriptive as I can, but don't expect me to teach you how to change file ownership or permissions, or how to edit config file in vi - this series will require fairly advanced knowledge of FreeBSD and UNIX in general.

Taming Overreaching Services

Ok, let's start. Before we set up our first jail, we need to prepare host environment, as hinted in jail(8) manpage. It's mostly about networking: no services on the host should bind to all local IP addresses, as this could result in host answering requests sent to inexisting services on jails. On clean FreeBSD install these are sshd and syslogd by default, and also ntpd if we opted-in during install (which we should, as accurate timekeeping is essential for almost all Internet services) . Let's check to be sure:

# netstat -an
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address          Foreign Address        (state)    
tcp4       0      0 *.22                   *.*                    LISTEN     
tcp6       0      0 *.22                   *.*                    LISTEN                
udp4       0      0 *.123                  *.*                    
udp6       0      0 *.123                  *.*                    
udp4       0      0 *.514                  *.*                    
udp6       0      0 *.514                  *.*  

All the services which listen on all local IP addresses are presented with asterisk followed with port number in "Local Address" column. You can check /etc/services file if you are not familiar with services belonging to respective ports, however anyone who deals with FreeBSD jails probably knows them by now - as I said above, they are ssh 22/tcp, ntp 123/udp and syslog 514/udp.

As for syslogd, at least for now I won't be using its network features on the host, so I'll disable them completely:

# sysrc syslogd_flags="-ss"
# service syslogd restart

Checking netstat output shouldn't show port 514 anymore.

Listen very carefully, I shall say this only once (to quote Michelle from "'Allo! 'Allo!"): all the config files in this tutorial will be copy-pastable as-is, with the exception of commented lines which start with "# EDIT THIS #" - those won't work for you, and you need to adjust them to your environment.

As for sshd, I will replace content of its default config file, /etc/ssh/sshd_config with one similar to this:

# EDIT THIS # ListenAddress
AuthorizedKeysFile .ssh/authorized_keys
Subsystem sftp /usr/libexec/sftp-server

After sshd restart, netstat output should show that sshd now listens on specified IP address, and not on asterisk / wildcard, which means on all available IP addresses.

As for ntpd, I will replace its config file, /etc/ntp.conf, with the following:

tos minclock 3 maxclock 6
pool iburst
restrict default limited kod nomodify notrap noquery nopeer
restrict source  limited kod nomodify notrap noquery
# EDIT THIS # restrict mask nomodify notrap noquery nopeer
leapfile "/var/db/ntpd.leap-seconds.list"
interface ignore wildcard
# EDIT THIS # interface listen

I will also set ntpd to listen on IPv4 only and restart the deamon:

# sysrc ntpd_flags="-4"
# service ntpd restart

ntpd should now listen only on loopback interface ( as well as on IP address of the host (, serving ntp clients on local network only (

netstat output at this point shouldn't show any asterisks / wildcards in "Local Address" column, which means I have bound all host's services to specific IP addreses, as opposed to all available addresses on the host.

Creating Additional Loopback Interface

In order to keep jails' loopback traffic off the host's loopback network interface lo0, we will configure and create additional loopback interface on host:

# sysrc cloned_interfaces="lo1"
# service netif cloneup

Later on, when creating jails, I will assign jail's primary IP address to be from address space, and bind it to lo1 interface, whereas secondary IP address is going to be "real" IP address from address space, bound to physical interface. This will prevent jails' communication over host's loopback interface, requiring all the jails to communicate with each other as though they were separate physical machines.

Editing hosts file

Long time ago I noticed that, after reboot, sshd would wait for DNS for some time in order to start accepting connections. It would eventually timeout after a minute or so, however adding local IP address to FQDN mappings to hosts file would speed things up (60 seconds may seem like a lifetime after reboot of remote production server while waiting for it to come up). I don't know if this is still relevant, but I got used to edit my hosts files so they contain local IP to FQDN mappings:

# EDIT THIS # ::1         localhost
# EDIT THIS #   localhost
# EDIT THIS #    jailhost
Tweaking Updates Config

Although freebsd-update.conf(5) lists src, world and kernel as update components, freebsd-update(8) is mostly "smart" enough to figure out that system doesn't have sources installed and to skip updating them. However, I like to explicitly remove src component from freebsd-update.conf for jail host so it looks as follows:

KeyPrint 800651ef4b4c71c27e60786d7b487188970f4b4169cc055784e21eb71d410cc5
Components world kernel
IDSIgnorePaths /usr/share/man/cat
IDSIgnorePaths /usr/share/man/whatis
IDSIgnorePaths /var/db/locate.database
IDSIgnorePaths /var/log
UpdateIfUnmodified /etc/ /var/ /root/ /.cshrc /.profile
MergeChanges /etc/ /boot/device.hints

By configuring sshd, ntpd and syslogd to bind to specific IP addresses, followed by creation of dedicated loopback interface for jails, I have prepared my host environment to be "jail-friendly". Before proceeding to installation of my first jail, I will apply binary patches by means of freebsd-update in order to hopefully increase host's security and reliability. I am not going to write exact procedure as it is really easy, and really well documented. However, the next chapter of this series will assume that my host runs with latest binary patches provided by freebsd-update.

Next Post Previous Post