More systemd changes
[lxc-debian-unprivileged.git] / templates / lxc-debian-unprivileged
1 #!/bin/bash
2
3 # lxc template for debootstrapping in userns
4
5 # Authors:
6 # Brett Parker <iDunno@sommitrealweird.co.uk>
7
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22 MAPPED=no
23
24 # Only support usage in userns.
25 for arg in "$@"; do
26     [ "$arg" = "--" ] && break
27     if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
28         MAPPED=yes
29     fi
30 done
31
32 if [ "$MAPPED" == "no" ]; then
33     echo "This template can only be used for unprivileged containers." 1>&2
34     echo "You might want the \"debian\" template instead." 1|&2
35 fi
36
37 # Make sure the usual locations are in PATH
38 export PATH=/usr/sbin:/usr/bin:/sbin:/bin:$PATH
39 export GREP_OPTIONS=""
40
41 usage() {
42     cat <<EOF
43 LXC debootstrap in user namespace for unprivileged containers
44
45 Special arguments:
46 [ -h | --help ]: Print this help message and exit.
47
48 Required arguments:
49 [ -r | --release <release> ]: The debian release, e.g. jessie or stretch.
50
51 Optional arguments:
52 [ -m | --mirror <mirrorurl> ]: The debian mirror to user
53 EOF
54     return 0
55 }
56
57 options=$(getopt -o r:m:h -l release:,mirror:,help,mapped-uid:,mapped-gid:,name:,path:,rootfs: -- "$@")
58
59 if [ $? -ne 0 ]; then
60     usage
61     exit 1
62 fi
63
64 eval set -- "$options"
65
66 DEBIAN_MIRROR="http://mirror.mythic-beasts.com/debian/"
67 DEBIAN_RELEASE="jessie"
68
69 disable_initscripts() {
70     cat <<EOF > "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
71 #!/bin/sh
72
73 exit 101
74 EOF
75     chmod 755 "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
76 }
77
78 enable_initscripts() {
79     if [ -e "${LXC_ROOTFS}/usr/sbin/policy-rc.d" ]; then
80         rm "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
81     fi
82 }
83
84 while :; do
85     case "$1" in
86         -h|--help)      usage && exit 1;;
87         -r|--release)   DEBIAN_RELEASE="$2"; shift 2;;
88         -m|--mirror)    DEBIAN_MIRROR="$2"; shift 2;;
89         --mapped-uid)   MAPPED_UID="$2"; shift 2;;
90         --mapped-gid)   MAPPED_GID="$2"; shift 2;;
91         --name)         LXC_NAME="$2"; shift 2;;
92         --path)         LXC_PATH="$2"; shift 2;;
93         --rootfs)       LXC_ROOTFS="$2"; shift 2;;
94         *)              break;;
95     esac
96 done
97
98 # rewrite the default config file
99
100 sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config"
101 sed -i -e '4,$d' "${LXC_PATH}/config"
102
103 cat <<EOF >> "${LXC_PATH}/config"
104
105 # Useful includes
106 lxc.include = /usr/share/lxc/config/debian.common.conf
107 lxc.include = /usr/share/lxc/config/debian.userns.conf
108
109 # Set our hostname
110 lxc.utsname = $LXC_NAME
111
112 # Automatic configuration
113 EOF
114
115 # add back in the auto foo
116 cat "${LXC_PATH}/config-auto" >> "${LXC_PATH}/config"
117 rm "${LXC_PATH}/config-auto"
118
119 mkdir "${LXC_PATH}/bin"
120 cat <<EOF > "${LXC_PATH}/bin/mknod"
121 #!/bin/sh
122
123 exec touch "\$1"
124 EOF
125
126 chmod 755 "${LXC_PATH}/bin/mknod"
127
128 export PATH="${LXC_PATH}/bin:$PATH"
129
130 debootstrap --foreign --include debian-archive-keyring,ifupdown,isc-dhcp-client,locales,openssh-server $DEBIAN_RELEASE "${LXC_ROOTFS}" $DEBIAN_MIRROR
131
132 # now totally skip that check in the new root, because it sucks.
133 sed -i -e 's#check_sane_mount () {#check_sane_mount () {\n\treturn 0#;' "${LXC_ROOTFS}/debootstrap/functions"
134
135 # and stop it from bothering to try to setup proc
136 sed -i -e 's#setup_proc () {#setup_proc () {\n\treturn 0#;' "${LXC_ROOTFS}/debootstrap/functions"
137
138 keyring_dpkg=$(sed -ne "/^debian-archive-keyring/ { s#.* ##; p; }" "${LXC_ROOTFS}/debootstrap/debpaths")
139 # and unpack debian-archive-keyring, because we'll need that
140 (cd "${LXC_ROOTFS}" && dpkg-deb -x ".$keyring_dpkg" .)
141
142 # replace the tar containing devices with something that doesn't contain any
143 (cd "$LXC_ROOTFS/debootstrap" && rm devices.tar.gz && tar czvf devices.tar.gz --files-from=/dev/null)
144
145 # and mount a shitload of things for fun and profit...
146 for file in /var/lib/lxcfs/proc/*; do
147     fname="$(basename $file)"
148     touch "${LXC_ROOTFS}/proc/$fname"
149     mount -n -o bind "$file" "${LXC_ROOTFS}/proc/$fname"
150 done
151
152 for dev in null random urandom; do
153     touch "${LXC_ROOTFS}/dev/$dev"
154     mount -n -o bind /dev/$dev "${LXC_ROOTFS}/dev/$dev"
155 done
156
157 # set /proc/cmdline to something
158 echo "debootstrapping" > "${LXC_ROOTFS}/proc/cmdline"
159
160 # and disable initscripts
161 disable_initscripts
162
163 # and run the second stage
164 chroot "${LXC_ROOTFS}" /debootstrap/debootstrap --second-stage
165
166 # make sure that initscripts are still disabled
167 disable_initscripts
168
169 # configure locales
170 lang=en_GB.UTF-8
171 enc=UTF-8
172 if [ ! -z "$LANG" ]; then
173     lang=${LANG}
174     enc=${LANG#*.}
175 fi
176
177 cat >> "${LXC_ROOTFS}/etc/locale.gen" <<EOF
178 $lang $enc
179 EOF
180
181 chroot "${LXC_ROOTFS}" /usr/sbin/locale-gen $lang $enc
182 chroot "${LXC_ROOTFS}" /usr/sbin/update-locale LANG=$LANG
183
184 # configure timezone
185 if [ -f /etc/timezone ]; then
186     cat /etc/timezone > "${LXC_ROOTFS}/etc/timezone"
187 elif [ -f /etc/sysconfig/clock ]; then
188     . /etc/sysconfig/clock
189     echo $ZONE > "${LXC_ROOTFS}/etc/timezone"
190 fi
191 chroot "${LXC_ROOTFS}" dpkg-reconfigure -f noninteractive tzdata
192
193 # "setup" networking
194 NETWORK_FILE=/etc/network/interfaces
195 if [ -e "${LXC_ROOTFS}/etc/network/interfaces.d" ]; then
196     NETWORK_FILE=/etc/network/interfaces.d/eth0
197 fi
198
199 # remove some interesting breakages in pam for unpriv foo
200 sed -i -e 's#^\(session.*required.*pam_loginuid.so\)#\#\1#;' "${LXC_ROOTFS}"/etc/pam.d/*
201
202 # set the hostname
203 echo $LXC_NAME > "${LXC_ROOTFS}/etc/hostname"
204
205 # setup sources.list
206 cat <<EOF > "${LXC_ROOTFS}/etc/apt/sources.list"
207 deb $DEBIAN_MIRROR $DEBIAN_RELEASE main
208 deb http://security.debian.org/ $DEBIAN_RELEASE/updates main
209 EOF
210
211 # disable bits of systemd that we hates
212 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f checkroot.sh disable > /dev/null 2>&1
213 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f umountfs disable > /dev/null 2>&1
214 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f hwclock.sh disable > /dev/null 2>&1
215 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f hwclockfirst.sh disable > /dev/null 2>&1
216
217 if [ -e "${LXC_ROOTFS}/etc/systemd/system/" ]; then
218     touch "${LXC_ROOTFS}/etc/systemd/system/systemd-setup-dgram-qlen.service"
219     touch "${LXC_ROOTFS}/etc/systemd/system/dev-hugepages.mount"
220     touch "${LXC_ROOTFS}/etc/systemd/system/udev.service"
221     touch "${LXC_ROOTFS}/etc/systemd/system/systemd-udevd.service"
222     chroot "${LXC_ROOTFS}" systemctl set-default multi-user.target
223     chroot "${LXC_ROOTFS}" ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
224 fi
225
226 if [ -e "${LXC_ROOTFS}/lib/systemd/system/systemd-journald-audit.socket" ]; then
227     touch "${LXC_ROOTFS}/etc/systemd/system/systemd-journald-audit.socket"
228 fi
229
230 cat <<EOF >> "${LXC_ROOTFS}${NETWORK_FILE}"
231 auto eth0
232 iface eth0 inet dhcp
233 EOF
234
235 # and update to the latest security
236 chroot "${LXC_ROOTFS}" apt-get update
237 chroot "${LXC_ROOTFS}" apt-get -y upgrade
238
239 # if we're all good here, unmount things and clean up
240 [ -e "${LXC_ROOTFS}/usr/sbin/policy-rc.d" ] && rm "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
241 rm "${LXC_ROOTFS}/proc/cmdline"
242
243 for dev in null random urandom; do
244     umount "${LXC_ROOTFS}/dev/$dev"
245     rm "${LXC_ROOTFS}/dev/$dev"
246 done
247
248 for file in /var/lib/lxcfs/proc/*; do
249     fname="$(basename $file)"
250     umount "${LXC_ROOTFS}/proc/$fname"
251     rm "${LXC_ROOTFS}/proc/$fname"
252 done
253
254 enable_initscripts
255
256 rm -r "${LXC_PATH}/bin"
257
258 exit 0