165 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
| #!/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:,mapped-uid:,mapped-gid: -- "${@}")
 | |
| 	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;;
 | |
| 			--mapped-uid)		echo "Cannot run with lxc.idmap set in config. Use --uidmap/--gidmap template options instead."; exit 1; shift 2;;
 | |
| 			--mapped-gid)		echo "Cannot run with lxc.idmap set in config. Use --uidmap/--gidmap template options instead."; exit 1; 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"}
 | |
| )
 | |
| 
 | |
| 
 | |
| write_userns_to_config() (
 | |
| 	# uses $path, $uidmap, $gidmap
 | |
| 	printf "lxc.idmap = %s\n" "$(printf "%s" "${uidmap}" | tr ':' ' ')" >> "${path}/config"
 | |
| 	printf "lxc.idmap = %s\n" "$(printf "%s" "${gidmap}" | tr ':' ' ')" >> "${path}/config"
 | |
| )
 | |
| 
 | |
| 
 | |
| parse_args "${0}" "${@}"
 | |
| 
 | |
| check_required_binary "${0}" mmdebstrap || exit 1
 | |
| check_required_binary "${0}" lxc-usernsexec || exit 1
 | |
| 
 | |
| chown_mountpoint || exit 1
 | |
| 
 | |
| install_debian
 | |
| 
 | |
| write_userns_to_config
 |