]> git.proxmox.com Git - mirror_lxc.git/blame - templates/lxc-archlinux.in
Update Arch Linux template and add common configuration files
[mirror_lxc.git] / templates / lxc-archlinux.in
CommitLineData
f6267d90
AV
1#!/bin/bash
2
3#
c194ffc1 4# template script for generating Arch Linux container for LXC
f6267d90
AV
5#
6
7#
8# lxc: linux Container library
9
10# Authors:
c194ffc1 11# Alexander Vladimirov <alexander.idkfa.vladimirov@gmail.com>
d0800999 12# John Lane <lxc@jelmail.com>
f6267d90
AV
13
14# This library is free software; you can redistribute it and/or
15# modify it under the terms of the GNU Lesser General Public
16# License as published by the Free Software Foundation; either
17# version 2.1 of the License, or (at your option) any later version.
18
19# This library is distributed in the hope that it will be useful,
20# but WITHOUT ANY WARRANTY; without even the implied warranty of
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22# Lesser General Public License for more details.
23
24# You should have received a copy of the GNU Lesser General Public
25# License along with this library; if not, write to the Free Software
250b1eec 26# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
f6267d90 27
8ec981fc 28# Detect use under userns (unsupported)
c63c04fc 29for arg in "$@"; do
96283b54
SG
30 [ "$arg" = "--" ] && break
31 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
8ec981fc
SG
32 echo "This template can't be used for unprivileged containers." 1>&2
33 echo "You may want to try the \"download\" template instead." 1>&2
34 exit 1
35 fi
36done
37
207bf0e4
SG
38# Make sure the usual locations are in PATH
39export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
40
f6267d90 41# defaults
f3849d01 42arch=$(uname -m)
f3849d01
AV
43default_path="@LXCPATH@"
44default_locale="en-US.UTF-8"
45default_timezone="UTC"
14831534 46pacman_config="/etc/pacman.conf"
c194ffc1 47shared_config="@LXCTEMPLATECONFIG@/archlinux.common.conf"
f6267d90 48
b7b7d388
LI
49# by default, install 'base' except the kernel
50pkg_blacklist="linux"
51base_packages=()
52for pkg in $(pacman -Sqg base); do
53 [ "${pkg_blacklist#*$pkg}" = "$pkg_blacklist" ] && base_packages+=($pkg)
54done
f6267d90
AV
55declare -a additional_packages
56
f6267d90
AV
57# split comma-separated string into an array
58# ${1} - string to split
59# ${2} - separator (default is ",")
60# ${result} - result value on success
17abf278 61split_string() {
f6267d90
AV
62 local ifs=${IFS}
63 IFS="${2:-,}"
64 read -a result < <(echo "${1}")
65 IFS=${ifs}
66 return 0
67}
68
f3849d01
AV
69[ -f /etc/arch-release ] && is_arch=true
70
f6267d90 71# Arch-specific preconfiguration for container
17abf278 72configure_arch() {
21ca73b9 73 # on ArchLinux, read defaults from host systemd configuration
f6267d90 74 if [ "${is_arch}" ]; then
c194ffc1 75 cp -p /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/"
f6267d90 76 else
f3849d01 77 echo "LANG=${default_lang}" > "${rootfs_path}/etc/locale.conf"
f3849d01
AV
78 if [ -e "${rootfs_path}/etc/locale.gen" ]; then
79 sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen"
80 if [ ! "${default_locale}" = "en_US.UTF-8" ]; then
c194ffc1
AV
81 echo "${default_locale} ${default_locale##*.}" >> \
82 "${rootfs_path}/etc/locale.gen"
f3849d01 83 fi
f6267d90 84 fi
f6267d90 85 fi
21ca73b9
LI
86
87 # hostname and nameservers
f3849d01 88 echo "${name}" > "${rootfs_path}/etc/hostname"
21ca73b9
LI
89 while read r; do
90 [ "${r#nameserver}" = "$r" ] || echo "$r"
91 done < /etc/resolv.conf > "${rootfs_path}/etc/resolv.conf"
f6267d90 92
21ca73b9 93 # chroot and configure system
f3849d01
AV
94 arch-chroot "${rootfs_path}" /bin/bash -s << EOF
95mkdir /run/lock
96locale-gen
97ln -s /usr/share/zoneinfo/${default_timezone} /etc/localtime
c194ffc1 98# set default boot target
f3849d01 99ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
c194ffc1
AV
100# override getty@.service for container ttys
101sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
102 -e 's/After=dev-%i.device/After=/' \
103 < /lib/systemd/system/getty\@.service \
104 > /etc/systemd/system/getty\@.service
f3849d01 105EOF
c194ffc1
AV
106 # enable getty on active ttys
107 nttys=$(grep lxc.tty ${config_path}/config | cut -d= -f 2 | tr -d "[:blank:]")
108 if [ ${nttys:-0} -gt 1 ]; then
109 ( cd ${rootfs_path}/etc/systemd/system/getty.target.wants
110 for i in $(seq 1 $nttys); do ln -sf ../getty\@.service getty@tty${i}.service; done )
111 fi
112 [ ${nttys:-0} -gt 6 ] && echo \
113 "You may want to modify container's /etc/securetty \
114 file to allow root logins on tty7 and higher"
f6267d90
AV
115 return 0
116}
117
118# write container configuration files
17abf278 119copy_configuration() {
f6267d90 120 mkdir -p "${config_path}"
c194ffc1
AV
121 local config="${config_path}/config"
122 echo "lxc.utsname = ${name}" >> "${config}"
123 grep -q "^lxc.arch" "${config}" 2>/dev/null \
124 || echo "lxc.arch = ${arch}" >> "${config}"
125 grep -q "^lxc.rootfs" "${config}" 2>/dev/null \
126 || echo "lxc.rootfs = ${rootfs_path}" >> "${config}"
127 [ -e "${shared_config}" ] \
128 && echo "lxc.include = ${shared_config}" >> "${config}"
129 if [ $? -ne 0 ]; then
130 echo "Failed to configure container"
131 return 1
132 fi
f6267d90
AV
133 return 0
134}
135
f6267d90 136# install packages within container chroot
17abf278 137install_arch() {
734d0bed
JL
138 [ "${arch}" != "$(uname -m)" ] && different_arch=true
139
140 if [ "${different_arch}" = "true" ]; then
141 container_pacman_config=$(mktemp)
142 container_mirrorlist=$(mktemp)
143 sed -e "s:Architecture =.*:Architecture = ${arch}:g" \
144 -e "s:/etc/pacman.d/mirrorlist:${container_mirrorlist}:g" \
145 "${pacman_config}" > "${container_pacman_config}"
146 sed -e "s:\(x86_64\|\$arch\):${arch}:g" \
147 /etc/pacman.d/mirrorlist > "${container_mirrorlist}"
148
149 pacman_config="${container_pacman_config}"
150 fi
151
44b03630 152 if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \
c194ffc1 153 ${base_packages[@]}; then
f6267d90
AV
154 echo "Failed to install container packages"
155 return 1
156 fi
734d0bed
JL
157
158 if [ "${different_arch}" = "true" ]; then
159 sed -i -e "s:Architecture =.*:Architecture = ${arch}:g" \
160 "${rootfs_path}"/etc/pacman.conf
161 cp "${container_mirrorlist}" "${rootfs_path}"/etc/pacman.d/mirrorlist
162 rm "${container_pacman_config}" "${container_mirrorlist}"
163 fi
164
f6267d90 165 [ -d "${rootfs_path}/lib/modules" ] && ldconfig -r "${rootfs_path}"
f6267d90
AV
166 return 0
167}
168
f3849d01 169usage() {
f6267d90
AV
170 cat <<EOF
171usage:
c194ffc1
AV
172 ${1} -n|--name=<container_name> [-p|--path=<path>] [-a|--arch=<arch of the container>] [-r|--root_password=<root password>]
173 [-P|--packages=<pkg1,pkg2,...>] [-e|--enable_units=unit1,unit2...] [-c|--config=<pacman config path>] [-h|--help]
174
f6267d90 175Mandatory args:
c194ffc1 176 -n,--name container name, used to as an identifier for that container from now on
f6267d90 177Optional args:
c194ffc1
AV
178 -p,--path path to where the container rootfs will be created (${default_path})
179 --rootfs path for actual container rootfs, (${default_path/rootfs)
180 -P,--packages preinstall additional packages, comma-separated list
181 -e,--enable_units enable systemd services, comma-separated list
182 -d,--disable_units disable systemd services, comma-separated list
183 -c,--config use specified pacman config when installing container packages
184 -a,--arch use specified architecture instead of host's architecture
185 -r,--root_password set container root password
186 -h,--help print this help
f6267d90
AV
187EOF
188 return 0
189}
190
c194ffc1 191options=$(getopt -o hp:P:e:d:n:c:a:r: -l help,rootfs:,path:,packages:,enable_units:,disable_units:,name:,config:,arch:,root_password: -- "${@}")
f6267d90
AV
192if [ ${?} -ne 0 ]; then
193 usage $(basename ${0})
194 exit 1
195fi
196eval set -- "${options}"
197
198while true
199do
200 case "${1}" in
f3849d01
AV
201 -h|--help) usage ${0} && exit 0;;
202 -p|--path) path=${2}; shift 2;;
203 -n|--name) name=${2}; shift 2;;
1897e3bc 204 --rootfs) rootfs_path=${2}; shift 2;;
f3849d01 205 -P|--packages) additional_packages=${2}; shift 2;;
012f591a 206 -e|--enable_units) enable_units=${2}; shift 2;;
c194ffc1 207 -d|--disable_units) disable_units=${2}; shift 2;;
14831534 208 -c|--config) pacman_config=${2}; shift 2;;
734d0bed 209 -a|--arch) arch=${2}; shift 2;;
c194ffc1 210 -r|--root_password) root_passwd=${2}; shift 2;;
f6267d90
AV
211 --) shift 1; break ;;
212 *) break ;;
213 esac
214done
215
216if [ -z "${name}" ]; then
217 echo "missing required 'name' parameter"
218 exit 1
219fi
220
221type pacman >/dev/null 2>&1
222if [ ${?} -ne 0 ]; then
223 echo "'pacman' command is missing, refer to wiki.archlinux.org for information about installing pacman"
224 exit 1
225fi
226
227if [ -z "${path}" ]; then
228 path="${default_path}/${name}"
229fi
230
231if [ "${EUID}" != "0" ]; then
232 echo "This script should be run as 'root'"
233 exit 1
234fi
235
1897e3bc
SH
236if [ -z "$rootfs_path" ]; then
237 rootfs_path="${path}/rootfs"
238fi
c194ffc1 239config_path="${path}"
f6267d90 240
f3849d01
AV
241revert() {
242 echo "Interrupted, cleaning up"
f6267d90 243 lxc-destroy -n "${name}"
f6267d90
AV
244 rm -rf "${path}/${name}"
245 rm -rf "${default_path}/${name}"
246 exit 1
247}
248
249trap revert SIGHUP SIGINT SIGTERM
250
251copy_configuration
252if [ ${?} -ne 0 ]; then
f3849d01 253 echo "failed to write configuration file"
f6267d90
AV
254 rm -rf "${config_path}"
255 exit 1
256fi
257
258if [ ${#additional_packages[@]} -gt 0 ]; then
259 split_string ${additional_packages}
260 base_packages+=(${result[@]})
261fi
262
f3849d01 263mkdir -p "${rootfs_path}"
f6267d90
AV
264install_arch
265if [ ${?} -ne 0 ]; then
f3849d01 266 echo "failed to install Arch Linux"
f6267d90
AV
267 rm -rf "${config_path}" "${path}"
268 exit 1
269fi
270
271configure_arch
272if [ ${?} -ne 0 ]; then
f3849d01 273 echo "failed to configure Arch Linux for a container"
f6267d90
AV
274 rm -rf "${config_path}" "${path}"
275 exit 1
276fi
277
012f591a
JL
278if [ ${#enable_units[@]} -gt 0 ]; then
279 split_string ${enable_units}
280 for unit in ${result[@]}; do
c194ffc1
AV
281 [ "${unit##*.}" = "service" ] || unit="${unit}.service"
282 ln -s "/usr/lib/systemd/system/${unit}" \
283 "${rootfs_path}/etc/systemd/system/multi-user.target.wants/"
284 done
285fi
286
287if [ ${#disable_units[@]} -gt 0 ]; then
288 split_string ${disable_units}
289 for unit in ${result[@]}; do
290 [ "${unit##*.}" = "service" ] || unit="${unit}.service"
291 ln -s /dev/null "${rootfs_path}/etc/systemd/system/${unit}"
012f591a
JL
292 done
293fi
294
d0800999
JL
295if [ -n "${root_passwd}" ]; then
296 echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd
297fi
298
21ca73b9 299cat << EOF
c194ffc1 300Arch Linux container ${name} is successfully created! The configuration is
21ca73b9 301stored in ${config_path}/config. Please refer to https://wiki.archlinux.org for
c194ffc1 302information about configuring Arch Linux.
21ca73b9 303EOF