154 lines
4.8 KiB
Plaintext
154 lines
4.8 KiB
Plaintext
|
#!/bin/sh
|
||
|
|
||
|
usage() (
|
||
|
cat <<-EOF
|
||
|
Template specific options can be passed to lxc-create after a '--' like this:
|
||
|
|
||
|
lxc-create --name=NAME [-lxc-create-options] -- [-template-options]
|
||
|
|
||
|
Usage: ${1} -h|--help --path=<path> --name=<name> --rootfs=<rootfs>
|
||
|
--uidmap=<uidmap> --gidmap=<gidmap>
|
||
|
--mirror=<mirror> [--security-mirror=<security mirror>]
|
||
|
[--release=<release>]
|
||
|
[--auth-key=<keyfile>]
|
||
|
|
||
|
Options :
|
||
|
|
||
|
-h, --help print this help text
|
||
|
--path=PATH directory where config of this VM will be kept
|
||
|
--name=NAME hostname name of the container
|
||
|
--rootfs=ROOTFS directory where the root filesystem can be accessed
|
||
|
--uidmap=UIDMAP Map of user ids for the userns. Format u:0:1000000:65535
|
||
|
See lxc-usernsexec (1) for format details.
|
||
|
--gidmap=GIDMAP Map of group ids for the userns. Format g:0:1000000:65535
|
||
|
See lxc-usernsexec (1) for format details.
|
||
|
--auth-key=KEYFILE SSH public key to inject into the container as the root user.
|
||
|
--release=RELEASE Debian release. Defaults to "stable"
|
||
|
--mirror=MIRROR Debian mirror to use during installation.
|
||
|
--security-mirror=SECURITY_MIRROR
|
||
|
Debian mirror to use for security updates.
|
||
|
|
||
|
This template uses mmdebstrap to install Debian in a userns into a directory as provided by lxc-create via the
|
||
|
--rootfs option. It's intended use is to create a filesystem for unprivileged containers started as root.
|
||
|
EOF
|
||
|
return 0
|
||
|
)
|
||
|
|
||
|
|
||
|
check_required_binary() (
|
||
|
prog="${1}"
|
||
|
bin="${2}"
|
||
|
if ! which ${bin} > /dev/null; then
|
||
|
printf "error: Need '%s' executable in PATH to execute this template.\n\n" ${bin}
|
||
|
usage "${prog}"
|
||
|
return 1
|
||
|
fi
|
||
|
return 0
|
||
|
)
|
||
|
|
||
|
|
||
|
check_required_arg() (
|
||
|
prog="${1}"
|
||
|
value="${2}"
|
||
|
opt="${3}"
|
||
|
if [ "${value}" = "" ]; then
|
||
|
printf "error: %s is a required option!\n\n" "${opt}"
|
||
|
usage "${prog}"
|
||
|
return 1
|
||
|
fi
|
||
|
return 0
|
||
|
)
|
||
|
|
||
|
|
||
|
parse_args() {
|
||
|
prog="${0}"
|
||
|
shift
|
||
|
|
||
|
options=$(getopt -o h -l help,path:,name:,rootfs:,mirror:,security-mirror:,auth-key:,release:,uidmap:,gidmap: -- "${@}")
|
||
|
if [ $? -ne 0 ]; then
|
||
|
usage "${prog}"
|
||
|
exit 1
|
||
|
fi
|
||
|
# printf "%s\n" "${options}"
|
||
|
|
||
|
eval set -- "${options}"
|
||
|
|
||
|
while true; do
|
||
|
case "${1}" in
|
||
|
-h|--help) usage "${prog}" && exit 1;;
|
||
|
--) shift 1; break;;
|
||
|
--path) path=${2}; shift 2;;
|
||
|
--name) name=${2}; shift 2;;
|
||
|
--rootfs) rootfs=${2}; shift 2;;
|
||
|
--release) release=${2}; shift 2;;
|
||
|
--mirror) mirror=${2}; shift 2;;
|
||
|
--security-mirror) security_mirror=${2}; shift 2;;
|
||
|
--auth-key) auth_key=${2}; shift 2;;
|
||
|
--uidmap) uidmap=${2}; shift 2;;
|
||
|
--gidmap) gidmap=${2}; shift 2;;
|
||
|
*) echo "programming error: found unknown opt ${1}"; exit 1; break;;
|
||
|
esac
|
||
|
done
|
||
|
|
||
|
# check required args
|
||
|
check_required_arg "${prog}" "${path}" "--path" || exit 1
|
||
|
check_required_arg "${prog}" "${name}" "--name" || exit 1
|
||
|
check_required_arg "${prog}" "${rootfs}" "--rootfs" || exit 1
|
||
|
check_required_arg "${prog}" "${mirror}" "--mirror" || exit 1
|
||
|
check_required_arg "${prog}" "${uidmap}" "--uidmap" || exit 1
|
||
|
check_required_arg "${prog}" "${gidmap}" "--gidmap" || exit 1
|
||
|
|
||
|
# set defaults where necessary
|
||
|
release=${release:-stable}
|
||
|
|
||
|
if ! [ -d "${rootfs}" ]; then
|
||
|
printf "error: --rootfs must point to a valid directory. Got '%s'\n\n" "${rootfs}"
|
||
|
usage "${prog}"
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
if [ "${auth_key}" != "" ] && ! [ -f "${auth_key}" ]; then
|
||
|
printf "error: --auth-key must point to a valid file. Got '%s'\n\n" "${auth_key}"
|
||
|
usage "${prog}"
|
||
|
exit 1
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
|
||
|
chown_mountpoint() (
|
||
|
# uses $rootfs, $uidmap, $gidmap
|
||
|
root_user_in_ns=$(echo $uidmap | cut -d : -f 3)
|
||
|
root_group_in_ns=$(echo $gidmap | cut -d : -f 3)
|
||
|
echo "Found root user ${root_user_in_ns} and group ${root_group_in_ns}"
|
||
|
chown ${root_user_in_ns}:${root_group_in_ns} "${rootfs}"
|
||
|
return 0
|
||
|
)
|
||
|
|
||
|
|
||
|
install_debian() (
|
||
|
# uses $rootfs, $name, $release, $uidmap, $gidmap, $mirror, $security_mirror, $auth_key
|
||
|
set -x
|
||
|
|
||
|
lxc-usernsexec -m ${uidmap} -m ${gidmap} -- \
|
||
|
lxc-unshare -s 'MOUNT|PID|UTSNAME|IPC' -- \
|
||
|
mmdebstrap \
|
||
|
--variant minbase \
|
||
|
--mode unshare \
|
||
|
--include 'init ifupdown locales dialog isc-dhcp-client netbase net-tools iproute2 openssh-server python3 vim' \
|
||
|
--customize-hook 'echo '${name}' > $1/etc/hostname' \
|
||
|
--customize-hook 'cp /etc/timezone $1/etc/timezone' \
|
||
|
${auth_key:+--customize-hook 'mkdir -p $1/root/.ssh' --customize-hook 'cat '${auth_key}' > $1/root/.ssh/authorized_keys'} \
|
||
|
$release "${rootfs}" \
|
||
|
"${mirror}" ${security_mirror:+"deb ${security_mirror} ${release}-security main contrib non-free"}
|
||
|
)
|
||
|
|
||
|
|
||
|
parse_args "${0}" "${@}"
|
||
|
|
||
|
check_required_binary "${0}" mmdebstrap || exit 1
|
||
|
check_required_binary "${0}" lxc-usernsexec || exit 1
|
||
|
|
||
|
chown_mountpoint || exit 1
|
||
|
|
||
|
install_debian
|