In an older blog post I focused on creating FreeBSD base jails with VNET on ZFS. Today, I want to do the same thing with Thick jails, since I have some use cases where base jails don’t quite do what I want to do in terms of management.
Thick Jail?
A thick jail in creation is basically half the steps of a base jail. It is a jail with its own complete userspace, no nullfs mounts and the sort.
My reasons for wanting a thick jail is because I used base jails to have an
easy to manage jail. freebsd-update
the base they were built on, restart the
jails, then I’m done. But to keep my jail versions pure and be able to delete
older FreeBSD versions, I’ve migrated my jails from base to base. For most,
this is not a problem. However, I have grown very tired of doing this with my
Nextcloud jail. Now yeah yeah I could use Ansible to do it all for me but for
this single jail, that’s a bit much.
The thick jail is has its own copy of the FreeBSD userland, which then means it uses more space the more thick jails you add. It also means I have to independently manage each jail. That makes it easier for me with Nextcloud, and some other single use jails where it’s probably easier to just treat each jail as a virtual machine, so to speak.
Creating the Jail
First off, we need to create the jail. I’m going to start by making a new jails dataset and mounting it at /jails
zfs create -o mountpoint=/jails zroot/jails
Here is the foundation for everything. Now I’ll create a few other datasets for our releases and templates and running jails, as well as our first release dataset (14.0-RELEASE)
zfs create -p zroot/jails/jails/myjailname
Next, we need to download the base OS as well as lib32 for our jail.
The contents should be extracted into /jails/jails/myjailname
in the end.
fetch https://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/14.0-RELEASE/base.txz -o /tmp/base.txz
fetch https://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/14.0-RELEASE/lib32.txz -o /tmp/lib32.txz
tar -xf /tmp/base.txz -C /jails/jails/myjailname
tar -xf /tmp/lib32.txz -C /jails/jails/myjailname
Now let us update the jail contents
env UNAME_r=14.0-RELEASE freebsd-update -b /jails/jails/myjailname fetch install
env UNAME_r=14.0-RELEASE freebsd-update -b /jails/jails/myjailname IDS
Then, we can copy our /etc/localtime and our /etc/resolv.conf files into the jail
cp /etc/localtime /jails/jails/myjailname/etc/localtime
cp /etc/resolv.conf /jails/jails/myjailname/etc/resolv.conf
Jail Configuration
Now that the jail is done, we need to configure it to start it. This is done by
editing the /etc/jail.conf
file. For this single jail, it should look something
like this
$jails="/jails/jails";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
exec.system_user = "root";
exec.jail_user = "root";
mount.devfs;
vnet;
vnet="new";
allow.raw_sockets = 1;
devfs_ruleset="5";
myjailname {
host.hostname = "myjailname";
path = "$jails/myjailname";
#securelevel="2";
vnet.interface = "e0b_jeth";
exec.prestart += "sh /usr/local/bin/jib addm jeth em0";
exec.poststop += "/usr/local/bin/jib destroy jeth";
}
Note
|
em0 is my hosts interface and jeth is the name of the interface that jib expects
|
We will need to drop some basic configs in the jail soon such as an rc.conf and pf.conf file since this configuration is set up to run pf in each jail on its own.
Inside the Jail
Inside the jail, we need a working rc.conf and pf.conf. To start, my rc.conf looks like this
cron_flags="$cron_flags -J 15"
# Disable Sendmail by default
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
# Run secure syslog
syslogd_flags="-c -ss"
hostname="myjailname"
# NOTE the usage of jeth here with /etc/jail.conf
ifconfig_e0b_jeth="192.168.1.100/24"
defaultrouter="192.168.10.1"
pf_enable="YES"
And the pf.conf file (definitely be sure to configure this properly, this is only an example)
block all
pass out
Host Configuration
For the host, we need to setup a few things:
-
Enable the service
-
Get jib in the right place
-
Configure our interface (optional)
Enable the Service
sysrc jail_enable="YES"
sysrc jail_list="myjailname"
The above enables the jail server and jail_list
will autostart the jail when
the service gets started and stopped when the service stops
Get jib in the Right Place
Either copy or symlink jib to /usr/local/bin
cp /usr/share/examples/jails/jib /usr/local/bin/jib
Wrapping It Up
The jail should be able to start now. Here is one way the jail can be started
service jail start myjailname
And now it is possible to jexec into it
jexec myjailname
Now you can do whatever you wish with this jail like any other jail.
UPDATES
-
2024-01-15 - Updated release numbers to 14.0