3 # lxc template for debootstrapping in userns
6 # Brett Parker <iDunno@sommitrealweird.co.uk>
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.
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.
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
24 # Only support usage in userns.
26 [ "$arg" = "--" ] && break
27 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
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
41 # Make sure the usual locations are in PATH
42 export PATH=/usr/sbin:/usr/bin:/sbin:/bin:$PATH
43 export GREP_OPTIONS=""
47 LXC debootstrap in user namespace for unprivileged containers
50 [ -h | --help ]: Print this help message and exit.
53 [ -r | --release <release> ]: The debian release, e.g. jessie or stretch.
56 [ -m | --mirror <mirrorurl> ]: The debian mirror to user
61 options=$(getopt -o r:m:h -l release:,mirror:,help,mapped-uid:,mapped-gid:,name:,path:,rootfs: -- "$@")
68 eval set -- "$options"
70 DEBIAN_MIRROR="http://mirror.mythic-beasts.com/debian/"
71 DEBIAN_RELEASE="jessie"
73 disable_initscripts() {
74 cat <<EOF > "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
79 chmod 755 "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
82 enable_initscripts() {
83 if [ -e "${LXC_ROOTFS}/usr/sbin/policy-rc.d" ]; then
84 rm "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
90 -h|--help) usage && exit 1;;
91 -r|--release) DEBIAN_RELEASE="$2"; shift 2;;
92 -m|--mirror) DEBIAN_MIRROR="$2"; shift 2;;
93 --mapped-uid) MAPPED_UID="$2"; shift 2;;
94 --mapped-gid) MAPPED_GID="$2"; shift 2;;
95 --name) LXC_NAME="$2"; shift 2;;
96 --path) LXC_PATH="$2"; shift 2;;
97 --rootfs) LXC_ROOTFS="$2"; shift 2;;
102 # rewrite the default config file
104 sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config"
105 sed -i -e '4,$d' "${LXC_PATH}/config"
107 cat <<EOF >> "${LXC_PATH}/config"
110 lxc.include = /usr/share/lxc/config/debian.common.conf
111 lxc.include = /usr/share/lxc/config/debian.userns.conf
114 lxc.utsname = $LXC_NAME
116 # Automatic configuration
119 # add back in the auto foo
120 cat "${LXC_PATH}/config-auto" >> "${LXC_PATH}/config"
121 rm "${LXC_PATH}/config-auto"
123 mkdir "${LXC_PATH}/bin"
124 cat <<EOF > "${LXC_PATH}/bin/mknod"
130 chmod 755 "${LXC_PATH}/bin/mknod"
132 export PATH="${LXC_PATH}/bin:$PATH"
134 debootstrap --foreign --include debian-archive-keyring,ifupdown,isc-dhcp-client,locales,openssh-server $DEBIAN_RELEASE "${LXC_ROOTFS}" $DEBIAN_MIRROR
136 # now totally skip that check in the new root, because it sucks.
137 sed -i -e 's#check_sane_mount () {#check_sane_mount () {\n\treturn 0#;' "${LXC_ROOTFS}/debootstrap/functions"
139 # and stop it from bothering to try to setup proc
140 sed -i -e 's#setup_proc () {#setup_proc () {\n\treturn 0#;' "${LXC_ROOTFS}/debootstrap/functions"
142 keyring_dpkg=$(sed -ne "/^debian-archive-keyring/ { s#.* ##; p; }" "${LXC_ROOTFS}/debootstrap/debpaths")
143 # and unpack debian-archive-keyring, because we'll need that
144 (cd "${LXC_ROOTFS}" && dpkg-deb -x ".$keyring_dpkg" .)
146 # replace the tar containing devices with something that doesn't contain any
147 (cd "$LXC_ROOTFS/debootstrap" && rm devices.tar.gz && tar czvf devices.tar.gz --files-from=/dev/null)
149 # and mount a shitload of things for fun and profit...
150 for file in /var/lib/lxcfs/proc/*; do
151 fname="$(basename $file)"
152 touch "${LXC_ROOTFS}/proc/$fname"
153 mount -n -o bind "$file" "${LXC_ROOTFS}/proc/$fname"
156 for dev in null random urandom; do
157 touch "${LXC_ROOTFS}/dev/$dev"
158 mount -n -o bind /dev/$dev "${LXC_ROOTFS}/dev/$dev"
161 # set /proc/cmdline to something
162 echo "debootstrapping" > "${LXC_ROOTFS}/proc/cmdline"
164 # and disable initscripts
167 # and run the second stage
168 chroot "${LXC_ROOTFS}" /debootstrap/debootstrap --second-stage
170 # make sure that initscripts are still disabled
176 if [ ! -z "$LANG" ]; then
181 cat >> "${LXC_ROOTFS}/etc/locale.gen" <<EOF
185 chroot "${LXC_ROOTFS}" /usr/sbin/locale-gen $lang $enc
186 chroot "${LXC_ROOTFS}" /usr/sbin/update-locale LANG=$LANG
189 if [ -f /etc/timezone ]; then
190 cat /etc/timezone > "${LXC_ROOTFS}/etc/timezone"
191 elif [ -f /etc/sysconfig/clock ]; then
192 . /etc/sysconfig/clock
193 echo $ZONE > "${LXC_ROOTFS}/etc/timezone"
195 chroot "${LXC_ROOTFS}" dpkg-reconfigure -f noninteractive tzdata
198 NETWORK_FILE=/etc/network/interfaces
199 if [ -e "${LXC_ROOTFS}/etc/network/interfaces.d" ]; then
200 NETWORK_FILE=/etc/network/interfaces.d/eth0
203 # remove some interesting breakages in pam for unpriv foo
204 sed -i -e 's#^\(session.*required.*pam_loginuid.so\)#\#\1#;' "${LXC_ROOTFS}"/etc/pam.d/*
207 echo $LXC_NAME > "${LXC_ROOTFS}/etc/hostname"
210 if [ "$DEBIAN_RELEASE" != "sid" ] && [ "$DEBIAN_RELEASE" != "unstable" ]; then
211 SECURITY="deb http://security.debian.org/ $DEBIAN_RELEASE/updates main"
215 cat <<EOF > "${LXC_ROOTFS}/etc/apt/sources.list"
216 deb $DEBIAN_MIRROR $DEBIAN_RELEASE main
220 # disable bits of systemd / initrd that break things
221 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f checkroot.sh disable > /dev/null 2>&1 || true
222 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f umountfs disable > /dev/null 2>&1 || true
223 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f hwclock.sh disable > /dev/null 2>&1 || true
224 chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f hwclockfirst.sh disable > /dev/null 2>&1 || true
226 if [ -e "${LXC_ROOTFS}/etc/systemd/system/" ]; then
227 touch "${LXC_ROOTFS}/etc/systemd/system/systemd-setup-dgram-qlen.service"
228 touch "${LXC_ROOTFS}/etc/systemd/system/dev-hugepages.mount"
229 touch "${LXC_ROOTFS}/etc/systemd/system/udev.service"
230 touch "${LXC_ROOTFS}/etc/systemd/system/systemd-udevd.service"
231 chroot "${LXC_ROOTFS}" systemctl set-default multi-user.target
232 chroot "${LXC_ROOTFS}" ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
235 if [ -e "${LXC_ROOTFS}/lib/systemd/system/systemd-journald-audit.socket" ]; then
236 touch "${LXC_ROOTFS}/etc/systemd/system/systemd-journald-audit.socket"
239 cat <<EOF >> "${LXC_ROOTFS}${NETWORK_FILE}"
244 # and update to the latest security
245 chroot "${LXC_ROOTFS}" apt-get update
246 chroot "${LXC_ROOTFS}" apt-get -y upgrade
248 # if we're all good here, unmount things and clean up
249 [ -e "${LXC_ROOTFS}/usr/sbin/policy-rc.d" ] && rm "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
250 rm "${LXC_ROOTFS}/proc/cmdline"
252 for dev in null random urandom; do
253 umount "${LXC_ROOTFS}/dev/$dev"
254 rm "${LXC_ROOTFS}/dev/$dev"
257 for file in /var/lib/lxcfs/proc/*; do
258 fname="$(basename $file)"
259 umount "${LXC_ROOTFS}/proc/$fname"
260 rm "${LXC_ROOTFS}/proc/$fname"
265 rm -r "${LXC_PATH}/bin"