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:
parent
845e3fe30e
commit
b5243aaa2b
|
@ -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
|
Loading…
Reference in New Issue