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
+ echo "You might want the \"debian\" template instead." 1>&2
+ exit 1
fi
+set -e
+set -u
+
# Make sure the usual locations are in PATH
-export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
+export PATH=/usr/sbin:/usr/bin:/sbin:/bin:$PATH
export GREP_OPTIONS=""
usage() {
DEBIAN_MIRROR="http://mirror.mythic-beasts.com/debian/"
DEBIAN_RELEASE="jessie"
+disable_initscripts() {
+ cat <<EOF > "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
+#!/bin/sh
+
+exit 101
+EOF
+ chmod 755 "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
+}
+
+enable_initscripts() {
+ if [ -e "${LXC_ROOTFS}/usr/sbin/policy-rc.d" ]; then
+ rm "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
+ fi
+}
+
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;;
+ -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
+sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config"
+sed -i -e '4,$d' "${LXC_PATH}/config"
-cat <<EOF >> ${LXC_PATH}/config
+cat <<EOF >> "${LXC_PATH}/config"
# Useful includes
lxc.include = /usr/share/lxc/config/debian.common.conf
EOF
# add back in the auto foo
-cat "${LXC_PATH}/config-auto" >> ${LXC_PATH}/config
-rm ${LXC_PATH}/config-auto
+cat "${LXC_PATH}/config-auto" >> "${LXC_PATH}/config"
+rm "${LXC_PATH}/config-auto"
-mkdir ${LXC_PATH}/bin
-cat <<EOF > ${LXC_PATH}/bin/mknod
+mkdir "${LXC_PATH}/bin"
+cat <<EOF > "${LXC_PATH}/bin/mknod"
#!/bin/sh
exec touch "\$1"
EOF
-chmod 755 ${LXC_PATH}/bin/mknod
+chmod 755 "${LXC_PATH}/bin/mknod"
-export PATH=${LXC_PATH}/bin:$PATH
+export PATH="${LXC_PATH}/bin:$PATH"
-debootstrap --foreign --include debian-archive-keyring,ifupdown,isc-dhcp-client,locales $DEBIAN_RELEASE ${LXC_ROOTFS} $DEBIAN_MIRROR
+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
+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
+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)
+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 .)
+(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)
+(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
+ 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
+for dev in null 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
+# set /proc/cmdline to something
+echo "debootstrapping" > "${LXC_ROOTFS}/proc/cmdline"
# and disable initscripts
-cat <<EOF > ${LXC_ROOTFS}/usr/sbin/policy-rc.d
-#!/bin/sh
-
-exit 101
-EOF
+disable_initscripts
# and run the second stage
-chroot ${LXC_ROOTFS} /debootstrap/debootstrap --second-stage
+chroot "${LXC_ROOTFS}" /debootstrap/debootstrap --second-stage
+
+# make sure that initscripts are still disabled
+disable_initscripts
# configure locales
lang=en_GB.UTF-8
enc=${LANG#*.}
fi
-cat >> ${LXC_ROOTFS}/etc/locale.gen <<EOF
+cat >> "${LXC_ROOTFS}/etc/locale.gen" <<EOF
$lang $enc
EOF
-chroot ${LXC_ROOTFS} /usr/sbin/locale-gen $lang $enc
-chroot ${LXC_ROOTFS} /usr/sbin/update-locale LANG=$LANG
+chroot "${LXC_ROOTFS}" /usr/sbin/locale-gen $lang $enc
+chroot "${LXC_ROOTFS}" /usr/sbin/update-locale LANG=$LANG
# configure timezone
if [ -f /etc/timezone ]; then
- cat /etc/timezone > ${LXC_ROOTFS}/etc/timezone
+ cat /etc/timezone > "${LXC_ROOTFS}/etc/timezone"
elif [ -f /etc/sysconfig/clock ]; then
. /etc/sysconfig/clock
- echo $ZONE > ${LXC_ROOTFS}/etc/timezone
+ echo $ZONE > "${LXC_ROOTFS}/etc/timezone"
fi
-chroot ${LXC_ROOTFS} dpkg-reconfigure -f noninteractive tzdata
+chroot "${LXC_ROOTFS}" dpkg-reconfigure -f noninteractive tzdata
# "setup" networking
NETWORK_FILE=/etc/network/interfaces
-if [ -e ${LXC_ROOTFS}/etc/network/interfaces.d ]; then
+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/*
+
+# set the hostname
+echo $LXC_NAME > "${LXC_ROOTFS}/etc/hostname"
+
+SECURITY=""
+if [ "$DEBIAN_RELEASE" != "sid" ] && [ "$DEBIAN_RELEASE" != "unstable" ]; then
+ SECURITY="deb http://security.debian.org/ $DEBIAN_RELEASE/updates main"
+fi
+
# setup sources.list
-cat <<EOF > ${LXC_ROOTFS}/etc/apt/sources.list
+cat <<EOF > "${LXC_ROOTFS}/etc/apt/sources.list"
deb $DEBIAN_MIRROR $DEBIAN_RELEASE main
-deb http://security.debian.org/ $DEBIAN_RELEASE/updates main
+$SECURITY
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
+# disable bits of systemd / initrd that break things
+chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f checkroot.sh disable > /dev/null 2>&1 || true
+chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f umountfs disable > /dev/null 2>&1 || true
+chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f hwclock.sh disable > /dev/null 2>&1 || true
+chroot "${LXC_ROOTFS}" /usr/sbin/update-rc.d -f hwclockfirst.sh disable > /dev/null 2>&1 || true
+
+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
+
+if [ -e "${LXC_ROOTFS}/lib/systemd/system/systemd-journald-audit.socket" ]; then
+ touch "${LXC_ROOTFS}/etc/systemd/system/systemd-journald-audit.socket"
fi
-cat <<EOF >> ${LXC_ROOTFS}${NETWORK_FILE}
+cat <<EOF >> "${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
+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
+[ -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
+for dev in null 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
+ fname="$(basename $file)"
+ umount "${LXC_ROOTFS}/proc/$fname"
+ rm "${LXC_ROOTFS}/proc/$fname"
done
+enable_initscripts
+
+rm -r "${LXC_PATH}/bin"
+
+cat <<EOF
+You have successfully created a new debian container, ${LXC_NAME} running ${DEBIAN_RELEASE}.
+
+You should start the new container, and use:
+
+ lxc-attach -n ${LXC_NAME} -- su -
+
+To create a user account / set the root password.
+
+Note, by default, it's likely only to be the console that can login as root, so that'd be:
+
+ lxc-console -n ${LXC_NAME} -t 0
+EOF
+
exit 0