Vincent's Weblog

Using jails in FreeBSD


Sat 21 October 2023 By Vincent Lammens
Category: Tutorial
Tags: freebsd

FreeBSD's jails are pretty powerful tools, in this post I will go over how they can be used.

Types of Jails

there are 3 main types of jails:

Thick jails are the "traditional" form of jails in FreeBSD, they contain a complete copy of the FreeBSD base system. This means that each jail has its own libraries, executables and configuration files. This can be thought of like it's own standalone installation. This isolation ensures that processes within the jail are kept entirely separate from the host or other jails.

Thin jails share the base system using OpenZFS snapshots or a NullFS mounts from a template, so only a minimal set of the base system is copied for each thin jail. This means less resources but also less isolation, and changes in shared components could affect multiple thin jails at once.

Linux jails are a feature of the FreeBSD OS that allows running Linux binaries and applications within a FreeBSD jail. This is done with a compatibility layer of the host system that translates Linux system calls to FreeBSD system calls.

In this post I'll go over Thick jails, but you can read more about the other types in the freebsd documentation

Enabeling Jails

To enable jails, we need to run the following commands:

sysrc jail_enable="YES"
sysrc jail_parallel_start="YES"

next we need to set up the directory tree for the jails:

zfs create -o mountpoint=/usr/local/jails zroot/jails
zfs create zroot/jails/media
zfs create zroot/jails/templates
zfs create zroot/jails/containers

Thick (classic) jails

First we need to download and extract the userland files. thickjail is the name of the jail I'm creating

fetch https://download.freebsd.org/ftp/releases/amd64/amd64/13.2-RELEASE/base.txz -o /usr/local/jails/media/13.2-RELEASE-base.txz
mkdir -p /usr/local/jails/containers/thickjail
tar -xf /usr/local/jails/media/13.2-RELEASE-base.txz -C /usr/local/jails/containers/thickjail --unlink
cp /etc/resolv.conf /usr/local/jails/containers/thickjail/etc/resolv.conf
cp /etc/localtime /usr/local/jails/containers/thickjail/etc/localtime

now we have the jail configured, we can update the jail to the latest patch level:

freebsd-update -b /usr/local/jails/containers/thickjail/ fetch install

Next, add the following to /etc/jail.conf (or; to a new file in /etc/jail.conf.d)

thickjail {
  # STARTUP/LOGGING
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # PERMISSIONS
  allow.raw_sockets;
  exec.clean;
  mount.devfs;

  # HOSTNAME/PATH
  host.hostname = "${name}";
  path = "/usr/local/jails/containers/${name}";

  # NETWORK
  ip4.addr = 172.16.0.201;
  interface = em0;
}

(tip: if you want to share the IP of the host, you can use ip4 = inherit instead)

and start it with

service jail start thickjail

Jail management

Now we have a jail running, we need to manage it. With jls we can list the running jails

root@testbsd:/etc/jail.conf.d # jls
   JID  IP Address      Hostname                      Path
     1  172.16.0.201    thickjail                     /usr/local/jails/containers/thickjail

to control power, we can use service jail <start|stop|restart> <jailname> for example

service jail stop thickjail

If needed, we can enter a jail with jexec.

jexec -u root thickjail

Starting jails at boot time

To start jails at boot time, you can add the following to /etc/rc.conf (you can add multiple jails, seperated with a space, like jail_list="jail-1 jail-2")

jail_list="thickjail"

Deleting a jail

service jail stop jailname
chflags -R 0 /usr/local/jails/containers/jailname
rm -rf /usr/local/jails/containers/jailname