FreeBSD jail server with ZFS clone and jail.conf

I’ll be using FreeBSD 10.0 AMD64 with root on ZFS, but you can follow these instructions as long as you have a ZFS pool on the system. It is assumed that the system is already installed and basic configuration is complete.

It should be noted that the benefit from using ZFS clones will more or less vanish if you do a major ‘world’ upgrade on the jail, for example upgrading from FreeBSD 9.2 to FreeBSD 10.0. This won’t be a problem for my setup as I’ll eventually get around to configuring sysutils/py-salt to automatically deploy my jails, and I’ll post about it when I do.

Create the ZFS dataset which will be used for storing the jails:

zfs create -o compress=lz4 -o mountpoint=/usr/jail sys/jail
zfs create sys/jail/.base10x64

Fetch and extract the FreeBSD 10.0-AMD64 dist files:

cd /var/tmp
fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/10.0-RELEASE/base.txz
fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/10.0-RELEASE/lib32.txz
fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/10.0-RELEASE/games.txz
fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/10.0-RELEASE/src.txz
tar -JxvC /usr/jail/.base10x64/ -f base.txz
tar -JxvC /usr/jail/.base10x64/ -f lib32.txz
tar -JxvC /usr/jail/.base10x64/ -f games.txz
tar -JxvC /usr/jail/.base10x64/ -f src.txz

Do some very basic configuration of the base jail and update it to the latest patch:

cp /etc/resolv.conf /usr/jail/.base10x64/etc/
chroot /usr/jail/.base10x64
passwd
mkdir /usr/ports
mkdir /usr/home
ln -s /usr/home /home
cd /etc/mail
make aliases
freebsd-update fetch install

Take a snapshot of the non-customized ‘install’:

zfs snapshot sys/jail/.base10x64@clean

Customize the base jail

# file: /etc/make.conf
# location: base jail
#
# Make ports use PKGNG.
WITH_PKGNG=yes
# This makes it possible for the jail to use
# the hosts ports tree via a read-only nullfs mount
WRKDIRPREFIX= /var/ports
DISTDIR= /var/ports/distfiles
PACKAGES= /var/ports/packages
INDEXDIR= /usr/ports

# Adjust to your needs
MAKE_JOBS_NUMBER=2
# file: /etc/rc.conf
# location: base jail
###
# Jail stuff
###
# Shouldn't run sendmail
sendmail_enable="NONE"
clear_tmp_enable="YES"
# Syslog shouldn't listen for incoming connections
syslogd_flags="-ss"
rpcbind_enable="NO"

##
## Services
##
sshd_enable="YES"
# Bootstrap pkg
pkg

At this point you may apply any other customizations you want all your jails to have.

Then, on the host, take a snapshot of the base jail:

# replace pX with the patch level, for example p0.
zfs snapshot sys/jail/.base10x64@pX

Configure Host

# file: /etc/rc.conf
###
## Services
###
jail_enable="YES"
# file: /etc/jail.conf
# Defaults
exec.prestart = "/sbin/mount -t nullfs -o ro /usr/ports/ /usr/jail/$name/usr/ports";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.poststop = "/sbin/umount -f /usr/jail/$name/usr/ports";
exec.clean;
mount.devfs;
mount.fstab = "/etc/fstab.$name";
host.hostname = "$name.somehost.example.com";
allow.nomount;

# Dynamic wildcard parameter:
# Base the path off the jail name.
path = "/usr/jail/$name";

# example {
#  interface = "lo0";
#  ip4.addr = 127.0.0.2;
#  }

Create Jail

To create a new jail, simply clone the base jail and add an entry to /etc/jail.conf. If you were to uncomment the example jail listed above, you’d also have to clone the base jail as such:

zfs clone sys/jail/.base10x64@p0 sys/jail/example

7 thoughts on “FreeBSD jail server with ZFS clone and jail.conf

  1. Excellent work!. Recently I was looking for operation with snapshots and jail and now I have worked with CBSD ( /usr/ports/sysutils/cbsd ) which is one of jail management tools. Where was your article before ;-)

    Like

  2. Great guide – thanks for taking the time to succinctly detail the configuration. Your article helped me migrate from ezjail to a more native jail config.

    Like

  3. Good straight forwarded article.
    How do you manage network connections within the jail?
    Forwarding, raw sockets allowance, interface aliases etc.

    Like

Leave a comment