Update jlmkr.sh
This commit is contained in:
parent
8e5140ec21
commit
65741bec66
199
jlmkr.sh
199
jlmkr.sh
|
@ -7,18 +7,19 @@ ABSOLUTE_SCRIPT_PATH="$(realpath "${BASH_SOURCE[0]}")"
|
|||
SCRIPT_NAME=$(basename "${ABSOLUTE_SCRIPT_PATH}")
|
||||
SCRIPT_DIR_PATH="$(dirname "${ABSOLUTE_SCRIPT_PATH}")"
|
||||
|
||||
CREATE_DONE=
|
||||
JAILS_DIR_PATH='jails'
|
||||
JAIL_ROOTFS_NAME='rootfs'
|
||||
JAIL_PATH=
|
||||
|
||||
USAGE="WARNING: EXPERIMENTAL AND WORK IN PROGRESS, USE ONLY FOR TESTING!
|
||||
|
||||
TODO: add version string
|
||||
Usage: ./${SCRIPT_NAME} COMMAND [ARG...]
|
||||
|
||||
TODO: complete writing usage
|
||||
"
|
||||
|
||||
JAILS_DIR_PATH='jails'
|
||||
JAIL_ROOTFS_NAME='rootfs'
|
||||
JAIL_PATH=
|
||||
JAIL_CONFIG_NAME='config'
|
||||
JAIL_START_SCRIPT_NAME='start.sh'
|
||||
|
||||
fail() {
|
||||
echo -e "$1" >&2 && exit 1
|
||||
}
|
||||
|
@ -38,23 +39,31 @@ trap 'err $LINENO' ERR
|
|||
# START RUN FUNCTIONALITY
|
||||
#########################
|
||||
|
||||
run_jail() (
|
||||
# Create a sub-shell to source the conf file
|
||||
start_jail() {
|
||||
local jail_config_path jail_start_script_path docker_compatible gpu_passthrough key value
|
||||
|
||||
jail_config_path="${1}/${JAIL_CONFIG_NAME}"
|
||||
jail_start_script_path="${1}/${JAIL_START_SCRIPT_NAME}"
|
||||
|
||||
! [[ -f "${jail_start_script_path}" ]] && fail "ERROR: Couldn't find: ${jail_start_script_path}"
|
||||
! [[ -f "${jail_config_path}" ]] && fail "ERROR: Couldn't find: ${jail_config_path}"
|
||||
|
||||
echo 'Load the config'
|
||||
|
||||
# TODO: also load the additional (user) args for nspawn from this file!
|
||||
while IFS="=" read -r key value || [ -n "$key" ]; do
|
||||
case "${key}" in
|
||||
"DOCKER_COMPATIBLE") docker_compatible="$value" ;;
|
||||
"GPU_PASSTHROUGH") gpu_passthrough="$value" ;;
|
||||
esac
|
||||
done <"${jail_config_path}"
|
||||
|
||||
echo 'Config loaded'
|
||||
|
||||
# Define as global vars: they are also global vars in the sourced start script
|
||||
DOCKER_COMPATIBLE=
|
||||
GPU_PASSTHROUGH=
|
||||
SYSTEMD_RUN_ADDITIONAL_ARGS=()
|
||||
SYSTEMD_NSPAWN_ADDITIONAL_ARGS=()
|
||||
|
||||
echo 'Load the config'
|
||||
# shellcheck disable=SC1090
|
||||
. "${1}"
|
||||
echo 'Config loaded'
|
||||
|
||||
set -eEuo pipefail
|
||||
if [[ "$(type -t start)" == 'function' ]]; then
|
||||
if [[ "${DOCKER_COMPATIBLE}" -eq 1 ]]; then
|
||||
if [[ "${docker_compatible}" -eq 1 ]]; then
|
||||
# Enable ip forwarding on the host (docker needs it)
|
||||
echo 1 >/proc/sys/net/ipv4/ip_forward
|
||||
# To properly run docker inside the jail, we need to lift restrictions
|
||||
|
@ -65,7 +74,7 @@ run_jail() (
|
|||
SYSTEMD_NSPAWN_ADDITIONAL_ARGS+=(--capability=all --system-call-filter='add_key keyctl bpf')
|
||||
fi
|
||||
|
||||
if [[ "${GPU_PASSTHROUGH}" -eq 1 ]]; then
|
||||
if [[ "${gpu_passthrough}" -eq 1 ]]; then
|
||||
SYSTEMD_NSPAWN_ADDITIONAL_ARGS+=(--property=DeviceAllow='char-drm rw')
|
||||
|
||||
# Detect intel GPU device and if present add bind flag
|
||||
|
@ -74,25 +83,22 @@ run_jail() (
|
|||
# TODO: add bind mount flags in case of nvidia GPU passthrough
|
||||
fi
|
||||
|
||||
# Pass the two arrays to the start script
|
||||
# https://stackoverflow.com/a/43687593
|
||||
echo "Starting jail..."
|
||||
start
|
||||
else
|
||||
echo "Can't call the start function since start.sh didn't contain one..."
|
||||
fi
|
||||
)
|
||||
|
||||
"./${jail_start_script_path}" \
|
||||
"${#SYSTEMD_RUN_ADDITIONAL_ARGS[@]}" "${SYSTEMD_RUN_ADDITIONAL_ARGS[@]}" \
|
||||
"${#SYSTEMD_NSPAWN_ADDITIONAL_ARGS[@]}" "${SYSTEMD_NSPAWN_ADDITIONAL_ARGS[@]}"
|
||||
}
|
||||
|
||||
############################
|
||||
# START CREATE FUNCTIONALITY
|
||||
############################
|
||||
|
||||
cleanup() {
|
||||
# If the script didn't complete (not CREATE_DONE) then
|
||||
# remove the JAIL_PATH (if set and a directory)
|
||||
if [[ "${CREATE_DONE}" -ne 1 && -n "${JAIL_PATH}" && -d "${JAIL_PATH}" &&
|
||||
"${JAIL_PATH}" != "${JAILS_DIR_PATH}" && "${JAIL_PATH}" != "/" ]]; then
|
||||
echo -e "\n\nCleaning up: ${JAIL_PATH}\n"
|
||||
rm -rf "${JAIL_PATH}"
|
||||
fi
|
||||
# Remove the JAIL_PATH (if set, a directory and not the root directory)
|
||||
[[ -d "${JAIL_PATH}" ]] && echo -e "\n\nCleaning up: ${JAIL_PATH}\n" && rm -rf "${JAIL_PATH}"
|
||||
}
|
||||
|
||||
stat_chmod() {
|
||||
|
@ -112,28 +118,19 @@ template_start_script() {
|
|||
echo "$((LINENO + 1))" && return
|
||||
# TEMPLATE START
|
||||
#!/bin/bash
|
||||
|
||||
# YOU CAN MANUALLY EDIT THE SETTINGS BELOW
|
||||
|
||||
DOCKER_COMPATIBLE=PLACEHOLDER_DOCKER_COMPATIBLE
|
||||
GPU_PASSTHROUGH=PLACEHOLDER_GPU_PASSTHROUGH
|
||||
|
||||
# DO NOT EDIT THE SCRIPT FROM HERE ON, UNLESS YOU KNOW WHAT YOU ARE DOING
|
||||
# THIS FILE WILL BE SOURCED IN A BASH SUB-SHELL BY PLACEHOLDER_SCRIPT_NAME
|
||||
# THE START FUNCTION WILL BE CALLED TO START THE JAIL
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# If this script is called from PLACEHOLDER_SCRIPT_NAME
|
||||
# and DOCKER_COMPATIBLE or GPU_PASSTHROUGH is enabled
|
||||
# then these arrays will be filled with additional args
|
||||
SYSTEMD_RUN_ADDITIONAL_ARGS=("${@:2:$1}") && shift "$(($1 + 1))"
|
||||
SYSTEMD_NSPAWN_ADDITIONAL_ARGS=("${@:2:$1}") && shift "$(($1 + 1))"
|
||||
|
||||
# Move into the directory where this script is stored (commands are relative to this directory)
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" || exit
|
||||
# Get the name of the jail from the directory name
|
||||
JAIL_NAME="$(basename "$(pwd)")"
|
||||
|
||||
# You may add additional args to the two arrays below
|
||||
# These args will be passed to systemd-run and systemd-nspawn in the start function
|
||||
SYSTEMD_RUN_ADDITIONAL_ARGS=()
|
||||
SYSTEMD_NSPAWN_ADDITIONAL_ARGS=(PLACEHOLDER_SYSTEMD_NSPAWN_ADDITIONAL_ARGS)
|
||||
|
||||
start() {
|
||||
# Use mostly default settings for systemd-nspawn but with systemd-run instead of a service file
|
||||
# https://github.com/systemd/systemd/blob/main/units/systemd-nspawn%40.service.in
|
||||
# TODO: also compare settings for docker: https://github.com/docker/engine/blob/master/contrib/init/systemd/docker.service
|
||||
|
@ -145,18 +142,8 @@ template_start_script() {
|
|||
-- \
|
||||
systemd-nspawn --keep-unit --quiet --boot \
|
||||
--machine="${JAIL_NAME}" --directory='./PLACEHOLDER_ROOTFS_NAME' \
|
||||
PLACEHOLDER_SYSTEMD_NSPAWN_USER_ARGS \
|
||||
"${SYSTEMD_NSPAWN_ADDITIONAL_ARGS[@]}"
|
||||
}
|
||||
|
||||
# Call the start function if this script is executed directly (not sourced)
|
||||
# https://stackoverflow.com/a/28776166
|
||||
(return 0 2>/dev/null) || {
|
||||
echo 'This script was called directly, not sourced.'
|
||||
echo 'The jail will now start...'
|
||||
echo 'But the DOCKER_COMPATIBLE and GPU_PASSTHROUGH settings are not considered.'
|
||||
echo "For this to work, start the jail from PLACEHOLDER_SCRIPT_NAME."
|
||||
start
|
||||
}
|
||||
# TEMPLATE END
|
||||
}
|
||||
|
||||
|
@ -194,28 +181,11 @@ process_template() {
|
|||
done < <(tail -n "+${1}" "${ABSOLUTE_SCRIPT_PATH}")
|
||||
}
|
||||
|
||||
# Helper function which escapes and concatenates a string of arguments
|
||||
escape() {
|
||||
local result="" spacer=""
|
||||
# Process each argument (newline separated thanks to: xargs -n 1)
|
||||
while IFS=$'\n' read -r arg; do
|
||||
arg="$(declare -p arg)"
|
||||
# Get everything after the first = character
|
||||
arg="${arg#*=}"
|
||||
# Append to string with leading space
|
||||
result+="${spacer}${arg}"
|
||||
# From now on, use a space in between elements
|
||||
spacer=" "
|
||||
done < <(printf "%s" "${1}" | xargs -n 1)
|
||||
|
||||
printf "%s" "${result}"
|
||||
}
|
||||
|
||||
create_jail() {
|
||||
|
||||
# TODO: show disclaimer
|
||||
local reply arch distro release lxc_dir_path lxc_cache_path lxc_download_script_path
|
||||
local jail_config_path jail_start_script_name jail_start_script_path docker_compatible gpu_passthrough
|
||||
local jail_name systemd_nspawn_additional_args
|
||||
local jail_config_path jail_start_script_path docker_compatible gpu_passthrough
|
||||
local jail_name systemd_nspawn_user_args
|
||||
|
||||
arch="$(dpkg --print-architecture)"
|
||||
lxc_dir_path='.lxc'
|
||||
|
@ -308,7 +278,8 @@ create_jail() {
|
|||
fi
|
||||
done
|
||||
|
||||
# Cleanup on exit, but only once the JAIL_PATH name is known
|
||||
# Cleanup on exit, but only once the JAIL_PATH is final
|
||||
# Otherwise we may cleanup the wrong directory
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "${SCRIPT_NAME} will not install docker for you."
|
||||
|
@ -334,25 +305,18 @@ create_jail() {
|
|||
echo "With incorrect flags the jail may not start."
|
||||
echo "It's possible to correct/add/remove flags post-install."
|
||||
echo
|
||||
read -e -r -p "Additional flags: " SYSTEMD_NSPAWN_USER_ARGS_STRING && echo
|
||||
read -e -r -p "Additional flags: " systemd_nspawn_user_args && echo
|
||||
# Backslashes and colons need to be escaped for systemd-nspawn by the user:
|
||||
# e.g. to bind mount a file called:
|
||||
# weird chars :?\"
|
||||
# the corresponding command would be:
|
||||
# --bind-ro='/mnt/data/weird chars \:?\\"'
|
||||
|
||||
# Process the flags (read as a string) as actual command line arguments with xargs and
|
||||
# pass these args to bash which then executes the escape function to convert the args into a properly escaped string
|
||||
# which can be evaluated as an array declaration in the start.sh bash script
|
||||
# https://superuser.com/a/1529316/1268213 and https://superuser.com/a/1627765
|
||||
systemd_nspawn_additional_args="$(escape "${SYSTEMD_NSPAWN_USER_ARGS_STRING}")"
|
||||
echo "systemd_nspawn_additional_args=${systemd_nspawn_additional_args}"
|
||||
|
||||
# Create directory for rootfs
|
||||
JAIL_ROOTFS_PATH="${JAIL_PATH}/${JAIL_ROOTFS_NAME}"
|
||||
mkdir -p "${JAIL_ROOTFS_PATH}"
|
||||
|
||||
jail_config_path="${JAIL_PATH}/config"
|
||||
jail_config_path="${JAIL_PATH}/${JAIL_CONFIG_NAME}"
|
||||
# LXC download script needs to write to this file during install
|
||||
# but we don't need it so we will remove it later
|
||||
touch "${jail_config_path}"
|
||||
|
@ -384,8 +348,6 @@ create_jail() {
|
|||
[[ "${reply}" =~ ^([Yy]|)$ ]] && exit
|
||||
fi
|
||||
|
||||
# Remove file we no longer need
|
||||
rm -f "${jail_config_path}"
|
||||
# Config which systemd handles for us
|
||||
rm -f "${JAIL_ROOTFS_PATH}/etc/machine-id"
|
||||
rm -f "${JAIL_ROOTFS_PATH}/etc/resolv.conf"
|
||||
|
@ -393,22 +355,29 @@ create_jail() {
|
|||
# https://github.com/systemd/systemd/issues/852
|
||||
printf 'pts/%d\n' $(seq 0 10) >"${JAIL_ROOTFS_PATH}/etc/securetty"
|
||||
|
||||
jail_start_script_name='start.sh'
|
||||
jail_start_script_path="${JAIL_PATH}/${jail_start_script_name}"
|
||||
jail_start_script_path="${JAIL_PATH}/${JAIL_START_SCRIPT_NAME}"
|
||||
|
||||
process_template "$(template_start_script)" PLACEHOLDER_DOCKER_COMPATIBLE "${docker_compatible}" PLACEHOLDER_GPU_PASSTHROUGH "${gpu_passthrough}" \
|
||||
PLACEHOLDER_ROOTFS_NAME "${JAIL_ROOTFS_NAME}" PLACEHOLDER_SYSTEMD_NSPAWN_ADDITIONAL_ARGS "${systemd_nspawn_additional_args}" \
|
||||
cat <<-EOF >"${jail_config_path}"
|
||||
DOCKER_COMPATIBLE=${docker_compatible}
|
||||
GPU_PASSTHROUGH=${gpu_passthrough}
|
||||
EOF
|
||||
|
||||
chmod 700 "${jail_config_path}"
|
||||
|
||||
process_template "$(template_start_script)" \
|
||||
PLACEHOLDER_ROOTFS_NAME "${JAIL_ROOTFS_NAME}" PLACEHOLDER_SYSTEMD_NSPAWN_USER_ARGS "${systemd_nspawn_user_args}" \
|
||||
PLACEHOLDER_SCRIPT_NAME "${SCRIPT_NAME}" >"${jail_start_script_path}"
|
||||
|
||||
chmod 700 "${jail_start_script_path}"
|
||||
|
||||
# Remove the cleanup trap on exit
|
||||
trap - EXIT
|
||||
echo "Done creating the jail."
|
||||
CREATE_DONE=1
|
||||
echo
|
||||
read -p "Start the jail now? [Y/n] " -n 1 -r reply && echo
|
||||
# Enter accepts default (yes)
|
||||
if [[ "${reply}" =~ ^([Yy]|)$ ]]; then
|
||||
run_jail "${jail_start_script_path}"
|
||||
start_jail "${JAIL_PATH}"
|
||||
else
|
||||
echo 'Skipped starting jail.'
|
||||
fi
|
||||
|
@ -418,16 +387,6 @@ create_jail() {
|
|||
# END CREATE FUNCTIONALITY
|
||||
##########################
|
||||
|
||||
read -p "Create a new jail? [Y/n] " -n 1 -r reply && echo
|
||||
# Enter accepts default (yes)
|
||||
# https://stackoverflow.com/a/1885534
|
||||
if [[ "${reply}" =~ ^([Yy]|)$ ]]; then
|
||||
create_jail
|
||||
else
|
||||
echo "${USAGE}"
|
||||
exit
|
||||
fi
|
||||
|
||||
# TODO document
|
||||
# machinectl shell
|
||||
# If that doesn't work try
|
||||
|
@ -440,3 +399,29 @@ fi
|
|||
# machinectl login
|
||||
# TODO: recommend ssh ;)
|
||||
# TODO: create a jlmkr shell command to try the above in case machinectl shell doesn't work
|
||||
|
||||
case "${1-""}" in
|
||||
|
||||
'')
|
||||
read -p "Create a new jail? [Y/n] " -n 1 -r reply && echo
|
||||
# Enter accepts default (yes)
|
||||
# https://stackoverflow.com/a/1885534
|
||||
if [[ "${reply}" =~ ^([Yy]|)$ ]]; then
|
||||
create_jail
|
||||
else
|
||||
echo "${USAGE}"
|
||||
fi
|
||||
;;
|
||||
|
||||
create)
|
||||
create_jail
|
||||
;;
|
||||
|
||||
start)
|
||||
start_jail "${JAILS_DIR_PATH}/${2}"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "${USAGE}"
|
||||
;;
|
||||
esac
|
||||
|
|
Loading…
Reference in New Issue