From a13b9f682945ef47d442cecdbfaf40f2f49bdf56 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 6 Nov 2025 11:07:53 -0700 Subject: [PATCH] zfs: properly jail dataset --- usr/local/share/bastille/zfs.sh | 82 ++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/usr/local/share/bastille/zfs.sh b/usr/local/share/bastille/zfs.sh index 97a7dea1..5b7a63c1 100644 --- a/usr/local/share/bastille/zfs.sh +++ b/usr/local/share/bastille/zfs.sh @@ -53,6 +53,8 @@ EOF zfs_jail_dataset() { + local jail_config="${bastille_jailsdir}/${JAIL}/jail.conf" + # Exit if MOUNT or DATASET is empty if [ -z "${MOUNT}" ] || [ -z "${DATASET}" ]; then usage @@ -65,30 +67,48 @@ zfs_jail_dataset() { if grep -hoqsw "${DATASET}" ${bastille_jailsdir}/*/zfs.conf; then error_exit "[ERROR]: Dataset already assigned." fi + # Validate jail state - check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - bastille stop "${_jail}" + check_target_is_stopped "${JAIL}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${JAIL}" else error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi # Add necessary config variables to jail - bastille config ${_jail} set enforce_statfs 1 >/dev/null - bastille config ${_jail} set allow.mount >/dev/null - bastille config ${_jail} set allow.mount.devfs >/dev/null - bastille config ${_jail} set allow.mount.zfs >/dev/null + bastille config ${JAIL} set enforce_statfs 1 >/dev/null + bastille config ${JAIL} set allow.mount >/dev/null + bastille config ${JAIL} set allow.mount.devfs >/dev/null + bastille config ${JAIL} set allow.mount.zfs >/dev/null + + # Enable ZFS inside jail + sysrc -f "${bastille_jailsdir}/${JAIL}/root/etc/rc.conf" zfs_enable="YES" + + # Jail the dataset + zfs set mountpoint="${MOUNT}" "${DATASET}" + zfs set jailed=on "${DATASET}" # Add dataset to zfs.conf - echo "${DATASET} ${MOUNT}" >> "${bastille_jailsdir}/${_jail}/zfs.conf" + echo "${DATASET} ${MOUNT}" >> "${bastille_jailsdir}/${JAIL}/zfs.conf" + + # Add config to jail.conf + sed -i '' '/^}$/d' "${jail_config}" + cat << EOF >> "${jail_config}" + # Jailed dataset: ${DATASET} + exec.created += "zfs jail ${JAIL} ${DATASET}"; +} +EOF if [ "${AUTO}" -eq 1 ]; then - bastille start "${_jail}" + bastille start "${JAIL}" fi } zfs_unjail_dataset() { + local jail_config="${bastille_jailsdir}/${JAIL}/jail.conf" + # Exit if DATASET is empty if [ -z "${DATASET}" ]; then usage @@ -98,57 +118,65 @@ zfs_unjail_dataset() { fi # Validate jail state - check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - bastille stop "${_jail}" + check_target_is_stopped "${JAIL}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${JAIL}" else error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi + # Unjail the dataset + zfs set jailed=off "${DATASET}" + zfs umount "${DATASET}" + # Remove dataset from zfs.conf - if ! grep -hoqsw "${DATASET}" ${bastille_jailsdir}/${_jail}/zfs.conf; then + if ! grep -hoqsw "${DATASET}" ${bastille_jailsdir}/${JAIL}/zfs.conf; then error_exit "[ERROR]: Dataset not present in zfs.conf." else - sed -i '' "\#.*${DATASET}.*#d" "${bastille_jailsdir}/${_jail}/zfs.conf" + sed -i '' "\#.*${DATASET}.*#d" "${bastille_jailsdir}/${JAIL}/zfs.conf" fi + # Remove config from jail.conf + sed -i '' "\#.*Jailed dataset: ${DATASET}.*#d" "${jail_config}" + sed -i '' "\#.*zfs jail ${JAIL} ${DATASET}.*#d" "${jail_config}" + if [ "${AUTO}" -eq 1 ]; then - bastille start "${_jail}" + bastille start "${JAIL}" fi } zfs_snapshot() { # shellcheck disable=SC2140 - zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" + zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL}"@"${TAG}" _return=$? } zfs_rollback() { # shellcheck disable=SC2140 - zfs rollback -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" + zfs rollback -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL}"@"${TAG}" # shellcheck disable=SC2140 - zfs rollback -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}/root"@"${TAG}" + zfs rollback -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL}/root"@"${TAG}" _return=$? } zfs_destroy_snapshot() { # shellcheck disable=SC2140 - zfs destroy ${OPT_DESTROY} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" + zfs destroy ${OPT_DESTROY} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL}"@"${TAG}" _return=$? } zfs_set_value() { - zfs set "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" + zfs set "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL}" _return=$? } zfs_get_value() { - zfs get "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" + zfs get "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL}" _return=$? } zfs_disk_usage() { - zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" + zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL}" _return=$? } @@ -162,10 +190,10 @@ snapshot_checks() { # Verify rollback snapshots if [ "${SNAP_ROLLBACK}" -eq 1 ]; then if [ -n "${TAG}" ]; then - SNAP_TAG_CHECK="$(zfs list -H -t snapshot -o name ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail} | grep -o "${TAG}$" | tail -n 1)" + SNAP_TAG_CHECK="$(zfs list -H -t snapshot -o name ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL} | grep -o "${TAG}$" | tail -n 1)" else - TAG="$(zfs list -H -t snapshot -o name ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail} | grep -o "bastille_${_jail}_.*$" | tail -n 1)" - SNAP_TAG_CHECK=$(echo ${TAG} | grep -wo "bastille_${_jail}_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}") + TAG="$(zfs list -H -t snapshot -o name ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL} | grep -o "bastille_${JAIL}_.*$" | tail -n 1)" + SNAP_TAG_CHECK=$(echo ${TAG} | grep -wo "bastille_${JAIL}_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}") fi if [ -z "${SNAP_TAG_CHECK}" ]; then error_continue "[ERROR]: Snapshot not found: ${TAG}" @@ -177,10 +205,10 @@ snapshot_checks() { # Generate a relatively short but unique name for the snapshots based on the current date/jail name. elif [ "${AUTO_TAG}" -eq 1 ]; then DATE=$(date +%F-%H%M%S) - TAG="bastille_${_jail}_${DATE}" + TAG="bastille_${JAIL}_${DATE}" # Check for the generated snapshot name. SNAP_GEN_CHECK="" - SNAP_GEN_CHECK=$(echo ${TAG} | grep -wo "bastille_${_jail}_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}") + SNAP_GEN_CHECK=$(echo ${TAG} | grep -wo "bastille_${JAIL}_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}") if [ -z "${SNAP_GEN_CHECK}" ]; then error_notify "[ERROR]: Failed to validate snapshot name." fi @@ -296,9 +324,9 @@ if [ -z "${bastille_zfs_zpool}" ]; then error_exit "[ERROR]: ZFS zpool not defined." fi -for _jail in ${JAILS}; do +for JAIL in ${JAILS}; do - info "\n[${_jail}]:" + info "\n[${JAIL}]:" case "${ACTION}" in destroy|destroy_snap|destroy_snapshot)