Add lxc-debian-userns LXC template script

This script can be used as LXC template to install a Debian into a
directory using `mmdebstrap`. It's intended use is to create a container
filesystem with appropriate uids/gids for use in an unprivileged
container. The script assumes that it runs as root and only changes the
userns to install Debian.
This commit is contained in:
MasterofJOKers 2023-02-26 00:24:25 +01:00
parent 845e3fe30e
commit b5243aaa2b
1 changed files with 153 additions and 0 deletions

153
lxc/lxc-debian-userns Executable file
View File

@ -0,0 +1,153 @@
#!/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