The FreeBSD Handbook has a great guide on how to create a classic jail. I refer to it all the time, but with a slight change so that it's more opinionated in the way it's configured and operates.
An agent skill is also available if you want to use this in your AI workflows.
Jail Features
- Shares the IP address with the host system. The Jail has no dedicated IP address
- Exclusively uses ZFS
- Scalable, meaning it's easy to add more Jails using the same pattern
Requirements
- FreeBSD 13.4 or later for the host system
- At least one additional volume for ZFS
- This guide assumes a newly installed system with nothing configured
Initial Host Setup
Set the following shell variables and adjust them to your needs.
SUBDOMAIN=local.tldSelect one of the following for ZFS devices.
ZFS_VDEV="mirror da1 da2" # If a multi device
ZFS_VDEV="da1" # If a single deviceCreate ZFS Pool:
ZFS_POOL=Storage
ZFS_DATASET=/Jails
ZFS_ROOT=/mnt/${ZFS_POOL}
ZFS_DS_ROOT=/usr/local$(echo $ZFS_DATASET | tr '[:upper:]' '[:lower:]')
if ! zpool list -H ${ZFS_POOL} >/dev/null 2>&1; then zpool create -m ${ZFS_ROOT} ${ZFS_POOL} ${ZFS_VDEV}; zfs set compression=lz4 ${ZFS_POOL}; fi
if ! zfs list -H ${ZFS_POOL}${ZFS_DATASET} >/dev/null 2>&1; then zfs create -p -o mountpoint=${ZFS_DS_ROOT} ${ZFS_POOL}${ZFS_DATASET}; fiInstall the Jail 'framework':
JAIL_CONFIGS=/etc/jail.conf.d
cat << EOF >/etc/jail.conf
# Global settings applied to all jails.
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.consolelog = "/var/log/jail_console_\${name}.log";
allow.raw_sockets;
exec.clean;
mount.devfs;
# Allow shared memory (ie. Postgresql)
allow.sysvipc;
\$domain = "${SUBDOMAIN}";
host.hostname = "\${name}.\${domain}";
path = "${ZFS_DS_ROOT}/\${name}";
ip4 = inherit;
.include "${JAIL_CONFIGS}/*.conf";
EOFEnable Jails and ZFS to start at boot:
sysrc jail_enable="YES" zfs_enable="YES" jail_parallel_start="YES"Install a Jail
Set the following shell variables. Make sure they match any values used prior if you customized them.
NAME=myjail
SUBDOMAIN=local.tld
FREEBSD_VERSION=13.2Next create the ZFS Dataset for the Jail
ZFS_POOL=Storage
ZFS_DATASET=/Jails
zfs create -o compression=lz4 ${ZFS_POOL}${ZFS_DATASET}/${NAME} && DESTDIR=$(zfs get -H -o value mountpoint ${ZFS_POOL}${ZFS_DATASET}/${NAME}); echo DESTDIR=${DESTDIR}Install the Jail, configure it, and update it
HOSTNAME=${NAME}.${SUBDOMAIN}
FTP_SOURCE=ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/${FREEBSD_VERSION}-RELEASE/base.txz
stat $DESTDIR && fetch -o - $FTP_SOURCE | tar -xf - -C $DESTDIR --unlink && touch ${DESTDIR}/etc/rc.conf && sysrc -f ${DESTDIR}/etc/rc.conf hostname="${HOSTNAME}" && cp /etc/resolv.conf ${DESTDIR}/etc/resolv.conf; cp /etc/localtime ${DESTDIR}/etc/localtime && if ! grep -q $HOSTNAME ${DESTDIR}/etc/hosts; then printf "%s\t\t%s\n" $(ifconfig $(netstat -4rn | grep ^default | sed "s/.* //") inet | awk '$1 == "inet" {print $2}') "${HOSTNAME}" >> ${DESTDIR}/etc/hosts; fi && env PAGER=cat freebsd-update -b $DESTDIR --currently-running $(${DESTDIR}/bin/freebsd-version) fetch install --not-running-from-cronSetup the Pacy World Root CA (optional but highly recommended)
if [ $(${DESTDIR}/usr/bin/uname -U) -ge 1202000 ]; then fetch -qo ${DESTDIR}/usr/share/certs/trusted/ca-pacyworld.com.pem http://cdn.pacyworld.com/pacyworld.com/ca/ca-pacyworld.com.crt; fetch -qo ${DESTDIR}/usr/share/certs/trusted/alt_ca-morante_root.pem http://cdn.pacyworld.com/pacyworld.com/ca/alt_ca-morante_root.crt; certctl -D ${DESTDIR} rehash; fiRegister the Jail so it starts with the service utility and automatically at boot
JAIL_CONFIGS=/etc/jail.conf.d
cat << EOF >${JAIL_CONFIGS}/${NAME}.conf
${NAME} {
}
EOFManage Your Jail
Set the following shell variables
NAME=myjailStart your Jail
service jail start $NAMEInstall packages in your Jail:
pkg --jail $NAME install -y ....Control services:
service -j $NAME ....Enter your Jail:
jexec $NAME /bin/shUpdate your Jail:
pkg -j $NAME upgrade
freebsd-update -j $NAME fetch install
service jail restart $NAMEStop your Jail:
service jail stop $NAMEOther Jail Tips
Disable tasks in /etc/periodic.conf (optional but highly recommended)
sysrc -j $NAME -f /etc/periodic.conf security_status_chksetuid_enable="NO" security_status_neggrpperm_enable="NO" weekly_locate_enable="NO"- Log in to post comments

.png)