diff --git a/config/templates/Makefile.am b/config/templates/Makefile.am index 0b265dfb2..3db2269be 100644 --- a/config/templates/Makefile.am +++ b/config/templates/Makefile.am @@ -3,6 +3,8 @@ templatesconfigdir=@LXCTEMPLATECONFIG@ EXTRA_DIST = ubuntu.priv.seccomp templatesconfig_DATA = \ + archlinux.common.conf \ + archlinux.userns.conf \ centos.common.conf \ centos.userns.conf \ debian.common.conf \ diff --git a/config/templates/archlinux.common.conf.in b/config/templates/archlinux.common.conf.in new file mode 100644 index 000000000..2c492995e --- /dev/null +++ b/config/templates/archlinux.common.conf.in @@ -0,0 +1,50 @@ +# Based on fedora.common.conf.in +# Console settings + +lxc.autodev = 1 +lxc.tty = 6 +lxc.pts = 1024 +lxc.kmsg = 0 + +lxc.haltsignal=SIGRTMIN+4 +lxc.stopsignal=SIGRTMIN+14 + +# Mount entries +lxc.mount.auto = proc:mixed sys:ro + +# Capabilities +# Uncomment these if you don't run anything that needs the capability, and +# would like the container to run with less privilege. +# +# Dropping sys_admin disables container root from doing a lot of things +# that could be bad like re-mounting lxc fstab entries rw for example, +# but also disables some useful things like being able to nfs mount, and +# things that are already namespaced with ns_capable() kernel checks, like +# hostname(1). +# lxc.cap.drop = sys_admin +# lxc.cap.drop = net_raw # breaks dhcp/ping +# lxc.cap.drop = setgid # breaks login (initgroups/setgroups) +# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) +# lxc.cap.drop = setuid # breaks sshd,nfs statd +# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) +# lxc.cap.drop = audit_write +# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd +# +lxc.cap.drop = mac_admin mac_override +lxc.cap.drop = setfcap +lxc.cap.drop = sys_module sys_nice sys_pacct +lxc.cap.drop = sys_rawio sys_time + +# Control Group devices: all denied except those whitelisted +lxc.cgroup.devices.deny = a +# Allow any mknod (but not reading/writing the node) +lxc.cgroup.devices.allow = c *:* m +lxc.cgroup.devices.allow = b *:* m +lxc.cgroup.devices.allow = c 1:3 rwm # /dev/null +lxc.cgroup.devices.allow = c 1:5 rwm # /dev/zero +lxc.cgroup.devices.allow = c 1:7 rwm # /dev/full +lxc.cgroup.devices.allow = c 5:0 rwm # /dev/tty +lxc.cgroup.devices.allow = c 1:8 rwm # /dev/random +lxc.cgroup.devices.allow = c 1:9 rwm # /dev/urandom +lxc.cgroup.devices.allow = c 136:* rwm # /dev/tty[1-6] ptys and lxc console +lxc.cgroup.devices.allow = c 5:2 rwm # /dev/ptmx pty master diff --git a/config/templates/archlinux.userns.conf.in b/config/templates/archlinux.userns.conf.in new file mode 100644 index 000000000..28b03faaf --- /dev/null +++ b/config/templates/archlinux.userns.conf.in @@ -0,0 +1,20 @@ +# Based on fedora.userns.conf.in +# CAP_SYS_ADMIN in init-user-ns is required for cgroup.devices +lxc.cgroup.devices.deny = +lxc.cgroup.devices.allow = + +# We can't move bind-mounts, so don't use /dev/lxc/ +lxc.devttydir = + +# Extra bind-mounts for userns +lxc.mount.entry = /dev/console dev/console none bind,create=file 0 0 +lxc.mount.entry = /dev/full dev/full none bind,create=file 0 0 +lxc.mount.entry = /dev/null dev/null none bind,create=file 0 0 +lxc.mount.entry = /dev/random dev/random none bind,create=file 0 0 +lxc.mount.entry = /dev/tty dev/tty none bind,create=file 0 0 +lxc.mount.entry = /dev/urandom dev/urandom none bind,create=file 0 0 +lxc.mount.entry = /dev/zero dev/zero none bind,create=file 0 0 + +# Extra fstab entries as mountall can't mount those by itself +# lxc.mount.entry = /sys/firmware/efi/efivars sys/firmware/efi/efivars none bind,optional 0 0 +lxc.mount.entry = /proc/sys/fs/binfmt_misc proc/sys/fs/binfmt_misc none bind,optional 0 0 diff --git a/configure.ac b/configure.ac index 6ee9aaa04..1a27e1f74 100644 --- a/configure.ac +++ b/configure.ac @@ -594,6 +594,8 @@ AC_CONFIG_FILES([ config/init/upstart/Makefile config/etc/Makefile config/templates/Makefile + config/templates/archlinux.common.conf + config/templates/archlinux.userns.conf config/templates/centos.common.conf config/templates/centos.userns.conf config/templates/debian.common.conf diff --git a/templates/lxc-archlinux.in b/templates/lxc-archlinux.in old mode 100755 new mode 100644 index ec14a9a7b..6f3ce2e03 --- a/templates/lxc-archlinux.in +++ b/templates/lxc-archlinux.in @@ -1,14 +1,14 @@ #!/bin/bash # -# template script for generating Arch linux container for LXC +# template script for generating Arch Linux container for LXC # # # lxc: linux Container library # Authors: -# Alexander Vladimirov +# Alexander Vladimirov # John Lane # This library is free software; you can redistribute it and/or @@ -40,12 +40,11 @@ export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin # defaults arch=$(uname -m) -lxc_network_type="veth" -lxc_network_link="br0" default_path="@LXCPATH@" default_locale="en-US.UTF-8" default_timezone="UTC" pacman_config="/etc/pacman.conf" +shared_config="@LXCTEMPLATECONFIG@/archlinux.common.conf" # by default, install 'base' except the kernel pkg_blacklist="linux" @@ -73,20 +72,14 @@ split_string() { configure_arch() { # on ArchLinux, read defaults from host systemd configuration if [ "${is_arch}" ]; then - cp -p /etc/vconsole.conf /etc/locale.conf /etc/locale.gen \ - "${rootfs_path}/etc/" + cp -p /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/" else echo "LANG=${default_lang}" > "${rootfs_path}/etc/locale.conf" - echo "KEYMAP=us" > "${rootfs_path}/etc/vconsole.conf" - cat > "${rootfs_path}/etc/adjtime" << EOF -0.0 0.0 0.0 -0 -LOCAL -EOF if [ -e "${rootfs_path}/etc/locale.gen" ]; then sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen" if [ ! "${default_locale}" = "en_US.UTF-8" ]; then - echo "${default_locale} ${default_locale##*.}" >> "${rootfs_path}/etc/locale.gen" + echo "${default_locale} ${default_locale##*.}" >> \ + "${rootfs_path}/etc/locale.gen" fi fi fi @@ -102,65 +95,41 @@ EOF mkdir /run/lock locale-gen ln -s /usr/share/zoneinfo/${default_timezone} /etc/localtime -# disable services unavailable for container -for i in systemd-udevd.service \ - systemd-udevd-control.socket \ - systemd-udevd-kernel.socket \ - proc-sys-fs-binfmt_misc.automount; do - ln -s /dev/null /etc/systemd/system/\$i -done -# set default systemd target +# set default boot target ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target -# enable sigpwr signal handling in systemd as otherwise lxc-stop won't work -ln -s /usr/lib/systemd/system/poweroff.target /etc/systemd/system/sigpwr.target -# initialize pacman keyring -pacman-key --init -pacman-key --populate archlinux +# override getty@.service for container ttys +sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ + -e 's/After=dev-%i.device/After=/' \ + < /lib/systemd/system/getty\@.service \ + > /etc/systemd/system/getty\@.service EOF + # enable getty on active ttys + nttys=$(grep lxc.tty ${config_path}/config | cut -d= -f 2 | tr -d "[:blank:]") + if [ ${nttys:-0} -gt 1 ]; then + ( cd ${rootfs_path}/etc/systemd/system/getty.target.wants + for i in $(seq 1 $nttys); do ln -sf ../getty\@.service getty@tty${i}.service; done ) + fi + [ ${nttys:-0} -gt 6 ] && echo \ + "You may want to modify container's /etc/securetty \ + file to allow root logins on tty7 and higher" return 0 } # write container configuration files copy_configuration() { mkdir -p "${config_path}" - cat > "${config_path}/config" << EOF -lxc.utsname=${name} -lxc.autodev=1 -lxc.tty=1 -lxc.pts=1024 -lxc.mount=${config_path}/fstab -lxc.cap.drop=sys_module mac_admin mac_override sys_time -lxc.kmsg=0 -lxc.stopsignal=SIGRTMIN+4 -#networking -lxc.network.type=${lxc_network_type} -lxc.network.link=${lxc_network_link} -lxc.network.flags=up -lxc.network.name=eth0 -lxc.network.mtu=1500 -#cgroups -lxc.cgroup.devices.deny = a -lxc.cgroup.devices.allow = c *:* m -lxc.cgroup.devices.allow = b *:* m -lxc.cgroup.devices.allow = c 1:3 rwm -lxc.cgroup.devices.allow = c 1:5 rwm -lxc.cgroup.devices.allow = c 1:7 rwm -lxc.cgroup.devices.allow = c 1:8 rwm -lxc.cgroup.devices.allow = c 1:9 rwm -lxc.cgroup.devices.allow = c 4:1 rwm -lxc.cgroup.devices.allow = c 5:0 rwm -lxc.cgroup.devices.allow = c 5:1 rwm -lxc.cgroup.devices.allow = c 5:2 rwm -lxc.cgroup.devices.allow = c 136:* rwm -EOF - - grep -q "^lxc.rootfs" ${config_path}/config 2>/dev/null || echo "lxc.rootfs = ${path}/rootfs" >> ${config_path}/config - - cat > "${config_path}/fstab" << EOF -sysfs sys sysfs defaults 0 0 -proc proc proc nodev,noexec,nosuid 0 0 -EOF - + local config="${config_path}/config" + echo "lxc.utsname = ${name}" >> "${config}" + grep -q "^lxc.arch" "${config}" 2>/dev/null \ + || echo "lxc.arch = ${arch}" >> "${config}" + grep -q "^lxc.rootfs" "${config}" 2>/dev/null \ + || echo "lxc.rootfs = ${rootfs_path}" >> "${config}" + [ -e "${shared_config}" ] \ + && echo "lxc.include = ${shared_config}" >> "${config}" + if [ $? -ne 0 ]; then + echo "Failed to configure container" + return 1 + fi return 0 } @@ -181,7 +150,7 @@ install_arch() { fi if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \ - ${base_packages[@]}; then + ${base_packages[@]}; then echo "Failed to install container packages" return 1 fi @@ -200,25 +169,26 @@ install_arch() { usage() { cat < - [-P|--packages=] [-p|--path=] [-t|--network_type=] [-l|--network_link=] [-h|--help] + ${1} -n|--name= [-p|--path=] [-a|--arch=] [-r|--root_password=] + [-P|--packages=] [-e|--enable_units=unit1,unit2...] [-c|--config=] [-h|--help] + Mandatory args: - -n,--name container name, used to as an identifier for that container from now on + -n,--name container name, used to as an identifier for that container from now on Optional args: - -p,--path path to where the container rootfs will be created, defaults to ${default_path}/rootfs. The container config will go under ${default_path} in that case - -P,--packages preinstall additional packages, comma-separated list - -e,--enable_units Enable additional systemd units, comma-separated list - -c,--config use specified pacman config when installing container packages - -a,--arch use specified architecture instead of host's architecture - -t,--network_type set container network interface type (${lxc_network_type}) - -l,--network_link set network link device (${lxc_network_link}) - -r,--root_passwd set container root password - -h,--help print this help + -p,--path path to where the container rootfs will be created (${default_path}) + --rootfs path for actual container rootfs, (${default_path/rootfs) + -P,--packages preinstall additional packages, comma-separated list + -e,--enable_units enable systemd services, comma-separated list + -d,--disable_units disable systemd services, comma-separated list + -c,--config use specified pacman config when installing container packages + -a,--arch use specified architecture instead of host's architecture + -r,--root_password set container root password + -h,--help print this help EOF return 0 } -options=$(getopt -o hp:P:e:n:c:a:l:t:r: -l help,rootfs:,path:,packages:,enable_units:,name:,config:,arch:,network_type:,network_link:,root_passwd: -- "${@}") +options=$(getopt -o hp:P:e:d:n:c:a:r: -l help,rootfs:,path:,packages:,enable_units:,disable_units:,name:,config:,arch:,root_password: -- "${@}") if [ ${?} -ne 0 ]; then usage $(basename ${0}) exit 1 @@ -234,11 +204,10 @@ do --rootfs) rootfs_path=${2}; shift 2;; -P|--packages) additional_packages=${2}; shift 2;; -e|--enable_units) enable_units=${2}; shift 2;; + -d|--disable_units) disable_units=${2}; shift 2;; -c|--config) pacman_config=${2}; shift 2;; -a|--arch) arch=${2}; shift 2;; - -t|--network_type) lxc_network_type=${2}; shift 2;; - -l|--network_link) lxc_network_link=${2}; shift 2;; - -r|--root_passwd) root_passwd=${2}; shift 2;; + -r|--root_password) root_passwd=${2}; shift 2;; --) shift 1; break ;; *) break ;; esac @@ -249,11 +218,6 @@ if [ -z "${name}" ]; then exit 1 fi -if [ ! -e /sys/class/net/${lxc_network_link} ]; then - echo "network link interface, ${lxc_network_link}, does not exist" - exit 1 -fi - type pacman >/dev/null 2>&1 if [ ${?} -ne 0 ]; then echo "'pacman' command is missing, refer to wiki.archlinux.org for information about installing pacman" @@ -272,7 +236,7 @@ fi if [ -z "$rootfs_path" ]; then rootfs_path="${path}/rootfs" fi -config_path="${default_path}/${name}" +config_path="${path}" revert() { echo "Interrupted, cleaning up" @@ -314,9 +278,17 @@ fi if [ ${#enable_units[@]} -gt 0 ]; then split_string ${enable_units} for unit in ${result[@]}; do - [ "${unit}" = *'.'* ] || unit="${unit}.service" - ln -s /usr/lib/systemd/system/"${unit}" \ - "${rootfs_path}"/etc/systemd/system/multi-user.target.wants + [ "${unit##*.}" = "service" ] || unit="${unit}.service" + ln -s "/usr/lib/systemd/system/${unit}" \ + "${rootfs_path}/etc/systemd/system/multi-user.target.wants/" + done +fi + +if [ ${#disable_units[@]} -gt 0 ]; then + split_string ${disable_units} + for unit in ${result[@]}; do + [ "${unit##*.}" = "service" ] || unit="${unit}.service" + ln -s /dev/null "${rootfs_path}/etc/systemd/system/${unit}" done fi @@ -325,7 +297,7 @@ if [ -n "${root_passwd}" ]; then fi cat << EOF -ArchLinux container ${name} is successfully created! The configuration is +Arch Linux container ${name} is successfully created! The configuration is stored in ${config_path}/config. Please refer to https://wiki.archlinux.org for -information about configuring ArchLinux. +information about configuring Arch Linux. EOF