#!/bin/bash # lxc template for debootstrapping in userns # Authors: # Brett Parker # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA MAPPED=no # Only support usage in userns. for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then MAPPED=yes fi done if [ "$MAPPED" == "no" ]; then echo "This template can only be used for unprivileged containers." 1>&2 echo "You might want the \"debian\" template instead." 1|&2 fi # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin export GREP_OPTIONS="" usage() { cat < ]: The debian release, e.g. jessie or stretch. Optional arguments: [ -m | --mirror ]: The debian mirror to user EOF return 0 } options=$(getopt -o r:m:h -l release:,mirror:,help,mapped-uid:,mapped-gid:,name:,path:,rootfs: -- "$@") if [ $? -ne 0 ]; then usage exit 1 fi eval set -- "$options" DEBIAN_MIRROR="http://mirror.mythic-beasts.com/debian/" DEBIAN_RELEASE="jessie" while :; do case "$1" in -h|--help) usage && exit 1;; -r|--release) DEBIAN_RELEASE=$2; shift 2;; -m|--mirror) DEBIAN_MIRROR=$2; shift 2;; --mapped-uid) MAPPED_UID=$2; shift 2;; --mapped-gid) MAPPED_GID=$2; shift 2;; --name) LXC_NAME=$2; shift 2;; --path) LXC_PATH=$2; shift 2;; --rootfs) LXC_ROOTFS=$2; shift 2;; *) break;; esac done echo "Mapped UID: $MAPPED_UID" echo "Mapped GID: $MAPPED_GID" echo "RootFS: $LXC_ROOTFS" echo "Name: $LXC_NAME" echo "Path: $LXC_PATH" # rewrite the default config file sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" ${LXC_PATH}/config sed -i -e '4,$d' ${LXC_PATH}/config cat <> ${LXC_PATH}/config # Useful includes lxc.include = /usr/share/lxc/config/debian.common.conf lxc.include = /usr/share/lxc/config/debian.userns.conf # Set our hostname lxc.utsname = $LXC_NAME # Automatic configuration EOF # add back in the auto foo cat "${LXC_PATH}/config-auto" >> ${LXC_PATH}/config rm ${LXC_PATH}/config-auto mkdir ${LXC_PATH}/bin cat < ${LXC_PATH}/bin/mknod #!/bin/sh exec touch "\$1" EOF chmod 755 ${LXC_PATH}/bin/mknod export PATH=${LXC_PATH}/bin:$PATH debootstrap --foreign --include debian-archive-keyring,ifupdown,isc-dhcp-client,locales,openssh-server $DEBIAN_RELEASE ${LXC_ROOTFS} $DEBIAN_MIRROR # now totally skip that check in the new root, because it sucks. sed -i -e 's#check_sane_mount () {#check_sane_mount () {\n\treturn 0#;' ${LXC_ROOTFS}/debootstrap/functions # and stop it from bothering to try to setup proc sed -i -e 's#setup_proc () {#setup_proc () {\n\treturn 0#;' ${LXC_ROOTFS}/debootstrap/functions keyring_dpkg=$(sed -ne "/^debian-archive-keyring/ { s#.* ##; p; }" ${LXC_ROOTFS}/debootstrap/debpaths) # and unpack debian-archive-keyring, because we'll need that (cd ${LXC_ROOTFS} && dpkg-deb -x .$keyring_dpkg .) # replace the tar containing devices with something that doesn't contain any (cd $LXC_ROOTFS/debootstrap && rm devices.tar.gz && tar czvf devices.tar.gz --files-from=/dev/null) # and mount a shitload of things for fun and profit... for file in /var/lib/lxcfs/proc/*; do fname=$(basename $file) touch ${LXC_ROOTFS}/proc/$fname mount -n -o bind $file ${LXC_ROOTFS}/proc/$fname done for dev in random urandom; do touch ${LXC_ROOTFS}/dev/$dev mount -n -o bind /dev/$dev ${LXC_ROOTFS}/dev/$dev done # set /proc/cmdline to something silly echo "debootstrapping - hahaha" > ${LXC_ROOTFS}/proc/cmdline # and disable initscripts cat < ${LXC_ROOTFS}/usr/sbin/policy-rc.d #!/bin/sh exit 101 EOF # and run the second stage chroot ${LXC_ROOTFS} /debootstrap/debootstrap --second-stage # configure locales lang=en_GB.UTF-8 enc=UTF-8 if [ ! -z "$LANG" ]; then lang=${LANG} enc=${LANG#*.} fi cat >> ${LXC_ROOTFS}/etc/locale.gen < ${LXC_ROOTFS}/etc/timezone elif [ -f /etc/sysconfig/clock ]; then . /etc/sysconfig/clock echo $ZONE > ${LXC_ROOTFS}/etc/timezone fi chroot ${LXC_ROOTFS} dpkg-reconfigure -f noninteractive tzdata # "setup" networking NETWORK_FILE=/etc/network/interfaces if [ -e ${LXC_ROOTFS}/etc/network/interfaces.d ]; then NETWORK_FILE=/etc/network/interfaces.d/eth0 fi # remove some interesting breakages in pam for unpriv foo sed -i -e 's#^\(session.*required.*pam_loginuid.so\)#\#\1#;' ${LXC_ROOTFS}/etc/pam.d/* # setup sources.list cat < ${LXC_ROOTFS}/etc/apt/sources.list deb $DEBIAN_MIRROR $DEBIAN_RELEASE main deb http://security.debian.org/ $DEBIAN_RELEASE/updates main EOF # disable bits of systemd that we hates chroot $LXC_ROOTFS /usr/sbin/update-rc.d -f checkroot.sh disable > /dev/null 2>&1 chroot $LXC_ROOTFS /usr/sbin/update-rc.d -f umountfs disable > /dev/null 2>&1 chroot $LXC_ROOTFS /usr/sbin/update-rc.d -f hwclock.sh disable > /dev/null 2>&1 chroot $LXC_ROOTFS /usr/sbin/update-rc.d -f hwclockfirst.sh disable > /dev/null 2>&1 if [ -e ${LXC_ROOTFS}/etc/systemd/system/ ]; then touch ${LXC_ROOTFS}/etc/systemd/system/systemd-setup-dgram-qlen.service touch ${LXC_ROOTFS}/etc/systemd/system/dev-hugepages.mount touch ${LXC_ROOTFS}/etc/systemd/system/udev.service touch ${LXC_ROOTFS}/etc/systemd/system/systemd-udevd.service chroot ${LXC_ROOTFS} systemctl set-default multi-user.target chroot ${LXC_ROOTFS} ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target fi cat <> ${LXC_ROOTFS}${NETWORK_FILE} auto eth0 iface eth0 inet dhcp EOF # and update to the latest security chroot ${LXC_ROOTFS} apt-get update chroot ${LXC_ROOTFS} apt-get -y upgrade # if we're all good here, unmount things and clean up [ -e ${LXC_ROOTFS}/usr/sbin/policy-rc.d ] && rm ${LXC_ROOTFS}/usr/sbin/policy-rc.d rm ${LXC_ROOTFS}/proc/cmdline for dev in random urandom; do umount ${LXC_ROOTFS}/dev/$dev rm ${LXC_ROOTFS}/dev/$dev done for file in /var/lib/lxcfs/proc/*; do fname=$(basename $file) umount ${LXC_ROOTFS}/proc/$fname rm ${LXC_ROOTFS}/proc/$fname done exit 0