From b4779954a9b3e313072a7e254a7d691ad3416dbd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 18:50:41 -0600 Subject: [PATCH 01/40] migrate: Initial commit for migrate subcommand --- usr/local/share/bastille/migrate.sh | 235 ++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 usr/local/share/bastille/migrate.sh diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh new file mode 100644 index 00000000..1d031d76 --- /dev/null +++ b/usr/local/share/bastille/migrate.sh @@ -0,0 +1,235 @@ +#!/bin/sh +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright (c) 2018-2025, Christer Edwards +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +. /usr/local/share/bastille/common.sh + +usage() { + error_notify "Usage: bastille migrate [option(s)] TARGET HOST USER" + cat << EOF + + Options: + + -a | --auto Auto mode. Start/stop jail(s) if required. + -d | --destroy Destroy local jail after migration. + -x | --debug Enable debug mode. + +EOF + exit 1 +} + +# Handle options. +AUTO=0 +OPT_DESTROY=0 +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -a|--auto) + AUTO=1 + shift + ;; + -d|--destroy) + OPT_DESTROY=1 + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + d) OPT_DESTROY=1 ;; + x) enable_debug ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done + +if [ "$#" -ne 3 ]; then + usage +fi + +TARGET="${1}" +HOST="${2}" +USER="${3}" + +bastille_root_check +set_target_single "${TARGET}" + +# Validate jail state +check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${TARGET}" +else + info "\n[${TARGET}]:" + error_notify "Jail is running." + error_exit "Use [-a|--auto] to auto-stop the jail." +fi + +validate_host_status() { + + local _host="${1}" + local _user="${2}" + + info "\nChecking remote host status..." + + if ! ping -c 1 ${_host} >/dev/null 2>/dev/null; then + error_exit "[ERROR]: Host appears to be down" + elif ! ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then + error_notify "[ERROR]: Could not establish ssh connection to host." + error_exit "Please make sure user '${_user}' has password-less access." + else + echo "Host check successful." + fi + +} + +migrate_create_export() { + + local _jail="${1}" + + info "\nPreparing jail for migration..." + + # --xz for ZFS, otherwise --txz + if checkyesno bastille_zfs_enable; then + bastille export --xz ${_jail} ${bastille_migratedir} + else + bastille export --txz ${_jail} ${_bastille_migratedir} + fi +} + +migrate_jail() { + + local _jail="${1}" + local _host="${2}" + local _user="${3}" + + local _remote_bastille_zfs_enable="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" + local _remote_bastille_jailsdir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" + local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" + local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" + + # Verify jail does not exist remotely + if echo ${_remote_jail_list} | grep -Eoq "^${TARGET}$"; then + error_exit "[ERROR]: Jail already exists on remote system: ${TARGET}" + fi + + # Verify ZFS on both systems + if checkyesno bastille_zfs_enable; then + if ! checkyesno _remote_bastille_zfs_enable; then + error_notify "[ERROR]: ZFS is enabled locally, but not remotely." + error_exit "Enable ZFS remotely to continue." + else + + info "\nAttempting to send jail to remote system..." + + local _file="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.xz")" + local _file_sha256="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.sha256")" + + # Send sha256 + if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + + # Send jail export + if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + rm -f "${bastille_migratedir}/${_file}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + fi + else + if checkyesno _remote_bastille_zfs_enable; then + error_notify "[ERROR]: ZFS is enabled remotely, but not locally." + error_exit "Enable ZFS locally to continue." + else + + info "\nAttempting to send jail to remote system..." + + local _file="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.txz")" + local _file_sha256="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.sha256")" + + # Send sha256 + if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + + # Send jail export + if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + rm -f "${bastille_migratedir}/${_file}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + fi + fi + + # Import the jail remotely + if ! ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" + error_exit "[ERROR]: Failed to import jail on remote system." + fi + + # Remove archive files from local and remote system + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" + rm -f "${bastille_migratedir}/${_file_sha256}" + rm -f "${bastille_migratedir}/${_file}" + + # Destroy old jail if FORCE=1 + if [ "${OPT_DESTROY}" -eq 1 ]; then + bastille destroy -af "${_jail}" + fi +} + +# Validate user +if [ -z "${USER}" ]; then + USER="root" +fi + +info "\nAttempting to migrate '${TARGET}' to '${HOST}'..." + +validate_host_status "${HOST}" "${USER}" + +migrate_jail "${TARGET}" "${HOST}" "${USER}" + +info "\nSuccessfully migrated '${_jail}' to '${_host}'.\n" From c1ecf22d6f6a8b9e3030d83ba3e8a78b7b712c86 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 18:51:12 -0600 Subject: [PATCH 02/40] export: Prepare for migrate command --- usr/local/share/bastille/export.sh | 50 ++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/usr/local/share/bastille/export.sh b/usr/local/share/bastille/export.sh index 34bbeb9b..ff2de4db 100644 --- a/usr/local/share/bastille/export.sh +++ b/usr/local/share/bastille/export.sh @@ -50,7 +50,7 @@ usage() { -v | --verbose Be more verbose during the ZFS send operation. --xz Export a ZFS jail using XZ(.xz) compressed image. -Note: If no export option specified, the container should be redirected to standard output. +Note: If no export option specified, the jail should be redirected to standard output. EOF exit 1 @@ -87,6 +87,7 @@ if [ -n "${bastille_export_options}" ]; then # Reference "/bastille/issues/443" DEFAULT_EXPORT_OPTS="${bastille_export_options}" + info "Default export option(s): '${DEFAULT_EXPORT_OPTS}'" for opt in ${DEFAULT_EXPORT_OPTS}; do @@ -123,7 +124,9 @@ if [ -n "${bastille_export_options}" ]; then usage;; esac done + else + # Handle options while [ $# -gt 0 ]; do case "${1}" in @@ -194,8 +197,6 @@ fi bastille_root_check set_target_single "${TARGET}" -info "\n[${_jail}]:" - # Validate for combined options if [ "${COMP_OPTION}" -gt "1" ]; then error_exit "[ERROR]: Only one compression format can be used during export." @@ -254,7 +255,7 @@ clean_zfs_snap() { zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_${TARGET}_${DATE}" } -export_check() { +export_check() { # Inform the user about the exporting method if [ -z "${USER_EXPORT}" ]; then if [ -n "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then @@ -302,35 +303,52 @@ jail_export() { # Attempt to export the container DATE=$(date +%F-%H%M%S) + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + if [ -n "${RAW_EXPORT}" ]; then + FILE_EXT="" + export_check # Export the raw container recursively and cleanup temporary snapshots zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_${TARGET}_${DATE}" \ > "${bastille_backupsdir}/${TARGET}_${DATE}" + clean_zfs_snap + elif [ -n "${GZIP_EXPORT}" ]; then + FILE_EXT=".gz" + export_check # Export the raw container recursively and cleanup temporary snapshots zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_${TARGET}_${DATE}" | \ gzip ${bastille_compress_gz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" + clean_zfs_snap + elif [ -n "${XZ_EXPORT}" ]; then + FILE_EXT=".xz" + export_check # Export the container recursively and cleanup temporary snapshots zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_${TARGET}_${DATE}" | \ xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" + clean_zfs_snap + else + FILE_EXT="" USER_EXPORT="1" + export_check # Quietly export the container recursively, user must redirect standard output @@ -342,16 +360,21 @@ jail_export() { fi else if [ -n "${TGZ_EXPORT}" ]; then + FILE_EXT=".tgz" # Create standard tgz backup archive info "\nExporting '${TARGET}' to a compressed ${FILE_EXT} archive..." + cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | gzip ${bastille_compress_gz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" + elif [ -n "${TXZ_EXPORT}" ]; then + FILE_EXT=".txz" # Create standard txz backup archive info "\nExporting '${TARGET}' to a compressed ${FILE_EXT} archive..." + cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" else error_exit "[ERROR]: export option required" @@ -363,10 +386,13 @@ jail_export() { error_exit "[ERROR]: Failed to export '${TARGET}' container." else if [ -z "${USER_EXPORT}" ]; then + # Generate container checksum file cd "${bastille_backupsdir}" || error_exit "Failed to change directory." sha256 -q "${TARGET}_${DATE}${FILE_EXT}" > "${TARGET}_${DATE}.sha256" + info "\nExported '${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}' successfully." + fi exit 0 fi @@ -379,18 +405,22 @@ fi if [ -n "${TARGET}" ]; then + # Validate jail existence if [ ! -d "${bastille_jailsdir}/${TARGET}" ]; then error_exit "[ERROR]: Jail not found: ${TARGET}" fi - # Check if is a ZFS system + # Jail needs to be stopped on non-ZFS systems if ! checkyesno bastille_zfs_enable; then - # Check if container is running and ask for stop in non ZFS systems - if [ -n "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then - error_exit "[ERROR]: ${TARGET} is running. See 'bastille stop'." + # Validate jail state + check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${TARGET}" + else + info "\n[${TARGET}]:" + error_notify "Jail is running." + error_exit "Use [-a|--auto] to auto-stop the jail." fi fi + jail_export fi - -echo \ No newline at end of file From 356a2264c7ced7d87c6d615e57e2af64ad21f1ea Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 18:51:39 -0600 Subject: [PATCH 03/40] import: Prepare for migrate command --- usr/local/share/bastille/import.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index cf9abda3..3affc7da 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -746,9 +746,11 @@ else fi # Check if a running jail matches name or already exist -check_target_exists || error_exit "[ERROR]: Jail: ${TARGET_TRIM} already exists." +if check_target_exists "${TARGET}"; then + error_exit "[ERROR]: Jail: ${TARGET} already exists." +fi if [ -n "${TARGET}" ]; then info "\nAttempting to import jail: ${TARGET}..." jail_import -fi \ No newline at end of file +fi From 2c0f2219ca573b9f4bb93957a5016091e1768a16 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 18:52:54 -0600 Subject: [PATCH 04/40] bastille: Add migrate as subcommand --- usr/local/bin/bastille | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index e962d513..bb1c712c 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -96,6 +96,7 @@ Available Commands: jcp cp(1) files from a jail to jail(s). limits Apply resources limits to targeted container(s). See rctl(8). list List containers (running). + migrate Migrate targetted jail(s) to a remote system. mount Mount a volume inside the targeted container(s). network Add/remove network interfaces from targeted container. pkg Manipulate binary packages within targeted container(s). See pkg(8). @@ -209,6 +210,7 @@ case "${CMD}" in jcp| \ limits| \ list| \ + migrate| \ network| \ rcp| \ rdr| \ From d861d8f7531ae79456c84c60177d72ac89fd6ac7 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 20:46:01 -0600 Subject: [PATCH 05/40] bootstrap: Create migrate directory --- usr/local/share/bastille/bootstrap.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index 8556421a..25e39ca6 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -183,6 +183,18 @@ bootstrap_directories() { mkdir -p "${bastille_releasesdir}/${RELEASE}" fi + ## ${bastille_migratedir} + if [ ! -d "${bastille_migratedir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" + fi + else + mkdir -p "${bastille_migratedir}" + fi + chmod 0750 "${bastille_migratedir}" + fi + ## create subsequent releases/XX.X-RELEASE datasets elif [ ! -d "${bastille_releasesdir}/${RELEASE}" ]; then if checkyesno bastille_zfs_enable; then From 1e4c620d6bfb1cb2bb9dcdf0b04e72d38db9ccaa Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 20:49:23 -0600 Subject: [PATCH 06/40] migrate: Must supply user --- usr/local/share/bastille/migrate.sh | 38 +++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 1d031d76..4a05ccd2 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -33,7 +33,7 @@ . /usr/local/share/bastille/common.sh usage() { - error_notify "Usage: bastille migrate [option(s)] TARGET HOST USER" + error_notify "Usage: bastille migrate [option(s)] TARGET HOST [USER]" cat << EOF Options: @@ -109,16 +109,19 @@ validate_host_status() { local _user="${2}" info "\nChecking remote host status..." - + + # Host uptime if ! ping -c 1 ${_host} >/dev/null 2>/dev/null; then error_exit "[ERROR]: Host appears to be down" - elif ! ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then - error_notify "[ERROR]: Could not establish ssh connection to host." - error_exit "Please make sure user '${_user}' has password-less access." - else - echo "Host check successful." fi + # Host SSH check + if ! ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then + error_notify "[ERROR]: Could not establish ssh connection to host." + error_exit "Please make sure user '${_user}' has password-less access." + fi + + echo "Host check successful." } migrate_create_export() { @@ -127,6 +130,19 @@ migrate_create_export() { info "\nPreparing jail for migration..." + # Ensure migrate directory is in place + ## ${bastille_migratedir} + if [ ! -d "${bastille_migratedir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" + fi + else + mkdir -p "${bastille_migratedir}" + fi + chmod 0750 "${bastille_migratedir}" + fi + # --xz for ZFS, otherwise --txz if checkyesno bastille_zfs_enable; then bastille export --xz ${_jail} ${bastille_migratedir} @@ -143,7 +159,8 @@ migrate_jail() { local _remote_bastille_zfs_enable="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" local _remote_bastille_jailsdir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" - local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" + #local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" + local _remote_bastille_migratedir=/mnt/tank/extensions/bastille/migrate local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" # Verify jail does not exist remotely @@ -221,11 +238,6 @@ migrate_jail() { fi } -# Validate user -if [ -z "${USER}" ]; then - USER="root" -fi - info "\nAttempting to migrate '${TARGET}' to '${HOST}'..." validate_host_status "${HOST}" "${USER}" From 94413088aa320232a7db7586e02d5b45c2b38f9b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 20:55:27 -0600 Subject: [PATCH 07/40] migrate: Support multi target --- usr/local/share/bastille/migrate.sh | 38 ++++++++++++++++++----------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 4a05ccd2..28211e8a 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -92,16 +92,7 @@ HOST="${2}" USER="${3}" bastille_root_check -set_target_single "${TARGET}" - -# Validate jail state -check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - bastille stop "${TARGET}" -else - info "\n[${TARGET}]:" - error_notify "Jail is running." - error_exit "Use [-a|--auto] to auto-stop the jail." -fi +set_target "${TARGET}" validate_host_status() { @@ -238,10 +229,29 @@ migrate_jail() { fi } -info "\nAttempting to migrate '${TARGET}' to '${HOST}'..." - +# Validate host uptime validate_host_status "${HOST}" "${USER}" -migrate_jail "${TARGET}" "${HOST}" "${USER}" +for _jail in ${JAILS}; do -info "\nSuccessfully migrated '${_jail}' to '${_host}'.\n" + ( + + # Validate jail state + check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${_jail}" + else + info "\n[${_jail}]:" + error_notify "Jail is running." + error_continue "Use [-a|--auto] to auto-stop the jail." + fi + + info "\nAttempting to migrate '${_jail}' to '${HOST}'..." + + migrate_jail "${TARGET}" "${HOST}" "${USER}" + + info "\nSuccessfully migrated '${_jail}' to '${_host}'.\n" + + ) & + +done +wait From 80d8da942b1a1821afe514eecf2ae75fe27cf72e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 20:59:23 -0600 Subject: [PATCH 08/40] migrate: Use grep to get filename --- usr/local/share/bastille/migrate.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 28211e8a..a915978d 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -150,8 +150,7 @@ migrate_jail() { local _remote_bastille_zfs_enable="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" local _remote_bastille_jailsdir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" - #local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" - local _remote_bastille_migratedir=/mnt/tank/extensions/bastille/migrate + local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" # Verify jail does not exist remotely @@ -168,8 +167,8 @@ migrate_jail() { info "\nAttempting to send jail to remote system..." - local _file="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.xz")" - local _file_sha256="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.sha256")" + local _file="$(grep -Eo "^${_jail}_.*\.xz" "${bastille_migratedir}")" + local _file_sha256="$(grep -Eo "^${_jail}_.*\.sha256" "${bastille_migratedir}")" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then @@ -192,8 +191,8 @@ migrate_jail() { info "\nAttempting to send jail to remote system..." - local _file="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.txz")" - local _file_sha256="$(ls -a ${bastille_migratedir} | grep -Eo "^${_jail}_.*\.sha256")" + local _file="$(grep -Eo "^${_jail}_.*\.txz" "${bastille_migratedir}")" + local _file_sha256="$(grep -Eo "^${_jail}_.*\.sha256" "${bastille_migratedir}")" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then From 125efe745aa1b586921b3390674b0220bbc83838 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 21:00:35 -0600 Subject: [PATCH 09/40] config file: Add bastille_migratedir --- usr/local/etc/bastille/bastille.conf.sample | 1 + 1 file changed, 1 insertion(+) diff --git a/usr/local/etc/bastille/bastille.conf.sample b/usr/local/etc/bastille/bastille.conf.sample index 5287c8eb..ea4c3a50 100644 --- a/usr/local/etc/bastille/bastille.conf.sample +++ b/usr/local/etc/bastille/bastille.conf.sample @@ -9,6 +9,7 @@ bastille_cachedir="${bastille_prefix}/cache" ## default bastille_jailsdir="${bastille_prefix}/jails" ## default: "${bastille_prefix}/jails" bastille_releasesdir="${bastille_prefix}/releases" ## default: "${bastille_prefix}/releases" bastille_templatesdir="${bastille_prefix}/templates" ## default: "${bastille_prefix}/templates" +bastille_migratedir="${bastille_prefix}/migrate" ## default: "${bastille_prefix}/migrate" bastille_logsdir="/var/log/bastille" ## default: "/var/log/bastille" ## pf configuration path From b34de8f3343ed387b3393b82fb636346a30c4a25 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 21:11:28 -0600 Subject: [PATCH 10/40] migrate: Fix names --- usr/local/share/bastille/migrate.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index a915978d..35fc6c72 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -165,7 +165,7 @@ migrate_jail() { error_exit "Enable ZFS remotely to continue." else - info "\nAttempting to send jail to remote system..." + info "\nAttempting to migrate jail to remote system..." local _file="$(grep -Eo "^${_jail}_.*\.xz" "${bastille_migratedir}")" local _file_sha256="$(grep -Eo "^${_jail}_.*\.sha256" "${bastille_migratedir}")" @@ -189,7 +189,7 @@ migrate_jail() { error_exit "Enable ZFS locally to continue." else - info "\nAttempting to send jail to remote system..." + info "\nAttempting to migrate jail to remote system..." local _file="$(grep -Eo "^${_jail}_.*\.txz" "${bastille_migratedir}")" local _file_sha256="$(grep -Eo "^${_jail}_.*\.sha256" "${bastille_migratedir}")" @@ -246,9 +246,9 @@ for _jail in ${JAILS}; do info "\nAttempting to migrate '${_jail}' to '${HOST}'..." - migrate_jail "${TARGET}" "${HOST}" "${USER}" + migrate_jail "${_jail}" "${HOST}" "${USER}" - info "\nSuccessfully migrated '${_jail}' to '${_host}'.\n" + info "\nSuccessfully migrated '${_jail}' to '${HOST}'.\n" ) & From 5cbfa987c5a7ac90e8d4864c8e564c81141975fb Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 21:33:58 -0600 Subject: [PATCH 11/40] Update migrate.sh --- usr/local/share/bastille/migrate.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 35fc6c72..01623708 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -246,6 +246,8 @@ for _jail in ${JAILS}; do info "\nAttempting to migrate '${_jail}' to '${HOST}'..." + migrate_create_export "${_jail}" + migrate_jail "${_jail}" "${HOST}" "${USER}" info "\nSuccessfully migrated '${_jail}' to '${HOST}'.\n" From d6fbfc31fd4ea39b799fdc84a5ee50885fd14cbe Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 4 May 2025 21:45:49 -0600 Subject: [PATCH 12/40] Update migrate.sh --- usr/local/share/bastille/migrate.sh | 257 ++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 01623708..6e0f51ad 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -231,6 +231,249 @@ migrate_jail() { # Validate host uptime validate_host_status "${HOST}" "${USER}" +for _jail in ${JAILS}; do + + ( + + # Validate jail state + check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${_jail}" + else + info "\n[${_jail}]:" + error_notify "Jail is running." + error_continue "Use [-a|--auto] to auto-stop the jail."#!/bin/sh +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright (c) 2018-2025, Christer Edwards +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +. /usr/local/share/bastille/common.sh + +usage() { + error_notify "Usage: bastille migrate [option(s)] TARGET HOST [USER]" + cat << EOF + + Options: + + -a | --auto Auto mode. Start/stop jail(s) if required. + -d | --destroy Destroy local jail after migration. + -x | --debug Enable debug mode. + +EOF + exit 1 +} + +# Handle options. +AUTO=0 +OPT_DESTROY=0 +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -a|--auto) + AUTO=1 + shift + ;; + -d|--destroy) + OPT_DESTROY=1 + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + d) OPT_DESTROY=1 ;; + x) enable_debug ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done + +if [ "$#" -ne 3 ]; then + usage +fi + +TARGET="${1}" +HOST="${2}" +USER="${3}" + +bastille_root_check +set_target "${TARGET}" + +validate_host_status() { + + local _host="${1}" + local _user="${2}" + + info "\nChecking remote host status..." + + # Host uptime + if ! ping -c 1 ${_host} >/dev/null 2>/dev/null; then + error_exit "[ERROR]: Host appears to be down" + fi + + # Host SSH check + if ! ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then + error_notify "[ERROR]: Could not establish ssh connection to host." + error_exit "Please make sure user '${_user}' has password-less access." + fi + + echo "Host check successful." +} + +migrate_create_export() { + + local _jail="${1}" + + info "\nPreparing jail for migration..." + + # Ensure migrate directory is in place + ## ${bastille_migratedir} + if [ ! -d "${bastille_migratedir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" + fi + else + mkdir -p "${bastille_migratedir}" + fi + chmod 0750 "${bastille_migratedir}" + fi + + # --xz for ZFS, otherwise --txz + if checkyesno bastille_zfs_enable; then + bastille export --xz ${_jail} ${bastille_migratedir} + else + bastille export --txz ${_jail} ${_bastille_migratedir} + fi +} + +migrate_jail() { + + local _jail="${1}" + local _host="${2}" + local _user="${3}" + + local _remote_bastille_zfs_enable="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" + local _remote_bastille_jailsdir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" + local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" + local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" + + # Verify jail does not exist remotely + if echo ${_remote_jail_list} | grep -Eoq "^${TARGET}$"; then + error_exit "[ERROR]: Jail already exists on remote system: ${TARGET}" + fi + + # Verify ZFS on both systems + if checkyesno bastille_zfs_enable; then + if ! checkyesno _remote_bastille_zfs_enable; then + error_notify "[ERROR]: ZFS is enabled locally, but not remotely." + error_exit "Enable ZFS remotely to continue." + else + + info "\nAttempting to migrate jail to remote system..." + + local _file="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.xz")" + local _file_sha256="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.sha256")" + + # Send sha256 + if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + + # Send jail export + if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + rm -f "${bastille_migratedir}/${_file}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + fi + else + if checkyesno _remote_bastille_zfs_enable; then + error_notify "[ERROR]: ZFS is enabled remotely, but not locally." + error_exit "Enable ZFS locally to continue." + else + + info "\nAttempting to migrate jail to remote system..." + + local _file="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.txz")" + local _file_sha256="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.sha256")" + + # Send sha256 + if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + + # Send jail export + if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + rm -f "${bastille_migratedir}/${_file_sha256}" + rm -f "${bastille_migratedir}/${_file}" + error_exit "[ERROR]: Failed to send jail to remote system." + fi + fi + fi + + # Import the jail remotely + if ! ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" + error_exit "[ERROR]: Failed to import jail on remote system." + fi + + # Remove archive files from local and remote system + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" + rm -f "${bastille_migratedir}/${_file_sha256}" + rm -f "${bastille_migratedir}/${_file}" + + # Destroy old jail if FORCE=1 + if [ "${OPT_DESTROY}" -eq 1 ]; then + bastille destroy -af "${_jail}" + fi +} + +# Validate host uptime +validate_host_status "${HOST}" "${USER}" + for _jail in ${JAILS}; do ( @@ -254,5 +497,19 @@ for _jail in ${JAILS}; do ) & +done +wait + fi + + info "\nAttempting to migrate '${_jail}' to '${HOST}'..." + + migrate_create_export "${_jail}" + + migrate_jail "${_jail}" "${HOST}" "${USER}" + + info "\nSuccessfully migrated '${_jail}' to '${HOST}'.\n" + + ) & + done wait From 21e460391bbf2b44513904d6c2d4f168a0c94d37 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 07:05:19 -0600 Subject: [PATCH 13/40] migrate: Did i really have double code? --- usr/local/share/bastille/migrate.sh | 257 +--------------------------- 1 file changed, 1 insertion(+), 256 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 6e0f51ad..9e6f76c9 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -142,249 +142,6 @@ migrate_create_export() { fi } -migrate_jail() { - - local _jail="${1}" - local _host="${2}" - local _user="${3}" - - local _remote_bastille_zfs_enable="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" - local _remote_bastille_jailsdir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" - local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" - local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" - - # Verify jail does not exist remotely - if echo ${_remote_jail_list} | grep -Eoq "^${TARGET}$"; then - error_exit "[ERROR]: Jail already exists on remote system: ${TARGET}" - fi - - # Verify ZFS on both systems - if checkyesno bastille_zfs_enable; then - if ! checkyesno _remote_bastille_zfs_enable; then - error_notify "[ERROR]: ZFS is enabled locally, but not remotely." - error_exit "Enable ZFS remotely to continue." - else - - info "\nAttempting to migrate jail to remote system..." - - local _file="$(grep -Eo "^${_jail}_.*\.xz" "${bastille_migratedir}")" - local _file_sha256="$(grep -Eo "^${_jail}_.*\.sha256" "${bastille_migratedir}")" - - # Send sha256 - if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" - error_exit "[ERROR]: Failed to send jail to remote system." - fi - - # Send jail export - if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" - rm -f "${bastille_migratedir}/${_file}" - error_exit "[ERROR]: Failed to send jail to remote system." - fi - fi - else - if checkyesno _remote_bastille_zfs_enable; then - error_notify "[ERROR]: ZFS is enabled remotely, but not locally." - error_exit "Enable ZFS locally to continue." - else - - info "\nAttempting to migrate jail to remote system..." - - local _file="$(grep -Eo "^${_jail}_.*\.txz" "${bastille_migratedir}")" - local _file_sha256="$(grep -Eo "^${_jail}_.*\.sha256" "${bastille_migratedir}")" - - # Send sha256 - if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" - error_exit "[ERROR]: Failed to send jail to remote system." - fi - - # Send jail export - if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" - rm -f "${bastille_migratedir}/${_file}" - error_exit "[ERROR]: Failed to send jail to remote system." - fi - fi - fi - - # Import the jail remotely - if ! ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" - error_exit "[ERROR]: Failed to import jail on remote system." - fi - - # Remove archive files from local and remote system - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" - rm -f "${bastille_migratedir}/${_file_sha256}" - rm -f "${bastille_migratedir}/${_file}" - - # Destroy old jail if FORCE=1 - if [ "${OPT_DESTROY}" -eq 1 ]; then - bastille destroy -af "${_jail}" - fi -} - -# Validate host uptime -validate_host_status "${HOST}" "${USER}" - -for _jail in ${JAILS}; do - - ( - - # Validate jail state - check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - bastille stop "${_jail}" - else - info "\n[${_jail}]:" - error_notify "Jail is running." - error_continue "Use [-a|--auto] to auto-stop the jail."#!/bin/sh -# -# SPDX-License-Identifier: BSD-3-Clause -# -# Copyright (c) 2018-2025, Christer Edwards -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -. /usr/local/share/bastille/common.sh - -usage() { - error_notify "Usage: bastille migrate [option(s)] TARGET HOST [USER]" - cat << EOF - - Options: - - -a | --auto Auto mode. Start/stop jail(s) if required. - -d | --destroy Destroy local jail after migration. - -x | --debug Enable debug mode. - -EOF - exit 1 -} - -# Handle options. -AUTO=0 -OPT_DESTROY=0 -while [ "$#" -gt 0 ]; do - case "${1}" in - -h|--help|help) - usage - ;; - -a|--auto) - AUTO=1 - shift - ;; - -d|--destroy) - OPT_DESTROY=1 - shift - ;; - -x|--debug) - enable_debug - shift - ;; - -*) - for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do - case ${_opt} in - a) AUTO=1 ;; - d) OPT_DESTROY=1 ;; - x) enable_debug ;; - *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; - esac - done - shift - ;; - *) - break - ;; - esac -done - -if [ "$#" -ne 3 ]; then - usage -fi - -TARGET="${1}" -HOST="${2}" -USER="${3}" - -bastille_root_check -set_target "${TARGET}" - -validate_host_status() { - - local _host="${1}" - local _user="${2}" - - info "\nChecking remote host status..." - - # Host uptime - if ! ping -c 1 ${_host} >/dev/null 2>/dev/null; then - error_exit "[ERROR]: Host appears to be down" - fi - - # Host SSH check - if ! ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then - error_notify "[ERROR]: Could not establish ssh connection to host." - error_exit "Please make sure user '${_user}' has password-less access." - fi - - echo "Host check successful." -} - -migrate_create_export() { - - local _jail="${1}" - - info "\nPreparing jail for migration..." - - # Ensure migrate directory is in place - ## ${bastille_migratedir} - if [ ! -d "${bastille_migratedir}" ]; then - if checkyesno bastille_zfs_enable; then - if [ -n "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" - fi - else - mkdir -p "${bastille_migratedir}" - fi - chmod 0750 "${bastille_migratedir}" - fi - - # --xz for ZFS, otherwise --txz - if checkyesno bastille_zfs_enable; then - bastille export --xz ${_jail} ${bastille_migratedir} - else - bastille export --txz ${_jail} ${_bastille_migratedir} - fi -} - migrate_jail() { local _jail="${1}" @@ -497,19 +254,7 @@ for _jail in ${JAILS}; do ) & -done -wait - fi - - info "\nAttempting to migrate '${_jail}' to '${HOST}'..." - - migrate_create_export "${_jail}" - - migrate_jail "${_jail}" "${HOST}" "${USER}" - - info "\nSuccessfully migrated '${_jail}' to '${HOST}'.\n" - - ) & + bastille_running_jobs "${bastille_process_limit}" done wait From 937c28e871d72143d67a518035b456bdaaa55317 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 07:37:44 -0600 Subject: [PATCH 14/40] migrate: Properly find file --- usr/local/share/bastille/migrate.sh | 45 ++++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 9e6f76c9..0f85159b 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -115,6 +115,15 @@ validate_host_status() { echo "Host check successful." } +migrate_cleanup() { + + local _jail"${1}" + + # Remove archive files from local and remote system + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*." + rm -f "${bastille_migratedir}/${_jail}_*." +} + migrate_create_export() { local _jail="${1}" @@ -155,77 +164,73 @@ migrate_jail() { # Verify jail does not exist remotely if echo ${_remote_jail_list} | grep -Eoq "^${TARGET}$"; then + migrate_cleanup "${_jail}" error_exit "[ERROR]: Jail already exists on remote system: ${TARGET}" fi # Verify ZFS on both systems if checkyesno bastille_zfs_enable; then if ! checkyesno _remote_bastille_zfs_enable; then + migrate_cleanup "${_jail}" error_notify "[ERROR]: ZFS is enabled locally, but not remotely." error_exit "Enable ZFS remotely to continue." else info "\nAttempting to migrate jail to remote system..." - local _file="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.xz")" - local _file_sha256="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.sha256")" + local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.xz$" | head -n1)" + local _file_sha256="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.sha256$" | head -n1)" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" + migrate_cleanup "${_jail}" error_exit "[ERROR]: Failed to send jail to remote system." fi # Send jail export if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" - rm -f "${bastille_migratedir}/${_file}" + migrate_cleanup "${_jail}" error_exit "[ERROR]: Failed to send jail to remote system." fi fi else if checkyesno _remote_bastille_zfs_enable; then + migrate_cleanup "${_jail}" error_notify "[ERROR]: ZFS is enabled remotely, but not locally." error_exit "Enable ZFS locally to continue." else info "\nAttempting to migrate jail to remote system..." - local _file="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.txz")" - local _file_sha256="$(ls "${bastille_migratedir}" | grep -Eo "^${_jail}_.*\.sha256")" + local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.txz$" | head -n1)" + local _file_sha256="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.sha256$" | head -n1)" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" - error_exit "[ERROR]: Failed to send jail to remote system." + migrate_cleanup "${_jail}" + error_exit "[ERROR]: Failed to migrate jail to remote system." fi # Send jail export if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then - rm -f "${bastille_migratedir}/${_file_sha256}" - rm -f "${bastille_migratedir}/${_file}" - error_exit "[ERROR]: Failed to send jail to remote system." + migrate_cleanup "${_jail}" + error_exit "[ERROR]: Failed to migrate jail to remote system." fi fi fi # Import the jail remotely if ! ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" + migrate_cleanup "${_jail}" error_exit "[ERROR]: Failed to import jail on remote system." fi - # Remove archive files from local and remote system - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file_sha256}" - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_file}" - rm -f "${bastille_migratedir}/${_file_sha256}" - rm -f "${bastille_migratedir}/${_file}" - # Destroy old jail if FORCE=1 if [ "${OPT_DESTROY}" -eq 1 ]; then bastille destroy -af "${_jail}" fi + + migrate_cleanup "${_jail}" } # Validate host uptime From c7d29dc98ea7121bc87ce2cabb60979143683212 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 08:59:17 -0600 Subject: [PATCH 15/40] migrate: Fix cleanup --- usr/local/share/bastille/migrate.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 0f85159b..d51c94cf 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -120,8 +120,8 @@ migrate_cleanup() { local _jail"${1}" # Remove archive files from local and remote system - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*." - rm -f "${bastille_migratedir}/${_jail}_*." + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" + rm -f "${bastille_migratedir}/${_jail}_*.*" } migrate_create_export() { From b411177732a74736212b11b1541c5f33df2d0a9a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 13:25:48 -0600 Subject: [PATCH 16/40] pkg: Fix prompt --- usr/local/share/bastille/pkg.sh | 60 ++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/usr/local/share/bastille/pkg.sh b/usr/local/share/bastille/pkg.sh index d73b6857..a4e5fb50 100644 --- a/usr/local/share/bastille/pkg.sh +++ b/usr/local/share/bastille/pkg.sh @@ -48,6 +48,7 @@ EOF # Handle options. AUTO=0 +AUTO_YES=0 USE_HOST_PKG=0 while [ "$#" -gt 0 ]; do case "${1}" in @@ -62,6 +63,10 @@ while [ "$#" -gt 0 ]; do USE_HOST_PKG=1 shift ;; + -y|--yes) + AUTO_YES=1 + shift + ;; -x|--debug) enable_debug shift @@ -71,6 +76,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in a) AUTO=1 ;; H) USE_HOST_PKG=1 ;; + y) AUTO_YES=1 ;; x) enable_debug ;; *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac @@ -89,15 +95,14 @@ fi TARGET="${1}" shift + +OPTION="" +BLA="$@" bastille_root_check set_target "${TARGET}" -errors=0 - -for _jail in ${JAILS}; do - - ( +pkg_run_command() { # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then @@ -120,18 +125,49 @@ for _jail in ${JAILS}; do if ! jexec -l "${_jail}" /usr/bin/apt "$@"; then errors=1 fi - elif [ "${USE_HOST_PKG}" = 1 ]; then - if ! /usr/sbin/pkg -j "${_jail}" "$@"; then + elif [ "${USE_HOST_PKG}" -eq 1 ]; then + if [ "${AUTO_YES}" -eq 1 ]; then + _jail_cmd="env ASSUME_ALWAYS_YES=yes /usr/sbin/pkg -j "${_jail}" "$@"" + else + _jail_cmd="/usr/sbin/pkg -j "${_jail}" "$@"" + fi + if ! ${_jail_cmd}; then errors=1 fi else - if ! jexec -l -U root "${_jail}" /usr/sbin/pkg "$@"; then + if [ "${AUTO_YES}" -eq 1 ]; then + _jail_cmd="jexec -l -U root "${_jail}" env ASSUME_ALWAYS_YES=yes /usr/sbin/pkg "$@"" + else + _jail_cmd="jexec -l -U root "${_jail}" /usr/sbin/pkg "$@"" + fi + if ! ${_jail_cmd}; then errors=1 fi fi - - ) & - +} + +errors=0 + +for _jail in ${JAILS}; do + + if [ "${AUTO_YES}" -eq 1 ]; then + + ( + + pkg_run_command "$@" + + ) & + + else + + ( + + pkg_run_command "$@" + + ) + + fi + bastille_running_jobs "${bastille_process_limit}" done @@ -141,4 +177,4 @@ if [ $errors -ne 0 ]; then error_exit "[ERROR]: Failed to apply on some jails, please check logs" else echo -fi \ No newline at end of file +fi From 23a734c7d58641ad45b1b26e5a6f0918a81a708e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 13:33:30 -0600 Subject: [PATCH 17/40] fix shellcheck --- usr/local/share/bastille/pkg.sh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/pkg.sh b/usr/local/share/bastille/pkg.sh index a4e5fb50..2e674f44 100644 --- a/usr/local/share/bastille/pkg.sh +++ b/usr/local/share/bastille/pkg.sh @@ -40,6 +40,7 @@ usage() { -a | --auto Auto mode. Start/stop jail(s) if required. -H | --host Use the hosts 'pkg' instead of the jails. + -y | --yes Assume always yes for pkg command. Do not prompt. -x | --debug Enable debug mode. EOF @@ -95,9 +96,6 @@ fi TARGET="${1}" shift - -OPTION="" -BLA="$@" bastille_root_check set_target "${TARGET}" @@ -127,18 +125,18 @@ pkg_run_command() { fi elif [ "${USE_HOST_PKG}" -eq 1 ]; then if [ "${AUTO_YES}" -eq 1 ]; then - _jail_cmd="env ASSUME_ALWAYS_YES=yes /usr/sbin/pkg -j "${_jail}" "$@"" + _jail_cmd="env ASSUME_ALWAYS_YES=yes /usr/sbin/pkg -j ${_jail} $@" else - _jail_cmd="/usr/sbin/pkg -j "${_jail}" "$@"" + _jail_cmd="/usr/sbin/pkg -j ${_jail} $@" fi if ! ${_jail_cmd}; then errors=1 fi else if [ "${AUTO_YES}" -eq 1 ]; then - _jail_cmd="jexec -l -U root "${_jail}" env ASSUME_ALWAYS_YES=yes /usr/sbin/pkg "$@"" + _jail_cmd="jexec -l -U root ${_jail} env ASSUME_ALWAYS_YES=yes /usr/sbin/pkg $@" else - _jail_cmd="jexec -l -U root "${_jail}" /usr/sbin/pkg "$@"" + _jail_cmd="jexec -l -U root ${_jail} /usr/sbin/pkg $@" fi if ! ${_jail_cmd}; then errors=1 From e82938904d20ed55e609de80d9cbeaec855e4a24 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 14:50:33 -0600 Subject: [PATCH 18/40] migrate: Error if no migratedir --- usr/local/share/bastille/migrate.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index d51c94cf..12a355aa 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -132,6 +132,10 @@ migrate_create_export() { # Ensure migrate directory is in place ## ${bastille_migratedir} + if [ -z "${bastille_migratedir}" ]; then + error_notify "[ERROR]: No migrate directory found." + error_exit "Did you diff the config file?" + fi if [ ! -d "${bastille_migratedir}" ]; then if checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ]; then From 76e480e756219b357f510c893f9209e8bfa85824 Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Mon, 5 May 2025 17:44:59 -0600 Subject: [PATCH 19/40] docs: Add migrate docs --- docs/chapters/migration.rst | 39 ++++++++++++++++++++++++++- docs/chapters/subcommands/migrate.rst | 18 +++++++++++++ usr/local/share/bastille/migrate.sh | 26 +++++++++++------- 3 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 docs/chapters/subcommands/migrate.rst diff --git a/docs/chapters/migration.rst b/docs/chapters/migration.rst index 8fd05f4f..ac1d6ae4 100644 --- a/docs/chapters/migration.rst +++ b/docs/chapters/migration.rst @@ -1,7 +1,44 @@ -========= Migration ========= +Bastille +-------- + +Bastille supports migrations to a remote system using the ``migrate`` subcommand. + +Prerequisites +^^^^^^^^^^^^^ + +There are a couple of things that need to be in place before running the ``migrate`` command. + +First, you must have bastille configured both locally and remotely to use the same filesystem +configuration. ZFS on both, or UFS on both. + +Second, we need a user on the remote system that has key-based authentication set up. Bastille +does not support password-based authentication. This also implies that SSH is working on the +remote system. This user also needs ``sudo`` permissions on the remote system. + +Third, if updating from a previous version, please make sure to ``diff`` your ``bastille.conf`` +file, as the ``migrate`` sub-command adds a new variable called ``bastille_migratedir``. + +Migration +^^^^^^^^^ + +To migrate a jail (or multiple jails) we can simply run +``bastille migrate TARGET USER HOST``. This will export the jail(s), send them to the +remote system, and import them. + +The ``migrate`` sub-command includes the ``-a|--auto`` option, which will auto-stop the old jail, +migrate it, and attempt to start the migrated jail on the remote system after importing it. See the +warning below about auto-starting the migrated jail. + +WARNING: Every system is unique, has different interfaces, bridges, and network configurations. +It is possible, with the right configuration, for jails to start and work normally. But for some +systems, it will be necessary to edit the ``jail.conf`` file of the migrated jail to get it working +properly. + +You can optionally set ``-d|--destroy`` to have Bastille destroy the old jail on completion. + iocage ------ diff --git a/docs/chapters/subcommands/migrate.rst b/docs/chapters/subcommands/migrate.rst new file mode 100644 index 00000000..e3b12d2c --- /dev/null +++ b/docs/chapters/subcommands/migrate.rst @@ -0,0 +1,18 @@ +migrate +======= + +The ``migrate`` sub-command allows migrating the targeted jail(s) to +another remote system. See the chapter on Migration. + +This sub-command supports multiple targets. + +.. code-block:: shell + + ishmael ~ # bastille migrate help + Usage: bastille migrate [option(s)] TARGET USER HOST + + Options: + + -a | --auto Auto mode. Start/stop jail(s) if required. + -d | --destroy Destroy local jail after migration. + -x | --debug Enable debug mode. diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 12a355aa..19565471 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -33,7 +33,7 @@ . /usr/local/share/bastille/common.sh usage() { - error_notify "Usage: bastille migrate [option(s)] TARGET HOST [USER]" + error_notify "Usage: bastille migrate [option(s)] TARGET USER HOST" cat << EOF Options: @@ -88,16 +88,16 @@ if [ "$#" -ne 3 ]; then fi TARGET="${1}" -HOST="${2}" -USER="${3}" +USER="${2}" +HOST="${3}" bastille_root_check set_target "${TARGET}" validate_host_status() { - local _host="${1}" - local _user="${2}" + local _user="${1}" + local _host="${2}" info "\nChecking remote host status..." @@ -158,8 +158,8 @@ migrate_create_export() { migrate_jail() { local _jail="${1}" - local _host="${2}" - local _user="${3}" + local _user="${2}" + local _host="${3}" local _remote_bastille_zfs_enable="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" local _remote_bastille_jailsdir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" @@ -229,16 +229,22 @@ migrate_jail() { error_exit "[ERROR]: Failed to import jail on remote system." fi - # Destroy old jail if FORCE=1 + # Destroy old jail if OPT_DESTROY=1 if [ "${OPT_DESTROY}" -eq 1 ]; then bastille destroy -af "${_jail}" fi + # Remove archives migrate_cleanup "${_jail}" + + # Start new jail if AUTO=1 + if [ "${AUTO}" -eq 1 ]; then + ssh ${_user}@${_host} sudo bastille start "${_jail}" + fi } # Validate host uptime -validate_host_status "${HOST}" "${USER}" +validate_host_status "${USER}" "${HOST}" for _jail in ${JAILS}; do @@ -257,7 +263,7 @@ for _jail in ${JAILS}; do migrate_create_export "${_jail}" - migrate_jail "${_jail}" "${HOST}" "${USER}" + migrate_jail "${_jail}" "${USER}" "${HOST}" info "\nSuccessfully migrated '${_jail}' to '${HOST}'.\n" From bd24727a2c7499b9e18453b81fd49854157d9893 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 17:58:37 -0600 Subject: [PATCH 20/40] common: Exit if no jails --- usr/local/share/bastille/common.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 21dcf6f8..8c395bed 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -247,6 +247,10 @@ set_target() { TARGET="${TARGET} ${_jail}" JAILS="${JAILS} ${_jail}" done + # Exit if no jails + if [ -z "${TARGET}" ] && [ -z "${JAILS}" ]; then + exit 1 + fi if [ "${_order}" = "forward" ]; then TARGET="$(list_jail_priority "${TARGET}" | sort -k2 -n | awk '{print $1}')" JAILS="$(list_jail_priority "${TARGET}" | sort -k2 -n | awk '{print $1}')" @@ -281,6 +285,10 @@ set_target_single() { exit 1 fi fi + # Exit if no jails + if [ -z "${TARGET}" ] && [ -z "${JAILS}" ]; then + exit 1 + fi TARGET="${_TARGET}" JAILS="${_TARGET}" export TARGET @@ -295,6 +303,10 @@ target_all_jails() { JAILS="${JAILS} ${_jail}" fi done + # Exit if no jails + if [ -z "${JAILS}" ]; then + exit 1 + fi if [ "${_order}" = "forward" ]; then JAILS="$(list_jail_priority "${JAILS}" | sort -k2 -n | awk '{print $1}')" elif [ "${_order}" = "reverse" ]; then From eb1bce22898633a28bfc8adda67064a4c02b63d1 Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Mon, 5 May 2025 18:41:34 -0600 Subject: [PATCH 21/40] docs: README update --- README.md | 19 ++++++------ docs/chapters/usage.rst | 67 +++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 7a23c58d..3ca56610 100644 --- a/README.md +++ b/README.md @@ -59,28 +59,29 @@ Available Commands: clone Clone an existing jail. cmd Execute arbitrary command on targeted jail(s). config Get, set or remove a config value for the targeted jail(s). - console Console into a running jail. + console Console into a jail. convert Convert thin jail to thick jail, or convert a jail to a custom release. - cp cp(1) files from host or jail to host or targeted jail(s). + cp cp(1) files from host to targeted jail(s). create Create a jail. destroy Destroy a jail or release. edit Edit jail configuration files (advanced). - export Exports a jail. + export Export a jail. help Help about any command. htop Interactive process viewer (requires htop). import Import a jail. jcp cp(1) files from a jail to jail(s). - limits Apply resources limits to targeted jail(s). See rctl(8). - list List jails, releases, templates etc... + limits Apply resources limits to targeted jail(s). See rctl(8) and cpuset(1). + list List jails, releases, templates and more... + migrate Migrate targeted jail(s) to a remote system. mount Mount a volume inside targeted jail(s). network Add or remove interfaces from targeted jail(s). pkg Manipulate binary packages within targeted jail(s). See pkg(8). rcp cp(1) files from a jail to host. - rdr Redirect host port to container port. + rdr Redirect host port to jail port. rename Rename a jail. restart Restart a running jail. service Manage services within targeted jail(s). - setup Attempt to auto-configure network, firewall and storage on new installs. + setup Attempt to auto-configure network, firewall and storage and more... start Start a stopped jail. stop Stop a running jail. sysrc Safely edit rc files within targeted jail(s). @@ -95,8 +96,8 @@ Available Commands: Use "bastille -v|--version" for version information. Use "bastille command -h|--help" for more information about a command. -Use "bastille [-c|--config config.conf] command" to specify a non-default config file. -Use "bastille [-p|--parallel VALUE] command" to run bastille in parallel mode. +Use "bastille -c|--config config.conf command" to specify a non-default config file. +Use "bastille -p|--parallel VALUE command" to run bastille in parallel mode. ``` diff --git a/docs/chapters/usage.rst b/docs/chapters/usage.rst index 2086d6db..b6623a8f 100644 --- a/docs/chapters/usage.rst +++ b/docs/chapters/usage.rst @@ -8,46 +8,49 @@ Usage containerized applications on FreeBSD. Usage: - bastille command TARGET [args] + bastille command [options(s)] TARGET [option(s)] [args] Available Commands: - bootstrap Bootstrap a FreeBSD release for container base. - clone Clone an existing container. - cmd Execute arbitrary command on targeted container(s). - config Get or set a config value for the targeted container(s). - console Console into a running container. - convert Convert a Thin container into a Thick container. - cp cp(1) files from host or container to host or targeted container(s). - create Create a new thin container or a thick container if -T|--thick option specified. - destroy Destroy a stopped container or a FreeBSD release. - edit Edit container configuration files (advanced). - export Exports a specified container. + bootstrap Bootstrap a release for jail base. + clone Clone an existing jail. + cmd Execute arbitrary command on targeted jail(s). + config Get, set or remove a config value for the targeted jail(s). + console Console into a jail. + convert Convert thin jail to thick jail, or convert a jail to a custom release. + cp cp(1) files from host to targeted jail(s). + create Create a jail. + destroy Destroy a jail or release. + edit Edit jail configuration files (advanced). + export Export a jail. help Help about any command. htop Interactive process viewer (requires htop). - import Import a specified container. - jcp cp(1) files from a jail to targeted jail(s). - limits Apply resources limits to targeted container(s). See rctl(8). - list List containers (running). - mount Mount a volume inside the targeted container(s). - pkg Manipulate binary packages within targeted container(s). See pkg(8). + import Import a jail. + jcp cp(1) files from a jail to jail(s). + limits Apply resources limits to targeted jail(s). See rctl(8) and cpuset(1). + list List jails, releases, templates and more... + migrate Migrate targeted jail(s) to a remote system. + mount Mount a volume inside targeted jail(s). + network Add or remove interfaces from targeted jail(s). + pkg Manipulate binary packages within targeted jail(s). See pkg(8). rcp cp(1) files from a jail to host. - rdr Redirect host port to container port. - rename Rename a container. - restart Restart a running container. - service Manage services within targeted container(s). - setup Attempt to auto-configure network, firewall and storage on new installs. - start Start a stopped container. - stop Stop a running container. - sysrc Safely edit rc files within targeted container(s). - tags Add or remove tags to targeted container(s). - template Apply file templates to targeted container(s). + rdr Redirect host port to jail port. + rename Rename a jail. + restart Restart a running jail. + service Manage services within targeted jail(s). + setup Attempt to auto-configure network, firewall and storage and more... + start Start a stopped jail. + stop Stop a running jail. + sysrc Safely edit rc files within targeted jail(s). + tags Add or remove tags to targeted jail(s). + template Apply file templates to targeted jail(s). top Display and update information about the top(1) cpu processes. - umount Unmount a volume from within the targeted container(s). - update Update container base -pX release. - upgrade Upgrade container release to X.Y-RELEASE. + umount Unmount a volume from targeted jail(s). + update Update jail base -pX release. + upgrade Upgrade jail release to X.Y-RELEASE. verify Compare release against a "known good" index. zfs Manage (get|set) ZFS attributes on targeted container(s). Use "bastille -v|--version" for version information. Use "bastille command -h|--help" for more information about a command. - Use "bastille [-c|--config FILE] command" to specify a non-default config file. + Use "bastille -c|--config config.conf command" to specify a non-default config file. + Use "bastille -p|--parallel VALUE command" to run bastille in parallel mode. \ No newline at end of file From 03f26cbb7f8b7361e0cd76cff94e641160b3f484 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 5 May 2025 21:42:17 -0600 Subject: [PATCH 22/40] migrate: Add config var if not present in bastille.conf --- usr/local/share/bastille/migrate.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 19565471..f5d8b232 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -133,8 +133,11 @@ migrate_create_export() { # Ensure migrate directory is in place ## ${bastille_migratedir} if [ -z "${bastille_migratedir}" ]; then - error_notify "[ERROR]: No migrate directory found." - error_exit "Did you diff the config file?" + if ! grep -oq "bastille_migratedir=" "${BASTILLE_CONFIG}"; then + sed -i '' 's|bastille_backupsdir=.*|&\nbastille_migratedir=\"${bastille_prefix}/migrate\" ## default: \"${bastille_prefix}/migrate\"|' ${BASTILLE_CONFIG} + # shellcheck disable=SC1090 + . ${BASTILLE_CONFIG} + fi fi if [ ! -d "${bastille_migratedir}" ]; then if checkyesno bastille_zfs_enable; then From c0cd4df6c596b6b52ce2e036f19f1fb678c61c1b Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Tue, 6 May 2025 07:40:08 -0600 Subject: [PATCH 23/40] migrate: Auto creating directory required --- docs/chapters/subcommands/setup.rst | 18 ++-- usr/local/share/bastille/bootstrap.sh | 25 +++--- usr/local/share/bastille/migrate.sh | 12 +-- usr/local/share/bastille/setup.sh | 124 +++++++++++++++++++++++++- 4 files changed, 147 insertions(+), 32 deletions(-) diff --git a/docs/chapters/subcommands/setup.rst b/docs/chapters/subcommands/setup.rst index 311c617a..40987f98 100644 --- a/docs/chapters/subcommands/setup.rst +++ b/docs/chapters/subcommands/setup.rst @@ -13,12 +13,13 @@ Below is a list of available options that can be used with the ``setup`` command .. code-block:: shell ishmael ~ # bastille setup -h ## display setup help - ishmael ~ # bastille setup -l ## configure loopback interface - ishmael ~ # bastille setup -s ## configure shared interface - ishmael ~ # bastille setup -p ## configure default pf firewall - ishmael ~ # bastille setup -z ## configure ZFS storage - ishmael ~ # bastille setup -v ## configure VNET ishmael ~ # bastille setup -b ## configure bridge interface + ishmael ~ # bastille setup -f ## configure filesystem/structure + ishmael ~ # bastille setup -l ## configure loopback interface + ishmael ~ # bastille setup -p ## configure default pf firewall + ishmael ~ # bastille setup -s ## configure shared interface + ishmael ~ # bastille setup -v ## configure VNET + ishmael ~ # bastille setup -z ## configure ZFS storage ishmael ~ # bastille setup ## configure -l -p and -z The ``-l|loopback`` option will configure a loopback interface called ``bastille0`` that @@ -36,6 +37,9 @@ networking option. The ``-l|loopback`` and ``-s|shared`` options are only for ca is not specified during the ``create`` command. If an interface is specified, these options have no effect. Instead, the specified interface will be used. +The ``-f|--filesystem`` option is to ensure the proper datasets/directories are in place +for using Bastille. This should only have to be run once on a new system. + The ``-s|shared`` option is for cases where you want an actual interface to use with bastille as opposed to a loopback. Jails will be linked to the shared interface on creation. @@ -51,10 +55,10 @@ The ``-v|vnet`` option will configure your system for use with VNET ``-V`` jails The ``-b|bridge`` options will attempt to configure a bridge interface for use with bridged VNET ``-B`` jails. -Running ``bastille setup`` without any options will attempt to auto-configure the ``-l``, ``-p`` and +Running ``bastille setup`` without any options will attempt to auto-configure the ``-f``, ``-l``, ``-p`` and ``-z`` options. .. code-block:: shell ishmael ~ # bastille setup help - Usage: bastille setup [-p|pf|firewall] [-l|loopback] [-s|shared] [-z|zfs|storage] [-v|vnet] [-b|bridge] + Usage: bastille setup [-b|bridge] [-f|--filesystem] [-l|loopback] [-p|pf|firewall] [-s|shared] [-v|vnet] [-z|zfs|storage] diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index 25e39ca6..f55c3ad6 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -108,6 +108,18 @@ bootstrap_directories() { chmod 0750 "${bastille_backupsdir}" fi + ## ${bastille_migratedir} + if [ ! -d "${bastille_migratedir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" + fi + else + mkdir -p "${bastille_migratedir}" + fi + chmod 0750 "${bastille_migratedir}" + fi + ## ${bastille_cachedir} if [ ! -d "${bastille_cachedir}" ]; then if checkyesno bastille_zfs_enable; then @@ -182,19 +194,6 @@ bootstrap_directories() { else mkdir -p "${bastille_releasesdir}/${RELEASE}" fi - - ## ${bastille_migratedir} - if [ ! -d "${bastille_migratedir}" ]; then - if checkyesno bastille_zfs_enable; then - if [ -n "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" - fi - else - mkdir -p "${bastille_migratedir}" - fi - chmod 0750 "${bastille_migratedir}" - fi - ## create subsequent releases/XX.X-RELEASE datasets elif [ ! -d "${bastille_releasesdir}/${RELEASE}" ]; then if checkyesno bastille_zfs_enable; then diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index f5d8b232..a286ec20 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -130,15 +130,9 @@ migrate_create_export() { info "\nPreparing jail for migration..." - # Ensure migrate directory is in place - ## ${bastille_migratedir} - if [ -z "${bastille_migratedir}" ]; then - if ! grep -oq "bastille_migratedir=" "${BASTILLE_CONFIG}"; then - sed -i '' 's|bastille_backupsdir=.*|&\nbastille_migratedir=\"${bastille_prefix}/migrate\" ## default: \"${bastille_prefix}/migrate\"|' ${BASTILLE_CONFIG} - # shellcheck disable=SC1090 - . ${BASTILLE_CONFIG} - fi - fi + # Ensure new migrate directory is created + bastille setup -f + if [ ! -d "${bastille_migratedir}" ]; then if checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ]; then diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index ecb954ff..453632b3 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -33,14 +33,128 @@ . /usr/local/share/bastille/common.sh usage() { - error_exit "Usage: bastille setup [-p|pf|firewall] [-l|loopback] [-s|shared] [-z|zfs|storage] [-v|vnet] [-b|bridge]" + error_exit "Usage: bastille setup [-b|bridge] [-f|--filesystem] [-l|loopback] [-p|pf|firewall] [-s|shared] [-v|vnet] [-z|zfs|storage]" } # Check for too many args -if [ $# -gt 1 ]; then +if [ "$#" -gt 1 ]; then usage fi +configure_filesystem() { + + # This is so we dont have to introduce breaking + # changes on new variables added to bastille.conf + + # Ensure migrate directory is in place + ## ${bastille_migratedir} + if [ -z "${bastille_migratedir}" ]; then + if ! grep -oq "bastille_migratedir=" "${BASTILLE_CONFIG}"; then + sed -i '' 's|bastille_backupsdir=.*|&\nbastille_migratedir=\"${bastille_prefix}/migrate\" ## default: \"${bastille_prefix}/migrate\"|' ${BASTILLE_CONFIG} + # shellcheck disable=SC1090 + . ${BASTILLE_CONFIG} + fi + fi + + ## ${bastille_prefix} + if [ ! -d "${bastille_prefix}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_prefix}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}" + fi + else + mkdir -p "${bastille_prefix}" + fi + chmod 0750 "${bastille_prefix}" + # Make sure the dataset is mounted in the proper place + elif [ -d "${bastille_prefix}" ]; then + if ! zfs list "${bastille_zfs_zpool}/${bastille_zfs_prefix}" >/dev/null; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_prefix}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}" + elif [ "$(zfs get -H -o value mountpoint ${bastille_zfs_zpool}/${bastille_zfs_prefix})" != "${bastille_prefix}" ]; then + zfs set mountpoint="${bastille_prefix}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}" + fi + fi + + ## ${bastille_backupsdir} + if [ ! -d "${bastille_backupsdir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_backupsdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/backups" + fi + else + mkdir -p "${bastille_backupsdir}" + fi + chmod 0750 "${bastille_backupsdir}" + fi + + ## ${bastille_cachedir} + if [ ! -d "${bastille_cachedir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_cachedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache" + fi + else + mkdir -p "${bastille_cachedir}" + fi + fi + + ## ${bastille_jailsdir} + if [ ! -d "${bastille_jailsdir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_jailsdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails" + fi + else + mkdir -p "${bastille_jailsdir}" + fi + fi + + ## ${bastille_logsdir} + if [ ! -d "${bastille_logsdir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_logsdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/logs" + fi + else + mkdir -p "${bastille_logsdir}" + fi + fi + + ## ${bastille_templatesdir} + if [ ! -d "${bastille_templatesdir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_templatesdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/templates" + fi + else + mkdir -p "${bastille_templatesdir}" + fi + fi + + ## ${bastille_releasesdir} + if [ ! -d "${bastille_releasesdir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_releasesdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases" + fi + else + mkdir -p "${bastille_releasesdir}" + fi + fi + + ## ${bastille_migratedir} + if [ ! -d "${bastille_migratedir}" ]; then + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" + fi + else + mkdir -p "${bastille_migratedir}" + fi + chmod 0750 "${bastille_migratedir}" + fi +} + # Configure netgraph configure_netgraph() { if [ ! "$(kldstat -m netgraph)" ]; then @@ -236,6 +350,7 @@ configure_zfs() { # Run all base functions (w/o vnet) if no args if [ $# -eq 0 ]; then sysrc bastille_enable=YES + configure_filesystem configure_loopback_interface configure_pf configure_zfs @@ -248,6 +363,9 @@ case "$1" in -h|--help|help) usage ;; + -f|--filesystem) + configure_filesystem + ;; -p|pf|firewall) configure_pf ;; @@ -320,4 +438,4 @@ case "$1" in *) error_exit "[ERROR]: Unknown option: \"${1}\"" ;; -esac +esac \ No newline at end of file From d7f9ce8050c31cf8c5be443dbd269666190ba316 Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Tue, 6 May 2025 07:50:56 -0600 Subject: [PATCH 24/40] migrate: run setup -f on remote also --- usr/local/share/bastille/migrate.sh | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index a286ec20..e0777805 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -132,17 +132,7 @@ migrate_create_export() { # Ensure new migrate directory is created bastille setup -f - - if [ ! -d "${bastille_migratedir}" ]; then - if checkyesno bastille_zfs_enable; then - if [ -n "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint="${bastille_migratedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/migrate" - fi - else - mkdir -p "${bastille_migratedir}" - fi - chmod 0750 "${bastille_migratedir}" - fi + ssh ${_user}@${_host} bastille setup -f # --xz for ZFS, otherwise --txz if checkyesno bastille_zfs_enable; then From 128d5f22539c9ae830994793f9adea3c02643d4e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 09:06:30 -0600 Subject: [PATCH 25/40] migrate: use sudo for setup command --- usr/local/share/bastille/migrate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index e0777805..e2f29f39 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -132,7 +132,7 @@ migrate_create_export() { # Ensure new migrate directory is created bastille setup -f - ssh ${_user}@${_host} bastille setup -f + ssh ${_user}@${_host} sudo bastille setup -f # --xz for ZFS, otherwise --txz if checkyesno bastille_zfs_enable; then From 71f8e2ee6369b8530a8773a5987bb7013474f260 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 10:51:28 -0600 Subject: [PATCH 26/40] Update migrate.sh --- usr/local/share/bastille/migrate.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index e2f29f39..f6b7804f 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -127,6 +127,8 @@ migrate_cleanup() { migrate_create_export() { local _jail="${1}" + local _user="${2}" + local _host="${3}" info "\nPreparing jail for migration..." @@ -248,7 +250,7 @@ for _jail in ${JAILS}; do info "\nAttempting to migrate '${_jail}' to '${HOST}'..." - migrate_create_export "${_jail}" + migrate_create_export "${_jail}" "${USER}" "${HOST}" migrate_jail "${_jail}" "${USER}" "${HOST}" From 58bc9ba3a5c6d590e2790648bf323b79cb2e9ec9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 11:19:40 -0600 Subject: [PATCH 27/40] Migrate: pass all vars --- usr/local/share/bastille/migrate.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index f6b7804f..7f1138cf 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -117,7 +117,9 @@ validate_host_status() { migrate_cleanup() { - local _jail"${1}" + local _jail="${1}" + local _user="${2}" + local _host="${3}" # Remove archive files from local and remote system ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" From a03baa0729741bb0aea2bd69eb1e586d1fbb631c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 11:58:00 -0600 Subject: [PATCH 28/40] Update migrate.sh --- usr/local/share/bastille/migrate.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 7f1138cf..0beec1cb 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -159,14 +159,14 @@ migrate_jail() { # Verify jail does not exist remotely if echo ${_remote_jail_list} | grep -Eoq "^${TARGET}$"; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Jail already exists on remote system: ${TARGET}" fi # Verify ZFS on both systems if checkyesno bastille_zfs_enable; then if ! checkyesno _remote_bastille_zfs_enable; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_notify "[ERROR]: ZFS is enabled locally, but not remotely." error_exit "Enable ZFS remotely to continue." else @@ -178,19 +178,19 @@ migrate_jail() { # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to send jail to remote system." fi # Send jail export if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to send jail to remote system." fi fi else if checkyesno _remote_bastille_zfs_enable; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_notify "[ERROR]: ZFS is enabled remotely, but not locally." error_exit "Enable ZFS locally to continue." else @@ -202,13 +202,13 @@ migrate_jail() { # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to migrate jail to remote system." fi # Send jail export if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to migrate jail to remote system." fi fi @@ -216,7 +216,7 @@ migrate_jail() { # Import the jail remotely if ! ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to import jail on remote system." fi @@ -226,7 +226,7 @@ migrate_jail() { fi # Remove archives - migrate_cleanup "${_jail}" + migrate_cleanup "${_jail}" "${_user}" "${_host}" # Start new jail if AUTO=1 if [ "${AUTO}" -eq 1 ]; then From a60f76b3b664f26ccea12f8a8702bb958317c62e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 15:18:43 -0600 Subject: [PATCH 29/40] import: Fix TARGET_TRIM var --- usr/local/share/bastille/import.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index 3affc7da..b0824379 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -715,9 +715,8 @@ jail_import() { # Check for user specified file location if echo "${TARGET}" | grep -q '\/'; then - GETDIR="${TARGET}" - TARGET=$(echo ${TARGET} | awk -F '\/' '{print $NF}') - bastille_backupsdir=$(echo ${GETDIR} | sed "s/${TARGET}//") + TARGET="$(basename ${TARGET})" + bastille_backupsdir="$(dirname ${TARGET})" fi # Check if backups directory/dataset exist @@ -746,11 +745,11 @@ else fi # Check if a running jail matches name or already exist -if check_target_exists "${TARGET}"; then - error_exit "[ERROR]: Jail: ${TARGET} already exists." +if check_target_exists "${TARGET_TRIM}"; then + error_exit "[ERROR]: Jail: ${TARGET_TRIM} already exists." fi if [ -n "${TARGET}" ]; then - info "\nAttempting to import jail: ${TARGET}..." + info "\nAttempting to import jail: ${TARGET_TRIM}..." jail_import fi From ac1e92258b0883984350b11bc7b69e45affe7780 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 15:21:45 -0600 Subject: [PATCH 30/40] migrate: Ensure same name for checksum --- usr/local/share/bastille/migrate.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 0beec1cb..ec73653f 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -158,9 +158,9 @@ migrate_jail() { local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" # Verify jail does not exist remotely - if echo ${_remote_jail_list} | grep -Eoq "^${TARGET}$"; then + if echo ${_remote_jail_list} | grep -Eoq "^${_jail}$"; then migrate_cleanup "${_jail}" "${_user}" "${_host}" - error_exit "[ERROR]: Jail already exists on remote system: ${TARGET}" + error_exit "[ERROR]: Jail already exists on remote system: ${_jail}" fi # Verify ZFS on both systems @@ -174,7 +174,7 @@ migrate_jail() { info "\nAttempting to migrate jail to remote system..." local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.xz$" | head -n1)" - local _file_sha256="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.sha256$" | head -n1)" + local _file_sha256="$(echo ${_file} | sed 's/\.*/.sha256/')" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then @@ -198,7 +198,7 @@ migrate_jail() { info "\nAttempting to migrate jail to remote system..." local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.txz$" | head -n1)" - local _file_sha256="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.sha256$" | head -n1)" + local _file_sha256="$(echo ${_file} | sed 's/\.*/.sha256/')" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then From 659020dd8950b76a1eeb46f8d0e0fafe3ecd974a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 15:24:54 -0600 Subject: [PATCH 31/40] migrate: Dont quote rm command --- usr/local/share/bastille/migrate.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index ec73653f..e7cbbb61 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -122,8 +122,8 @@ migrate_cleanup() { local _host="${3}" # Remove archive files from local and remote system - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" - rm -f "${bastille_migratedir}/${_jail}_*.*" + ssh ${_user}@${_host} sudo rm -f ${_remote_bastille_migratedir}/${_jail}_*.* + rm -f ${bastille_migratedir}/${_jail}_*.* } migrate_create_export() { From 1bb7fe1db4d35de9be55dfe53b47440e9c09a523 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 15:27:34 -0600 Subject: [PATCH 32/40] Update migrate.sh --- usr/local/share/bastille/migrate.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index e7cbbb61..276e197d 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -122,7 +122,7 @@ migrate_cleanup() { local _host="${3}" # Remove archive files from local and remote system - ssh ${_user}@${_host} sudo rm -f ${_remote_bastille_migratedir}/${_jail}_*.* + ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" rm -f ${bastille_migratedir}/${_jail}_*.* } @@ -174,7 +174,7 @@ migrate_jail() { info "\nAttempting to migrate jail to remote system..." local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.xz$" | head -n1)" - local _file_sha256="$(echo ${_file} | sed 's/\.*/.sha256/')" + local _file_sha256="$(echo ${_file} | sed 's/\..*/.sha256/')" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then @@ -198,7 +198,7 @@ migrate_jail() { info "\nAttempting to migrate jail to remote system..." local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.txz$" | head -n1)" - local _file_sha256="$(echo ${_file} | sed 's/\.*/.sha256/')" + local _file_sha256="$(echo ${_file} | sed 's/\..*/.sha256/')" # Send sha256 if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then From 510807657bff07128659f1244f6f2bb06b70ff07 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 15:36:59 -0600 Subject: [PATCH 33/40] Update import.sh --- usr/local/share/bastille/import.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index b0824379..9d004840 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -715,8 +715,9 @@ jail_import() { # Check for user specified file location if echo "${TARGET}" | grep -q '\/'; then + GETDIR="${TARGET}" TARGET="$(basename ${TARGET})" - bastille_backupsdir="$(dirname ${TARGET})" + bastille_backupsdir="$(dirname ${GETDIR})" fi # Check if backups directory/dataset exist @@ -739,7 +740,7 @@ else error_exit "[ERROR]: Archive '${TARGET}' not found." else # Assume user will import from standard input - TARGET_TRIM=${TARGET} + TARGET_TRIM="${TARGET}" USER_IMPORT="1" fi fi From 72038fe658e3c6d76f51713ebd1e1cc8df4cc7aa Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 15:44:28 -0600 Subject: [PATCH 34/40] Update migrate.sh --- usr/local/share/bastille/migrate.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 276e197d..435ca3a8 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -158,19 +158,19 @@ migrate_jail() { local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" # Verify jail does not exist remotely - if echo ${_remote_jail_list} | grep -Eoq "^${_jail}$"; then - migrate_cleanup "${_jail}" "${_user}" "${_host}" + if echo "${_remote_jail_list}" | grep -Eoqw "${_jail}"; then error_exit "[ERROR]: Jail already exists on remote system: ${_jail}" fi # Verify ZFS on both systems if checkyesno bastille_zfs_enable; then if ! checkyesno _remote_bastille_zfs_enable; then - migrate_cleanup "${_jail}" "${_user}" "${_host}" error_notify "[ERROR]: ZFS is enabled locally, but not remotely." error_exit "Enable ZFS remotely to continue." else + migrate_create_export "${_jail}" "${_user}" "${_host}" + info "\nAttempting to migrate jail to remote system..." local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.xz$" | head -n1)" @@ -190,13 +190,14 @@ migrate_jail() { fi else if checkyesno _remote_bastille_zfs_enable; then - migrate_cleanup "${_jail}" "${_user}" "${_host}" error_notify "[ERROR]: ZFS is enabled remotely, but not locally." error_exit "Enable ZFS locally to continue." else info "\nAttempting to migrate jail to remote system..." + migrate_create_export "${_jail}" "${_user}" "${_host}" + local _file="$(find "${bastille_migratedir}" -maxdepth 1 -type f | grep -Eo "${_jail}_.*\.txz$" | head -n1)" local _file_sha256="$(echo ${_file} | sed 's/\..*/.sha256/')" @@ -251,8 +252,6 @@ for _jail in ${JAILS}; do fi info "\nAttempting to migrate '${_jail}' to '${HOST}'..." - - migrate_create_export "${_jail}" "${USER}" "${HOST}" migrate_jail "${_jail}" "${USER}" "${HOST}" From da2444f1505bc46f27dbc44649dd71943bc98c94 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 18:13:18 -0600 Subject: [PATCH 35/40] migrate: Support password with -p option --- usr/local/share/bastille/migrate.sh | 60 +++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 435ca3a8..33ab5380 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -38,9 +38,10 @@ usage() { Options: - -a | --auto Auto mode. Start/stop jail(s) if required. - -d | --destroy Destroy local jail after migration. - -x | --debug Enable debug mode. + -a | --auto Auto mode. Start/stop jail(s) if required. + -d | --destroy Destroy local jail after migration. + -p | --password Use password based authentication. + -x | --debug Enable debug mode. EOF exit 1 @@ -49,6 +50,7 @@ EOF # Handle options. AUTO=0 OPT_DESTROY=0 +OPT_PASSWORD=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) @@ -62,6 +64,10 @@ while [ "$#" -gt 0 ]; do OPT_DESTROY=1 shift ;; + -p|--password) + OPT_PASSWORD=1 + shift + ;; -x|--debug) enable_debug shift @@ -71,6 +77,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in a) AUTO=1 ;; d) OPT_DESTROY=1 ;; + p) OPT_PASSWORD=1 ;; x) enable_debug ;; *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac @@ -107,9 +114,10 @@ validate_host_status() { fi # Host SSH check - if ! ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then + if ! $_sshpass_cmd ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then error_notify "[ERROR]: Could not establish ssh connection to host." - error_exit "Please make sure user '${_user}' has password-less access." + error_notify "Please make sure user '${_user}' has password-less access" + error_exit "or use '-p|--password' for password based authentication." fi echo "Host check successful." @@ -122,7 +130,7 @@ migrate_cleanup() { local _host="${3}" # Remove archive files from local and remote system - ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" + $_sshpass_cmd ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" rm -f ${bastille_migratedir}/${_jail}_*.* } @@ -136,7 +144,7 @@ migrate_create_export() { # Ensure new migrate directory is created bastille setup -f - ssh ${_user}@${_host} sudo bastille setup -f + $_sshpass_cmd ssh ${_user}@${_host} sudo bastille setup -f # --xz for ZFS, otherwise --txz if checkyesno bastille_zfs_enable; then @@ -152,10 +160,10 @@ migrate_jail() { local _user="${2}" local _host="${3}" - local _remote_bastille_zfs_enable="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" - local _remote_bastille_jailsdir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" - local _remote_bastille_migratedir="$(ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" - local _remote_jail_list="$(ssh ${_user}@${_host} bastille list jails)" + local _remote_bastille_zfs_enable="$($_sshpass_cmd ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" + local _remote_bastille_jailsdir="$($_sshpass_cmd ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" + local _remote_bastille_migratedir="$($_sshpass_cmd ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" + local _remote_jail_list="$($_sshpass_cmd ssh ${_user}@${_host} bastille list jails)" # Verify jail does not exist remotely if echo "${_remote_jail_list}" | grep -Eoqw "${_jail}"; then @@ -177,13 +185,13 @@ migrate_jail() { local _file_sha256="$(echo ${_file} | sed 's/\..*/.sha256/')" # Send sha256 - if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to send jail to remote system." fi # Send jail export - if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to send jail to remote system." fi @@ -202,13 +210,13 @@ migrate_jail() { local _file_sha256="$(echo ${_file} | sed 's/\..*/.sha256/')" # Send sha256 - if ! scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to migrate jail to remote system." fi # Send jail export - if ! scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to migrate jail to remote system." fi @@ -216,7 +224,7 @@ migrate_jail() { fi # Import the jail remotely - if ! ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then + if ! $_sshpass_cmd ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to import jail on remote system." fi @@ -231,10 +239,28 @@ migrate_jail() { # Start new jail if AUTO=1 if [ "${AUTO}" -eq 1 ]; then - ssh ${_user}@${_host} sudo bastille start "${_jail}" + $_sshpass_cmd ssh ${_user}@${_host} sudo bastille start "${_jail}" fi } +# Determine if user wants to authenticate via password +if [ "${OPT_PASSWORD}" -eq 1 ]; then + if ! which sshpass >/dev/null 2>/dev/null; then + error_exit "[ERROR]: Please install 'sshpass' to use password based authentication." + else + warn "[WARNING]: Password based authentication can be insecure." + printf "Please enter your password: " + # We disable terminal output for the password + stty -echo + read _password + stty echo + printf "\n" + _sshpass_cmd="sshpass -p ${_password}" + fi +else + _sshpass_cmd= +fi + # Validate host uptime validate_host_status "${USER}" "${HOST}" From e27ea1a806315c21e4a6416e729b9ba869a8bc2a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 18:14:13 -0600 Subject: [PATCH 36/40] docs: Update migrate -p --- docs/chapters/subcommands/migrate.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/chapters/subcommands/migrate.rst b/docs/chapters/subcommands/migrate.rst index e3b12d2c..36365c18 100644 --- a/docs/chapters/subcommands/migrate.rst +++ b/docs/chapters/subcommands/migrate.rst @@ -13,6 +13,7 @@ This sub-command supports multiple targets. Options: - -a | --auto Auto mode. Start/stop jail(s) if required. - -d | --destroy Destroy local jail after migration. - -x | --debug Enable debug mode. + -a | --auto Auto mode. Start/stop jail(s) if required. + -d | --destroy Destroy local jail after migration. + -p | --password Use password based authentication. + -x | --debug Enable debug mode. From ef0ba9946227f7583c69d08c83e8e6a19bab0060 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 19:01:28 -0600 Subject: [PATCH 37/40] migrate: Different message for ssh with password fail --- usr/local/share/bastille/migrate.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 33ab5380..84b932db 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -114,7 +114,13 @@ validate_host_status() { fi # Host SSH check - if ! $_sshpass_cmd ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then + if [ "${OPT_PASSWORD}" -eq 1 ]; then + if ! $_sshpass_cmd ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password ${_user}@${_host} exit >/dev/null 2>/dev/null; then + error_notify "[ERROR]: Could not establish ssh connection to host." + error_notify "Please make sure the remote host supports password based authentication" + error_exit "and you are using the correct password for user: '${_user}'" + fi + elif ! $_sshpass_cmd ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then error_notify "[ERROR]: Could not establish ssh connection to host." error_notify "Please make sure user '${_user}' has password-less access" error_exit "or use '-p|--password' for password based authentication." From 171240a4f79236fa98600855e6777c035597b6b8 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 21:45:43 -0600 Subject: [PATCH 38/40] migrate: Fix key location --- usr/local/share/bastille/migrate.sh | 39 ++++++++++++++++++----------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 84b932db..6640e1f6 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -115,12 +115,12 @@ validate_host_status() { # Host SSH check if [ "${OPT_PASSWORD}" -eq 1 ]; then - if ! $_sshpass_cmd ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password ${_user}@${_host} exit >/dev/null 2>/dev/null; then + if ! ${_sshpass_cmd} ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password ${_user}@${_host} exit >/dev/null 2>/dev/null; then error_notify "[ERROR]: Could not establish ssh connection to host." error_notify "Please make sure the remote host supports password based authentication" error_exit "and you are using the correct password for user: '${_user}'" fi - elif ! $_sshpass_cmd ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then + elif ! ${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} exit >/dev/null 2>/dev/null; then error_notify "[ERROR]: Could not establish ssh connection to host." error_notify "Please make sure user '${_user}' has password-less access" error_exit "or use '-p|--password' for password based authentication." @@ -136,7 +136,7 @@ migrate_cleanup() { local _host="${3}" # Remove archive files from local and remote system - $_sshpass_cmd ssh ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" + ${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} sudo rm -f "${_remote_bastille_migratedir}/${_jail}_*.*" rm -f ${bastille_migratedir}/${_jail}_*.* } @@ -150,7 +150,7 @@ migrate_create_export() { # Ensure new migrate directory is created bastille setup -f - $_sshpass_cmd ssh ${_user}@${_host} sudo bastille setup -f + ${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} sudo bastille setup -f # --xz for ZFS, otherwise --txz if checkyesno bastille_zfs_enable; then @@ -166,10 +166,10 @@ migrate_jail() { local _user="${2}" local _host="${3}" - local _remote_bastille_zfs_enable="$($_sshpass_cmd ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" - local _remote_bastille_jailsdir="$($_sshpass_cmd ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" - local _remote_bastille_migratedir="$($_sshpass_cmd ssh ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" - local _remote_jail_list="$($_sshpass_cmd ssh ${_user}@${_host} bastille list jails)" + local _remote_bastille_zfs_enable="$(${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_zfs_enable)" + local _remote_bastille_jailsdir="$(${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_jailsdir)" + local _remote_bastille_migratedir="$(${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} sysrc -f /usr/local/etc/bastille/bastille.conf -n bastille_migratedir)" + local _remote_jail_list="$(${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} bastille list jails)" # Verify jail does not exist remotely if echo "${_remote_jail_list}" | grep -Eoqw "${_jail}"; then @@ -191,13 +191,13 @@ migrate_jail() { local _file_sha256="$(echo ${_file} | sed 's/\..*/.sha256/')" # Send sha256 - if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! ${_sshpass_cmd} scp ${_opt_ssh_key} ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to send jail to remote system." fi # Send jail export - if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! ${_sshpass_cmd} scp ${_opt_ssh_key} ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to send jail to remote system." fi @@ -216,13 +216,13 @@ migrate_jail() { local _file_sha256="$(echo ${_file} | sed 's/\..*/.sha256/')" # Send sha256 - if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! ${_sshpass_cmd} scp ${_opt_ssh_key} ${bastille_migratedir}/${_file_sha256} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to migrate jail to remote system." fi # Send jail export - if ! $_sshpass_cmd scp ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then + if ! ${_sshpass_cmd} scp ${_opt_ssh_key} ${bastille_migratedir}/${_file} ${_user}@${_host}:${_remote_bastille_migratedir}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to migrate jail to remote system." fi @@ -230,7 +230,7 @@ migrate_jail() { fi # Import the jail remotely - if ! $_sshpass_cmd ssh ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then + if ! ${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} sudo bastille import ${_remote_bastille_migratedir}/${_file}; then migrate_cleanup "${_jail}" "${_user}" "${_host}" error_exit "[ERROR]: Failed to import jail on remote system." fi @@ -245,7 +245,7 @@ migrate_jail() { # Start new jail if AUTO=1 if [ "${AUTO}" -eq 1 ]; then - $_sshpass_cmd ssh ${_user}@${_host} sudo bastille start "${_jail}" + ${_sshpass_cmd} ssh ${_opt_ssh_key} ${_user}@${_host} sudo bastille start "${_jail}" fi } @@ -267,6 +267,17 @@ else _sshpass_cmd= fi +# Get user we want to migrate as +# We need this to pass the ssh keys properly +if [ "${OPT_PASSWORD}" -eq 1 ]; then + _opt_ssh_key= +else + _migrate_user="$(sudo -u ${USER} whoami)" + _migrate_user_home="$(getent passwd migrate | cut -d: -f6)" + _migrate_user_ssh_key="${_migrate_user_home}/.ssh/id_rsa" + _opt_ssh_key="-i ${_migrate_user_ssh_key}" +fi + # Validate host uptime validate_host_status "${USER}" "${HOST}" From a9121f357d7c220960601de707f589b1b19ce50e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 6 May 2025 22:03:24 -0600 Subject: [PATCH 39/40] docs: Update migration for password use --- docs/chapters/migration.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/chapters/migration.rst b/docs/chapters/migration.rst index ac1d6ae4..d605f8d8 100644 --- a/docs/chapters/migration.rst +++ b/docs/chapters/migration.rst @@ -14,12 +14,18 @@ There are a couple of things that need to be in place before running the ``migra First, you must have bastille configured both locally and remotely to use the same filesystem configuration. ZFS on both, or UFS on both. -Second, we need a user on the remote system that has key-based authentication set up. Bastille -does not support password-based authentication. This also implies that SSH is working on the -remote system. This user also needs ``sudo`` permissions on the remote system. +Second, you must create a user on the remote system that will be used to migrate the jail. The user +must be able to log in via SSH using either key-based authentication, or password based authentication. +The user also needs ``sudo`` permissions on the remote system. This user should then be given as the +``USER`` arg in the ``migrate`` command. -Third, if updating from a previous version, please make sure to ``diff`` your ``bastille.conf`` -file, as the ``migrate`` sub-command adds a new variable called ``bastille_migratedir``. +If you are using key-based auth, the keys should be stored in the default location at ``$HOME/.ssh/id_rsa``, +where ``$HOME`` is the users home directory. This is the default location for ssh keys, and where Bastille +will try to load them from. + +If you want to use password based authentication, simply run ``bastille migrate -p TARGET USER HOST``. This +will prompt you to enter the password for the remote system, which Bastille will then use during the migration +process. Migration ^^^^^^^^^ From 482883ec979023c6e7bfaff41e20fffa9dbb9824 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 7 May 2025 08:40:53 -0600 Subject: [PATCH 40/40] migrate: Update password auth --- usr/local/share/bastille/migrate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/migrate.sh b/usr/local/share/bastille/migrate.sh index 6640e1f6..9996d7fb 100644 --- a/usr/local/share/bastille/migrate.sh +++ b/usr/local/share/bastille/migrate.sh @@ -115,7 +115,7 @@ validate_host_status() { # Host SSH check if [ "${OPT_PASSWORD}" -eq 1 ]; then - if ! ${_sshpass_cmd} ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password ${_user}@${_host} exit >/dev/null 2>/dev/null; then + if ! ${_sshpass_cmd} ssh ${_user}@${_host} exit >/dev/null 2>/dev/null; then error_notify "[ERROR]: Could not establish ssh connection to host." error_notify "Please make sure the remote host supports password based authentication" error_exit "and you are using the correct password for user: '${_user}'"