Update Arch Linux template and add common configuration files

Move common container configuration entries into template config.
Remove unnecessary service symlinking and configuration entries, as well as
guest configs and other redundant configuration, fix minor script bugs.
Clean up template command line, add -d option to allow disabling services.
Also enable getty's on all configured ttys to allow logins via lxc-console,
set lxc.tty value corresponding to default Arch /etc/securetty configuration.

This patch simplifies Arch Linux template a bit, while fixing some
longstanding issues. It also provides common configuration based on
files provided for Fedora templates.

Signed-off-by: Alexander Vladimirov <alexander.idkfa.vladimirov@gmail.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
This commit is contained in:
Alexander Vladimirov 2014-06-25 01:27:54 +08:00 committed by Stéphane Graber
parent f36062dc50
commit c194ffc100
5 changed files with 138 additions and 92 deletions

View File

@ -3,6 +3,8 @@ templatesconfigdir=@LXCTEMPLATECONFIG@
EXTRA_DIST = ubuntu.priv.seccomp EXTRA_DIST = ubuntu.priv.seccomp
templatesconfig_DATA = \ templatesconfig_DATA = \
archlinux.common.conf \
archlinux.userns.conf \
centos.common.conf \ centos.common.conf \
centos.userns.conf \ centos.userns.conf \
debian.common.conf \ debian.common.conf \

View File

@ -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

View File

@ -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

View File

@ -594,6 +594,8 @@ AC_CONFIG_FILES([
config/init/upstart/Makefile config/init/upstart/Makefile
config/etc/Makefile config/etc/Makefile
config/templates/Makefile config/templates/Makefile
config/templates/archlinux.common.conf
config/templates/archlinux.userns.conf
config/templates/centos.common.conf config/templates/centos.common.conf
config/templates/centos.userns.conf config/templates/centos.userns.conf
config/templates/debian.common.conf config/templates/debian.common.conf

156
templates/lxc-archlinux.in Executable file → Normal file
View File

@ -1,14 +1,14 @@
#!/bin/bash #!/bin/bash
# #
# template script for generating Arch linux container for LXC # template script for generating Arch Linux container for LXC
# #
# #
# lxc: linux Container library # lxc: linux Container library
# Authors: # Authors:
# Alexander Vladimirov <idkfa@vlan1.ru> # Alexander Vladimirov <alexander.idkfa.vladimirov@gmail.com>
# John Lane <lxc@jelmail.com> # John Lane <lxc@jelmail.com>
# This library is free software; you can redistribute it and/or # 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 # defaults
arch=$(uname -m) arch=$(uname -m)
lxc_network_type="veth"
lxc_network_link="br0"
default_path="@LXCPATH@" default_path="@LXCPATH@"
default_locale="en-US.UTF-8" default_locale="en-US.UTF-8"
default_timezone="UTC" default_timezone="UTC"
pacman_config="/etc/pacman.conf" pacman_config="/etc/pacman.conf"
shared_config="@LXCTEMPLATECONFIG@/archlinux.common.conf"
# by default, install 'base' except the kernel # by default, install 'base' except the kernel
pkg_blacklist="linux" pkg_blacklist="linux"
@ -73,20 +72,14 @@ split_string() {
configure_arch() { configure_arch() {
# on ArchLinux, read defaults from host systemd configuration # on ArchLinux, read defaults from host systemd configuration
if [ "${is_arch}" ]; then if [ "${is_arch}" ]; then
cp -p /etc/vconsole.conf /etc/locale.conf /etc/locale.gen \ cp -p /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/"
"${rootfs_path}/etc/"
else else
echo "LANG=${default_lang}" > "${rootfs_path}/etc/locale.conf" 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 if [ -e "${rootfs_path}/etc/locale.gen" ]; then
sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen" sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen"
if [ ! "${default_locale}" = "en_US.UTF-8" ]; then 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 fi
fi fi
@ -102,65 +95,41 @@ EOF
mkdir /run/lock mkdir /run/lock
locale-gen locale-gen
ln -s /usr/share/zoneinfo/${default_timezone} /etc/localtime ln -s /usr/share/zoneinfo/${default_timezone} /etc/localtime
# disable services unavailable for container # set default boot target
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
ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.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 # override getty@.service for container ttys
ln -s /usr/lib/systemd/system/poweroff.target /etc/systemd/system/sigpwr.target sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
# initialize pacman keyring -e 's/After=dev-%i.device/After=/' \
pacman-key --init < /lib/systemd/system/getty\@.service \
pacman-key --populate archlinux > /etc/systemd/system/getty\@.service
EOF 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 return 0
} }
# write container configuration files # write container configuration files
copy_configuration() { copy_configuration() {
mkdir -p "${config_path}" mkdir -p "${config_path}"
cat > "${config_path}/config" << EOF local config="${config_path}/config"
lxc.utsname=${name} echo "lxc.utsname = ${name}" >> "${config}"
lxc.autodev=1 grep -q "^lxc.arch" "${config}" 2>/dev/null \
lxc.tty=1 || echo "lxc.arch = ${arch}" >> "${config}"
lxc.pts=1024 grep -q "^lxc.rootfs" "${config}" 2>/dev/null \
lxc.mount=${config_path}/fstab || echo "lxc.rootfs = ${rootfs_path}" >> "${config}"
lxc.cap.drop=sys_module mac_admin mac_override sys_time [ -e "${shared_config}" ] \
lxc.kmsg=0 && echo "lxc.include = ${shared_config}" >> "${config}"
lxc.stopsignal=SIGRTMIN+4 if [ $? -ne 0 ]; then
#networking echo "Failed to configure container"
lxc.network.type=${lxc_network_type} return 1
lxc.network.link=${lxc_network_link} fi
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
return 0 return 0
} }
@ -181,7 +150,7 @@ install_arch() {
fi fi
if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \ if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \
${base_packages[@]}; then ${base_packages[@]}; then
echo "Failed to install container packages" echo "Failed to install container packages"
return 1 return 1
fi fi
@ -200,25 +169,26 @@ install_arch() {
usage() { usage() {
cat <<EOF cat <<EOF
usage: usage:
${1} -n|--name=<container_name> ${1} -n|--name=<container_name> [-p|--path=<path>] [-a|--arch=<arch of the container>] [-r|--root_password=<root password>]
[-P|--packages=<pkg1,pkg2,...>] [-p|--path=<path>] [-t|--network_type=<type>] [-l|--network_link=<link>] [-h|--help] [-P|--packages=<pkg1,pkg2,...>] [-e|--enable_units=unit1,unit2...] [-c|--config=<pacman config path>] [-h|--help]
Mandatory args: 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: 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,--path path to where the container rootfs will be created (${default_path})
-P,--packages preinstall additional packages, comma-separated list --rootfs path for actual container rootfs, (${default_path/rootfs)
-e,--enable_units Enable additional systemd units, comma-separated list -P,--packages preinstall additional packages, comma-separated list
-c,--config use specified pacman config when installing container packages -e,--enable_units enable systemd services, comma-separated list
-a,--arch use specified architecture instead of host's architecture -d,--disable_units disable systemd services, comma-separated list
-t,--network_type set container network interface type (${lxc_network_type}) -c,--config use specified pacman config when installing container packages
-l,--network_link set network link device (${lxc_network_link}) -a,--arch use specified architecture instead of host's architecture
-r,--root_passwd set container root password -r,--root_password set container root password
-h,--help print this help -h,--help print this help
EOF EOF
return 0 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 if [ ${?} -ne 0 ]; then
usage $(basename ${0}) usage $(basename ${0})
exit 1 exit 1
@ -234,11 +204,10 @@ do
--rootfs) rootfs_path=${2}; shift 2;; --rootfs) rootfs_path=${2}; shift 2;;
-P|--packages) additional_packages=${2}; shift 2;; -P|--packages) additional_packages=${2}; shift 2;;
-e|--enable_units) enable_units=${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;; -c|--config) pacman_config=${2}; shift 2;;
-a|--arch) arch=${2}; shift 2;; -a|--arch) arch=${2}; shift 2;;
-t|--network_type) lxc_network_type=${2}; shift 2;; -r|--root_password) root_passwd=${2}; shift 2;;
-l|--network_link) lxc_network_link=${2}; shift 2;;
-r|--root_passwd) root_passwd=${2}; shift 2;;
--) shift 1; break ;; --) shift 1; break ;;
*) break ;; *) break ;;
esac esac
@ -249,11 +218,6 @@ if [ -z "${name}" ]; then
exit 1 exit 1
fi 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 type pacman >/dev/null 2>&1
if [ ${?} -ne 0 ]; then if [ ${?} -ne 0 ]; then
echo "'pacman' command is missing, refer to wiki.archlinux.org for information about installing pacman" 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 if [ -z "$rootfs_path" ]; then
rootfs_path="${path}/rootfs" rootfs_path="${path}/rootfs"
fi fi
config_path="${default_path}/${name}" config_path="${path}"
revert() { revert() {
echo "Interrupted, cleaning up" echo "Interrupted, cleaning up"
@ -314,9 +278,17 @@ fi
if [ ${#enable_units[@]} -gt 0 ]; then if [ ${#enable_units[@]} -gt 0 ]; then
split_string ${enable_units} split_string ${enable_units}
for unit in ${result[@]}; do for unit in ${result[@]}; do
[ "${unit}" = *'.'* ] || unit="${unit}.service" [ "${unit##*.}" = "service" ] || unit="${unit}.service"
ln -s /usr/lib/systemd/system/"${unit}" \ ln -s "/usr/lib/systemd/system/${unit}" \
"${rootfs_path}"/etc/systemd/system/multi-user.target.wants "${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 done
fi fi
@ -325,7 +297,7 @@ if [ -n "${root_passwd}" ]; then
fi fi
cat << EOF 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 stored in ${config_path}/config. Please refer to https://wiki.archlinux.org for
information about configuring ArchLinux. information about configuring Arch Linux.
EOF EOF