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.
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.tld
Select one of the following for ZFS devices.
ZFS_VDEV="mirror da1 da2" # If a multi device
ZFS_VDEV="da1" # If a single device
Create 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}; fi
Install 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";
EOF
Enable 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.2
Next 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-cron
Setup 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; fi
Register 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} {
}
EOF
Manage Your Jail
Set the following shell variables
NAME=myjail
Start your Jail
service jail start $NAME
Install packages in your Jail:
pkg --jail $NAME install -y ....
Control services:
service -j $NAME ....
Enter your Jail:
jexec $NAME /bin/sh
Update your Jail:
pkg -j $NAME upgrade
freebsd-update -j $NAME fetch install
service jail restart $NAME
Stop your Jail:
service jail stop $NAME
Other 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