Solved FreeBSD 14.2 Host-Managed ZFS datasets auto-mounted With jexec inside a jail - native ZFS solution

Hello every one;

I had a problem of mounting 3 hierarchical datasets (data17, base, pg_wal) with nested mount-points as explained in this Post thread.
The issue was that I didn't know how to attach the mount point of a host-managed ZFS dataset inside a jail, without having to do a manual
creation of the mounting directory within the jail.

So this post is a summery after resolving the issue and making some modification in my setup, to get a native ZFS solution for a dataset having
the mount point auto directed to a jail's.

The trick and the magic for solution to work, are inside the file jail.con configuration with the instruction "jexec pgdb01 zfs mount your_zfs_dataset".

The goal is to install PostgreSQL 17 inside FreeBSD 14.2 Jail, and that by separating and tweaking the datasets inside the jail.
My FreeBSD 14.2 Host-Managed ZFS datasets are like below :

zroot/jails/containers/pgdb01 -----------------------------#. mounted at /usr/local/jails/containers/pgdb01
zroot/jails/containers/pgdb01/data17_base -----------------#. mounted at /usr/local/jails/containers/pgdb01/data17_base
zroot/jails/containers/pgdb01/data17_pg_wal ---------------#. mounted at /usr/local/jails/containers/pgdb01/data17_pg_wal


Install and configure your FreeBSD jail as explained in the FreeBSD Handbook jail section, my preference is the thick jail with vnet.
The FreeBSD 14.2 jail configuration File :

root@desktopfb:~ # cat /etc/jail.conf.d/pgdb01.conf
pgdb01 {
# STARTUP/LOGGING
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.consolelog = "/var/log/jails/jail_console_${name}.log";

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

allow.mount;
allow.mount.devfs;
allow.mount.zfs;

enforce_statfs = 1;

# /etc/defaults/devfs.rules
devfs_ruleset = 5;

# To run PostgreSQL in a FreeBSD jail
sysvmsg=new ;
sysvsem=new ;
sysvshm=new ;

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

# Not used because the mount points are not auto unmounted where stopping or restaring a Jail
# mount.fstab="/etc/fstab.$name";

# VNET/VIMAGE
vnet;
vnet.interface = "${epair}b";

# NETWORKS/INTERFACES
$id = "232";
$ip = "192.168.20.${id}/24";
$gateway = "192.168.20.1";
$bridge = "bridge0";
$epair = "epair${id}";

# ADD TO bridge INTERFACE
exec.prestart = "/sbin/ifconfig ${epair} create up";
exec.prestart += "/sbin/ifconfig ${epair}a up descr jail:${name}";
exec.prestart += "/sbin/ifconfig ${bridge} addm ${epair}a up";
exec.start += "/sbin/ifconfig ${epair}b ${ip} up";
exec.start += "/sbin/route add default ${gateway}";
exec.poststop = "/sbin/ifconfig ${bridge} deletem ${epair}a";
exec.poststop += "/sbin/ifconfig ${epair}a destroy";

# PostgeSQL PG_DATA ZFS datasets auto mounted inside the jail in the directory /var/db/postgres/data17

# Without the config of the datasets. It will be added later.
}


Use pkg to install the PostgreSQL Database Server without staring it, then initialize your database Server with oneinitdb

#--------------------------------------------------
# initializing the PostgreSQL Database Server
#--------------------------------------------------
echo -e "\n---- initializing the PostgreSQL Database Server. Please wait. ----"
sudo /usr/local/etc/rc.d/postgresql oneinitdb -E UTF-8 /var/db/postgres/data17

exit # exit from the jail
service jail stop pgdb01
service jail start pgdb01
jexec pgdb01 login -f root
#--------------------------------------------------------------------------------
# Mouving the database data17/base and the Write Ahead Log - WAL data17/pg_wal :
#--------------------------------------------------------------------------------
echo -e "\n---- Mouving the database data17/base and the Write Ahead Log - WAL data17/pg_wal. ----"

mv /var/db/postgres/data17/base /var/db/postgres/data17/base_original
mv /var/db/postgres/data17/pg_wal /var/db/postgres/data17/pg_wal_original

exit # Log out of jail console to host
service jail stop pgdb01

Now is the time for the creation of the ZFS datasets for the PostgreSQL DB (PG_DATA) : [data17_base, data17_pg_wal] :

# Creating the database data17_base dataset :

zfs set jailed=off zroot/jails/containers/pgdb01

zfs create -o mountpoint=/var/db/postgres/data17/base zroot/jails/containers/pgdb01/data17_base
zfs set mountpoint=/var/db/postgres/data17/base zroot/jails/containers/pgdb01/data17_base

sudo zfs set recordsize=8k zroot/jails/containers/pgdb01/data17_base
sudo zfs set redundant_metadata=most zroot/jails/containers/pgdb01/data17_base
sudo zfs set primarycache=metadata zroot/jails/containers/pgdb01/data17_base
sudo zfs set logbias=throughput zroot/jails/containers/pgdb01/data17_base
sudo zfs set compression=zstd zroot/jails/containers/pgdb01/data17_base
sudo zfs set checksum=sha512 zroot/jails/containers/pgdb01/data17_base
sudo zfs set atime=off zroot/jails/containers/pgdb01/data17_base
sudo zfs set relatime=on zroot/jails/containers/pgdb01/data17_base


# Creating the database data17_pg_wal dataset :

zfs create -o mountpoint=/var/db/postgres/data17/pg_wal zroot/jails/containers/pgdb01/data17_pg_wal
zfs set mountpoint=/var/db/postgres/data17/pg_wal zroot/jails/containers/pgdb01/data17_pg_wal

sudo zfs set recordsize=8k zroot/jails/containers/pgdb01/data17_pg_wal
sudo zfs set redundant_metadata=most zroot/jails/containers/pgdb01/data17_pg_wal
sudo zfs set primarycache=metadata zroot/jails/containers/pgdb01/data17_pg_wal
sudo zfs set logbias=throughput zroot/jails/containers/pgdb01/data17_pg_wal
sudo zfs set compression=zstd zroot/jails/containers/pgdb01/data17_pg_wal
sudo zfs set checksum=sha512 zroot/jails/containers/pgdb01/data17_pg_wal
sudo zfs set atime=off zroot/jails/containers/pgdb01/data17_pg_wal
sudo zfs set relatime=on zroot/jails/containers/pgdb01/data17_pg_wal

Jail your ZFS datasets

zfs set jailed=on zroot/jails/containers/pgdb01/data17_base
zfs set jailed=on zroot/jails/containers/pgdb01/data17_pg_wal
zfs set jailed=on zroot/jails/containers/pgdb01


Now the important part is to actualize the configuration in the file /etc/jail.conf.d/pgdb01.conf for the datasets :

ee /etc/jail.conf.d/pgdb01.conf

pgdb01 {

# If you wan to use zfs commands in jail like take snapshot inside the jail, put zfs_enable="YES" in the /etc/rc.conf of your jail
#
# PostgeSQL PG_DATA ZFS datasets are auto mounted inside the jail in the directory /var/db/postgres/data17

exec.created += "/sbin/zfs jail pgdb01 zroot/jails/containers/pgdb01/data17_base";
exec.created += "jexec pgdb01 zfs mount zroot/jails/containers/pgdb01/data17_base";

exec.created += "/sbin/zfs jail pgdb01 zroot/jails/containers/pgdb01/data17_pg_wal";
exec.created += "jexec pgdb01 zfs mount zroot/jails/containers/pgdb01/data17_pg_wal";

exec.release += "/sbin/zfs unjail pgdb01 zroot/jails/containers/pgdb01/data17_base";
exec.release += "umount -f zroot/jails/containers/pgdb01/data17_base";

exec.release += "/sbin/zfs unjail pgdb01 zroot/jails/containers/pgdb01/data17_pg_wal";
exec.release += "umount -f zroot/jails/containers/pgdb01/data17_pg_wal";

# mountpoints - # I did a working test for nullfs mount - but I preferred using ZFS mount by jexec jail
}


Now moving the directories [base, pg_wa] to datasets {data17_base, data17_pg_wal} :

service jail start pgdb01
jexec pgdb01 login -f root

cd /var/db/postgres/data17
pwd
ls -al
chown -R postgres:postgres base pg_wal

mv base_original/* base/
mv pg_wal_original/* pg_wal/
# Remove the old directories after verification
# rmdir base_original pg_wal_original
chown -R postgres:postgres base pg_wal

ee /etc/rc.conf
# Postgresql database
postgresql_enable="YES"
postgresql_class="postgres"

# Cross your fingers and start PostgreSQL
service postgresql start
psql -U postgres -l

Enjoy the deployment of your jailed PostgreSQL server with native ZFS integration.

My config shown form FreeBSD host, you will notice the used space listed by zfs list for the dataset data17_base, data17_pg_wal mounted
on /var/db/postgres/data17 on the jail :
F01 - Freebsd 14-2 Host-Managed ZFS datasets auto-mounted With jexec inside a jail - native ZFS.png


My config inside the FreeBSD jail, you will notice mounted ZFS lines on /var/db/postgres/data17 and the exact mach of the used space listed by zfs list for the datasets :
F02 - Freebsd 14-2 Host-Managed ZFS datasets auto-mounted With jexec inside a jail - native ZFS.png
 
Back
Top