Starting with FreeBSD jails

Software

Update: An earlier verison of this post didn’t include the output from jls, and I had mismatched paths for the jail dataset. Thanks also to Ashy for correcting the zfs create line.

A reader by the name of Mitchell asked me to discuss FreeBSD jails, given how often I’ve mentioned the feature here over the years. I was ready to refer him to an earlier post before realising I never introduced them here before. Whoops!

Jails are a lightweight, fast form of virtualisation and process isolation invented by the imitable Poul-Henning Kamp that, once you first use them, you miss them everywhere else. Each jail operates with its own chroot file system environment and network configuration, similar to a Solaris Zone.

(Aside: Hey, it’s Ruben here, from the future. Resist the temptation to assert correct spelling with “gaol” in your pools and scripts. You feel great creating them, and you pay for it for years afterwards. The system calls them jails; make your life easier and use broken spelling too)!

Much has been written about the potential security benefits of isolating processes, but I shamelessly use them foremost to keep my ports clean. My Plex jail has everything for video encoding, the Minecraft jail is the only one with a JDK runtime. Conflicts aren’t an issue, they’re simple to update without unintentionally breaking something else, and it keeps individual attack surfaces small.

Photo of Hololive EN's Gawr Gura, for whom the following jail is named for

There are specialised tools like iocage and the older ezjail to make building and managing fleets of jails easier, but lately I’ve gone back to building them manually. The provided tooling is already excellent, and ZFS features like snapshots make generating new ones simple. I still think it’s the best way to learn, as well.

It’s easy to carve out space for your jails if you’re using ZFS, then a new dataset for your first jail, which I’ve named for everyone’s favourite cute shark. These can be anywhere you want:

# zfs create -o mountpoint=/jail zroot/jail
# zfs create zroot/jail/gura

You can extract a base.txz from a FreeBSD installer image or download via svn—wow I love FreeBSD!—but bsdinstall will handily install it for us too:

# bsdinstall jail /jail/gura

Now we need the config. Here’s a minimal /etc/jail.conf:

mount.devfs;
exec.clean;
exec.start="sh /etc/rc";
exec.stop="sh /etc/rc.shutdown";    
    
path="/jail/${name}";
host.hostname="${name}.myhost.lan";    
    
gura {
	ip4.addr="10.8.8.81";
}

Note the handy $name variable. This is surprisingly populated with the name of the jail, so we can keep config consistent. The only jail-specific config I want for gura in this case is her IP. Check the well-written jail.conf(5) manpage for all the options.

Networking to jails can be as simple or complex as you want, which is really cool! You can use a network bridge like you would with a hypervisor and VM guests, or inherit the host’s networks with ip4=inherit. I employ the former in production, but for home setups I just use aliases against my primary interface. Note the address below matches our config above:

# ifconfig igb0 10.8.8.81/32 alias
# sysrc ifconfig_igb0_alias0="inet 10.8.8.81/32"

Now we can enable jails on boot, and optionally a list:

# sysrc jail_enable="YES"
# sysrc jail_list="gura"

Ready to start? Using service is the easiest, and use jls(8) to list:

# service jail start gura
# jls    
    
==> JID  IP Address  Hostname         Path
==> 1    10.8.8.81   gura.myhost.lan  /jail/gura

Huzzah! We could SSH into the VM at the IP provided, but we can also execute commands directly on the jail with jexec(8)… like a shell!

# jexec gura /bin/sh

I hope using ZFS sparked some creative thinking too. With ZFS you could easily create a template jail, then snapshot and promote to create new ones. You can do thin provisioning by sharing portions of the filesystem, but I always do thicc [sic] provisions; disk space is cheap, and it gives me more flexibility down the road.

This barely scratches the surface, but I hope I’ve given you some motivation to play around with this feature, and maybe give FreeBSD a try. They’re available on OrionVM as a template if you want to spin up to test; and they exist on more expensive, slower clouds with more complex UIs as well, not that I’m biased (disclosure: completely biased)!

The FreeBSD Handbook goes into more detail, and I seriously encourage you to buy Michael Warren Lucas’ FreeBSD Mastery: Jails tome. I bought it for the third time yesterday as part of my move to the Kobo ebook platform, it’s that good.

Author bio and support

Me!

Ruben Schade is a technical writer and infrastructure architect in Sydney, Australia who refers to himself in the third person. Hi!

The site is powered by Hugo, FreeBSD, and OpenZFS on OrionVM, everyone’s favourite bespoke cloud infrastructure provider.

If you found this post helpful or entertaining, you can shout me a coffee or send a comment. Thanks ☺️.