lxc-archlinux.in revision d8c77af0ae59a3c48a44a11c95b991bd10473713
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#!/bin/bash
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# template script for generating Arch linux container for LXC
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# lxc: linux Container library
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# Authors:
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# Alexander Vladimirov <idkfa@vlan1.ru>
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# This library is free software; you can redistribute it and/or
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# modify it under the terms of the GNU Lesser General Public
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# License as published by the Free Software Foundation; either
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# version 2.1 of the License, or (at your option) any later version.
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# This library is distributed in the hope that it will be useful,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# but WITHOUT ANY WARRANTY; without even the implied warranty of
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# Lesser General Public License for more details.
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# You should have received a copy of the GNU Lesser General Public
8900b9eb2514c07047541833286428572493a9fdStéphane Graber# License along with this library; if not, write to the Free Software
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# defaults
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiarch=$(uname -m)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumilxc_network_type="veth"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumilxc_network_link="br0"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumidefault_path="@LXCPATH@"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumidefault_locale="en-US.UTF-8"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumidefault_timezone="UTC"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumipacman_config="/etc/pacman.conf"
a600d021adf34e58b3991269a9ceca3737c63aa8KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# sort of minimal package set
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumibase_packages=(
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "systemd"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "systemd-sysvcompat"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "filesystem"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "coreutils"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "kmod"
23faab5d6b6276950f83f6a924387cbc4a70deb1Sungbae Yoo "procps"
23faab5d6b6276950f83f6a924387cbc4a70deb1Sungbae Yoo "psmisc"
23faab5d6b6276950f83f6a924387cbc4a70deb1Sungbae Yoo "pacman"
23faab5d6b6276950f83f6a924387cbc4a70deb1Sungbae Yoo "bash"
23faab5d6b6276950f83f6a924387cbc4a70deb1Sungbae Yoo "cronie"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "iproute2"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "iputils"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "inetutils"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "dhcpcd"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "dnsutils"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "nano"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "grep"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "less"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "gawk"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "sed"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "tar"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "gzip"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "which"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumideclare -a additional_packages
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# split comma-separated string into an array
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# ${1} - string to split
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# ${2} - separator (default is ",")
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# ${result} - result value on success
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumisplit_string() {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi local ifs=${IFS}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi IFS="${2:-,}"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi read -a result < <(echo "${1}")
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi IFS=${ifs}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return 0
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi[ -f /etc/arch-release ] && is_arch=true
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# Arch-specific preconfiguration for container
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiconfigure_arch() {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi # read locale and timezone defaults from system rc.conf if running on Arch
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if [ "${is_arch}" ]; then
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi cp -p /etc/vconsole.conf /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi else
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi echo "LANG=${default_lang}" > "${rootfs_path}/etc/locale.conf"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi echo "KEYMAP=us" > "${rootfs_path}/etc/vconsole.conf"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi cat > "${rootfs_path}/etc/adjtime" << EOF
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi0.0 0.0 0.0
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi0
57da8c32f85c0255efa61ee32e260068afdaa565KATOH YasufumiLOCAL
57da8c32f85c0255efa61ee32e260068afdaa565KATOH YasufumiEOF
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if [ -e "${rootfs_path}/etc/locale.gen" ]; then
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if [ ! "${default_locale}" = "en_US.UTF-8" ]; then
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi echo "${default_locale} ${default_locale##*.}" >> "${rootfs_path}/etc/locale.gen"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi fi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi fi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi fi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi echo "${name}" > "${rootfs_path}/etc/hostname"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi cat > "${rootfs_path}/etc/hosts" << EOF
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi127.0.0.1 localhost.localdomain localhost ${name}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi::1 localhost.localdomain localhost
57da8c32f85c0255efa61ee32e260068afdaa565KATOH YasufumiEOF
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi grep nameserver /etc/resolv.conf > "${rootfs_path}/etc/resolv.conf"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi arch-chroot "${rootfs_path}" /bin/bash -s << EOF
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumimkdir /run/lock
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumilocale-gen
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiln -s /usr/share/zoneinfo/${default_timezone} /etc/localtime
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# disable services unavailable for container
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiln -s /dev/null /etc/systemd/system/systemd-udevd.service
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# set default systemd target
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
57da8c32f85c0255efa61ee32e260068afdaa565KATOH YasufumiEOF
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return 0
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi# write container configuration files
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumicopy_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 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 = ${rootfs_path}" >> ${config_path}/config
cat > "${config_path}/fstab" << EOF
sysfs sys sysfs ro,defaults 0 0
proc proc proc nodev,noexec,nosuid 0 0
/proc/sys ${rootfs_path}/proc/sys none ro,bind 0 0
#/var/log/journal ${rootfs_path}/var/log/journal none bind 0 0
EOF
return 0
}
# install packages within container chroot
install_arch() {
if ! pacstrap -dcC "${pacman_config}" "${rootfs_path}" ${base_packages[@]}; then
echo "Failed to install container packages"
return 1
fi
[ -d "${rootfs_path}/lib/modules" ] && ldconfig -r "${rootfs_path}"
return 0
}
usage() {
cat <<EOF
usage:
${1} -n|--name=<container_name>
[-P|--packages=<pkg1,pkg2,...>] [-p|--path=<path>] [-t|--network_type=<type>] [-l|--network_link=<link>] [-h|--help]
Mandatory args:
-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
-c,--config use specified pacman config when installing container packages
-t,--network_type set container network interface type (${lxc_network_type})
-l,--network_link set network link device (${lxc_network_link})
-h,--help print this help
EOF
return 0
}
options=$(getopt -o hp:P:n:c:l:t: -l help,rootfs:,path:,packages:,name:,config:,network_type:,network_link: -- "${@}")
if [ ${?} -ne 0 ]; then
usage $(basename ${0})
exit 1
fi
eval set -- "${options}"
while true
do
case "${1}" in
-h|--help) usage ${0} && exit 0;;
-p|--path) path=${2}; shift 2;;
-n|--name) name=${2}; shift 2;;
--rootfs) rootfs_path=${2}; shift 2;;
-P|--packages) additional_packages=${2}; shift 2;;
-c|--config) pacman_config=${2}; shift 2;;
-t|--network_type) lxc_network_type=${2}; shift 2;;
-l|--network_link) lxc_network_link=${2}; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ -z "${name}" ]; then
echo "missing required 'name' parameter"
exit 1
fi
if [ ! -e /sys/class/net/${lxc_network_link} ]; then
echo "network link interface 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"
exit 1
fi
if [ -z "${path}" ]; then
path="${default_path}/${name}"
fi
if [ "${EUID}" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -z "$rootfs_path" ]; then
rootfs_path="${path}/rootfs"
fi
config_path="${default_path}/${name}"
revert() {
echo "Interrupted, cleaning up"
lxc-destroy -n "${name}"
rm -rf "${path}/${name}"
rm -rf "${default_path}/${name}"
exit 1
}
trap revert SIGHUP SIGINT SIGTERM
copy_configuration
if [ ${?} -ne 0 ]; then
echo "failed to write configuration file"
rm -rf "${config_path}"
exit 1
fi
if [ ${#additional_packages[@]} -gt 0 ]; then
split_string ${additional_packages}
base_packages+=(${result[@]})
fi
mkdir -p "${rootfs_path}"
install_arch
if [ ${?} -ne 0 ]; then
echo "failed to install Arch Linux"
rm -rf "${config_path}" "${path}"
exit 1
fi
configure_arch
if [ ${?} -ne 0 ]; then
echo "failed to configure Arch Linux for a container"
rm -rf "${config_path}" "${path}"
exit 1
fi
echo "container config is ${config_path}/config"