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=/usr/sbin:/usr/bin:/sbin:/bin:$PATH
export GREP_OPTIONS=""
Optional arguments:
[ -m | --mirror <mirrorurl> ]: The debian mirror to user
+[ -n | --network <networkspec> ]: How to configure networking
+
+Network spec:
+ <type>[,options]
+
+ type is one of:
+ dhcp4: v4 dhcp will be enabled.
+ dhcp6: v6 dhcp will be enabled.
+ dhcp: v4 and v6 dhcp will be enabled.
+ static: no dhcp will be enabled
+
+ options:
+ this is a , seperated list, and sets up static assignments for v4 or v6,
+ regardless of type.
+ The order of arguments is
+ staticv4/staticnetmask
+ staticv6/staticv6netmask
+ gateway
+ v6gateway
+
+ examples:
+
+ --network dhcp4 (default)
+ --network dhcp6 (v6 dhcp)
+ --network dhcp (v4 and v6 dhcp)
+ --network dhcp4,,2001:db8:1234:5678::1/64 (dhcp4 and static v6 address)
+ --network static,,2001:db8:1234:5678::5/64,,fe80::1 (static v6)
+ --network static,192.0.2.15/24,,192.0.2.1 (static v4)
+
EOF
return 0
}
-options=$(getopt -o r:m:h -l release:,mirror:,help,mapped-uid:,mapped-gid:,name:,path:,rootfs: -- "$@")
+options=$(getopt -o r:m:n:h -l release:,mirror:,network:,help,mapped-uid:,mapped-gid:,name:,path:,rootfs: -- "$@")
if [ $? -ne 0 ]; then
usage
eval set -- "$options"
-DEBIAN_MIRROR="http://mirror.mythic-beasts.com/debian/"
+DEBIAN_MIRROR_DEFAULT="http://mirror.sommitrealweird.co.uk/debian/"
+DEBIAN_MIRROR=$DEBIAN_MIRROR_DEFAULT
DEBIAN_RELEASE="jessie"
+NETWORK_CONFIG=""
disable_initscripts() {
cat <<EOF > "${LXC_ROOTFS}/usr/sbin/policy-rc.d"
-h|--help) usage && exit 1;;
-r|--release) DEBIAN_RELEASE="$2"; shift 2;;
-m|--mirror) DEBIAN_MIRROR="$2"; shift 2;;
+ -n|--network) NETWORK_CONFIG="$2"; shift 2;;
--mapped-uid) MAPPED_UID="$2"; shift 2;;
--mapped-gid) MAPPED_GID="$2"; shift 2;;
--name) LXC_NAME="$2"; shift 2;;
esac
done
+if [ "$DEBIAN_RELEASE" == "squeeze" ] || [ "$DEBIAN_RELEASE" == "lenny" ] || [ "$DEBIAN_RELEASE" == "etch" ]; then
+ if [ "$DEBIAN_MIRROR" == "$DEBIAN_MIRROR_DEFAULT" ]; then
+ DEBIAN_MIRROR="http://archive.debian.org/debian/"
+ fi
+fi
+
+INTERFACE_DEFAULTS="auto eth0
+iface eth0 inet dhcp"
+
+generate_network_config() {
+ if [ "$NETWORK_CONFIG" == "" ]; then
+ echo "$INTERFACE_DEFAULTS"
+ return 0
+ fi
+
+ ETH0_HEADER="auto eth0"
+ ETH0_IPV4=""
+ ETH0_IPV6=""
+
+ echo "auto eth0"
+ # see if there's a type
+ network_type=${NETWORK_CONFIG/,*}
+ other_params=${NETWORK_CONFIG#*,}
+
+ v4_configured=no
+ v6_configured=no
+
+ if [ "$network_type" == "dhcp" ]; then
+ ETH0_IPV4="iface eth0 inet dhcp"
+ ETH0_IPV6="iface eth0 inet6 dhcp"
+ v4_configured=yes
+ v6_configured=yes
+ elif [ "$network_type" == "dhcp4" ]; then
+ ETH0_IPV4="iface eth0 inet dhcp"
+ v4_configured=yes
+ elif [ "$network_type" == "dhcp6" ]; then
+ ETH0_IPV6="iface eth0 inet6 dhcp"
+ v6_configured=yes
+ elif [ "$network_type" != "static" ]; then
+ echo "Unknown network type: $network_type" 1>&2
+ echo 1>&2
+ usage 1>&2
+ exit 1
+ fi
+
+ [ "$network_type" == "$other_params" ] && return 0
+
+ v4_static=${other_params/,*}
+ other_params=${other_params#*,}
+
+ if [ "$v4_static" != "" ]; then
+ if [ "$v4_configured" == "yes" ]; then
+ echo "Both v4 DHCP and Static - giving up." 1>&2
+ echo 1>&2
+ usage 1>&2
+ exit 1
+ fi
+ fi
+
+ if [ "$v4_static" == "$other_params" ]; then
+ if [ "$v4_static" != "" ]; then
+ echo "iface eth0 inet static"
+ echo " address $v4_static"
+ fi
+ fi
+
+ v6_static=${other_params/,*}
+ other_params=${other_params#*,}
+
+ if [ "$v6_static" != "" ]; then
+ if [ "$v6_configured" == "yes" ]; then
+ echo "Both v6 DHCP and Static - giving up." 1>&2
+ echo 1>&2
+ usage 1>&2
+ exit 1
+ fi
+ fi
+
+ if [ "$v6_static" == "$other_params" ]; then
+ if [ "$v4_static" ]; then
+ echo "iface eth0 inet static"
+ echo " address $v4_static"
+ echo
+ fi
+
+ echo "iface eth0 inet6 static"
+ echo " address $v6_static"
+
+ return 0
+ fi
+
+ v4_gateway=${other_params/,*}
+ other_params=${other_params#*,}
+
+ if [ "$v4_gateway" == "$other_params" ]; then
+ if [ "$v4_static" != "" ]; then
+ echo "iface eth0 inet static"
+ echo " address $v4_static"
+ [ "$v4_gateway" != "" ] && echo " gateway $v4_gateway"
+
+ if [ "$v6_static" != "" ]; then
+ echo "iface eth0 inet6 static"
+ echo " address $v6_static"
+ fi
+
+ return 0
+ fi
+
+ if [ "$v4_configured" == "yes" ]; then
+ echo "DHCP and static gateway not supported, giving up." 1>&2
+ echo 1>&2
+ usage 1>&2
+ exit 1
+ fi
+ fi
+
+ v6_gateway=${other_params/,*}
+
+ if [ "$v4_static" != "" ]; then
+ echo "iface eth0 inet static"
+ echo " address $v4_static"
+ [ "$v4_gateway" != "" ] && echo " gateway $v4_gateway"
+ echo
+ fi
+
+ if [ "$v6_static" != "" ]; then
+ echo "iface eth0 inet6 static"
+ echo " address $v6_static"
+ [ "$v6_gateway" != "" ] && echo " gateway $v6_gateway"
+ fi
+
+ return 0
+}
+
+INTERFACE_DETAILS="$(generate_network_config)"
+
# rewrite the default config file
sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config"
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
+# Set hostname
+lxc.uts.name = $LXC_NAME
# Automatic configuration
EOF
cat <<EOF > "${LXC_PATH}/bin/mknod"
#!/bin/sh
-exec touch "\$1"
+# look for the first argument that looks like a path
+for i do
+ case \$i in
+ /*)
+ exec touch "\$i"
+ ;;
+ esac
+done
+
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
+DEBOOTSTRAPOPTIONS=""
+STANDARDPACKAGES="debian-archive-keyring,ifupdown,isc-dhcp-client,locales,openssh-server"
+
+if [ "$DEBIAN_RELEASE" == "squeeze" ] || [ "$DEBIAN_RELEASE" == "lenny" ] || [ "$DEBIAN_RELEASE" == "etch" ]; then
+ DEBOOTSTRAPOPTIONS="--no-check-gpg"
+fi
+
+if [ "$DEBIAN_RELEASE" == "lenny" ] || [ "$DEBIAN_RELEASE" == "etch" ]; then
+ STANDARDPACKAGES="debian-archive-keyring,ifupdown,locales,openssh-server"
+fi
+
+debootstrap $DEBOOTSTRAPOPTIONS --foreign --include "${STANDARDPACKAGES}" $DEBIAN_RELEASE "${LXC_ROOTFS}" $DEBIAN_MIRROR
+
+echo "DEBOOTSTRAP STAGE 1 COMPLETE"
# 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"
(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)
+if [ -e "$LXC_ROOTFS/debootstrap/devices.tar.gz" ]; then
+ (cd "$LXC_ROOTFS/debootstrap" && rm devices.tar.gz && tar czvf devices.tar.gz --files-from=/dev/null)
+fi
-# and mount a shitload of things for fun and profit...
+# if squeeze, which is totally out of date, then ignore release file expired
+if [ "$DEBIAN_RELEASE" == "squeeze" ]; then
+ echo 'Acquire::Check-Valid-Until "0";' > ${LXC_ROOTFS}/etc/apt/apt.conf.d/squeeze.conf
+fi
+
+# and mount a shedload of things for fun and profit...
for file in /var/lib/lxcfs/proc/*; do
fname="$(basename $file)"
touch "${LXC_ROOTFS}/proc/$fname"
# 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
+
+if [ "$DEBIAN_RELEASE" == "squeeze" ]; then
+ SECURITY="deb http://archive.debian.org/debian/ squeeze-lts main"
+fi
+
+if [ "$DEBIAN_RELEASE" == "lenny" ] || [ "$DEBIAN_RELEASE" == "etch" ]; then
+ SECURITY=""
+fi
+
# setup 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
+# 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}" systemctl set-default multi-user.target || true
chroot "${LXC_ROOTFS}" ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
fi
-cat <<EOF >> "${LXC_ROOTFS}${NETWORK_FILE}"
-auto eth0
-iface eth0 inet dhcp
-EOF
+if [ -e "${LXC_ROOTFS}/lib/systemd/system/systemd-journald-audit.socket" ]; then
+ touch "${LXC_ROOTFS}/etc/systemd/system/systemd-journald-audit.socket"
+fi
+
+echo "$INTERFACE_DETAILS" >> "${LXC_ROOTFS}${NETWORK_FILE}"
# and update to the latest security
chroot "${LXC_ROOTFS}" apt-get update
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