#!/bin/bash # set -ex NAME="debian" CONFFILE="lxc.conf" MNTFILE="mount.conf" UTSNAME= IPV4="172.20.0.21" GATEWAY="172.20.0.1" INTERFACES="/etc/network/interfaces" INITTAB="/etc/inittab" HOSTNAME="/etc/hostname" FSTAB="/etc/fstab" SSHD_CONFIG="/etc/ssh/sshd_config" CACHE="@LOCALSTATEDIR@/cache/lxc/debian" ################################################################################ # debian custom configuration files ################################################################################ # custom selinux write_debian_selinux() { mkdir $ROOTFS/selinux echo 0 > $ROOTFS/selinux/enforce } # custom fstab write_debian_fstab() { cat < $ROOTFS/$FSTAB tmpfs /dev/shm tmpfs defaults 0 0 EOF } # custom inittab write_debian_inittab() { cat < $ROOTFS/$INITTAB id:3:initdefault: si::sysinit:/etc/init.d/rcS l0:0:wait:/etc/init.d/rc 0 l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 # Normally not reached, but fallthrough in case of emergency. z6:6:respawn:/sbin/sulogin 1:2345:respawn:/sbin/getty 38400 console c1:12345:respawn:/sbin/getty 38400 tty1 linux c2:12345:respawn:/sbin/getty 38400 tty2 linux c3:12345:respawn:/sbin/getty 38400 tty3 linux c4:12345:respawn:/sbin/getty 38400 tty4 linux EOF } # custom network configuration write_debian_network() { cat < $ROOTFS/$INTERFACES auto eth0 lo iface eth0 inet static address $IPV4 netmask 255.255.255.0 broadcast 0.0.0.0 up route add default gw $GATEWAY iface lo inet loopback EOF } # custom hostname write_debian_hostname() { cat < $ROOTFS/$HOSTNAME $UTSNAME EOF } # custom sshd configuration file write_debian_sshd_config() { cat < $ROOTFS/$SSHD_CONFIG Port 22 Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key UsePrivilegeSeparation yes KeyRegenerationInterval 3600 ServerKeyBits 768 SyslogFacility AUTH LogLevel INFO LoginGraceTime 120 PermitRootLogin yes StrictModes yes RSAAuthentication yes PubkeyAuthentication yes IgnoreRhosts yes RhostsRSAAuthentication no HostbasedAuthentication no PermitEmptyPasswords yes ChallengeResponseAuthentication no EOF } ################################################################################ # lxc configuration files ################################################################################ write_lxc_configuration() { cat < $CONFFILE lxc.utsname = $UTSNAME lxc.tty = 4 lxc.network.type = veth lxc.network.flags = up lxc.network.link = br0 lxc.network.name = eth0 lxc.mount = $MNTFILE lxc.rootfs = $ROOTFS lxc.cgroup.devices.deny = a # /dev/null and zero lxc.cgroup.devices.allow = c 1:3 rwm lxc.cgroup.devices.allow = c 1:5 rwm # consoles lxc.cgroup.devices.allow = c 5:1 rwm lxc.cgroup.devices.allow = c 5:0 rwm lxc.cgroup.devices.allow = c 4:0 rwm lxc.cgroup.devices.allow = c 4:1 rwm # /dev/{,u}random lxc.cgroup.devices.allow = c 1:9 rwm lxc.cgroup.devices.allow = c 1:8 rwm # /dev/pts/* - pts namespaces are "coming soon" lxc.cgroup.devices.allow = c 136:* rwm lxc.cgroup.devices.allow = c 5:2 rwm # rtc lxc.cgroup.devices.allow = c 254:0 rwm EOF } write_lxc_mounts() { cat < $MNTFILE EOF } create() { # choose a container name, default is 'debian' echo -n "What is the name for the container ? [$NAME] " read _NAME_ if [ ! -z "$_NAME_" ]; then NAME=$_NAME_ fi # choose a hostname, default is the container name echo -n "What hostname do you wish for this container ? [$NAME] " read _UTSNAME_ if [ ! -z "$_UTSNAME_" ]; then UTSNAME=$_UTSNAME_ else UTSNAME=$NAME fi # choose an ipv4 address, better to choose the same network than # your host echo -n "What IP address do you wish for this container ? [$IPV4] " read _IPV4_ if [ ! -z "$_IPV4_" ]; then IPV4=$_IPV4_ fi # choose the gateway ip address echo -n "What is the gateway IP address ? [$GATEWAY] " read _GATEWAY_ if [ ! -z "$_GATEWAY_" ]; then GATEWAY=$_GATEWAY_ fi # the rootfs name will be build with the container name ROOTFS="./rootfs.$NAME" # check if the rootfs does already exist if [ ! -e "$ROOTFS" ]; then ( flock -n -x 200 RES=$? if [ "$RES" != "0" ]; then echo "Cache repository is busy." break fi echo "Choose your architecture" select ARCH in amd64 i386; do echo "Architecture $ARCH selected" break; done # check the mini debian was not already downloaded echo -n "Checking cache download ..." if [ ! -e "$CACHE/rootfs-$ARCH" ]; then echo "not cached" mkdir -p "$CACHE/rootfs-$ARCH" # download a mini debian into a cache echo "Downloading debian minimal ..." debootstrap --verbose --variant=minbase --arch=$ARCH \ --include apache,netbase,net-tools,iproute,openssh-server \ etch $CACHE/rootfs-$ARCH http://ftp.debian.org/debian RESULT=$? if [ "$RESULT" != "0" ]; then echo "Failed to download the rootfs, aborting." exit 1 fi echo "Download complete." else echo "Found." fi # make a local copy of the minidebian echo -n "Copying rootfs ..." cp -a $CACHE/rootfs-$ARCH $ROOTFS && echo "Done." || exit ) 200>/var/lock/subsys/lxc fi write_lxc_mounts write_lxc_configuration write_debian_inittab write_debian_hostname write_debian_fstab write_debian_network write_debian_sshd_config write_debian_selinux @BINDIR@/lxc-create -n $NAME -f $CONFFILE RES=$? # remove the configuration files rm -f $CONFFILE rm -f $MNTFILE if [ "$RES" != "0" ]; then echo "Failed to create '$NAME'" exit 1 fi echo "Done." echo -e "\nYou can run your container with the 'lxc-start -n $NAME'\n" } destroy() { echo -n "What is the name for the container ? [$NAME] " read _NAME_ if [ ! -z "$_NAME_" ]; then NAME=$_NAME_ fi @BINDIR@/lxc-destroy -n $NAME RETVAL=$? if [ ! $RETVAL -eq 0 ]; then echo "Failed to destroyed '$NAME'" return $RETVAL; fi ROOTFS="./rootfs.$NAME" echo -n "Shall I remove the rootfs [y/n] ? " read if [ "$REPLY" = "y" ]; then rm -rf $ROOTFS fi return 0 } help() { cat </var/lock/subsys/lxc } if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi case "$1" in create) create;; destroy) destroy;; help) help;; purge) purge;; *) echo "Usage: $0 {create|destroy|purge|help}" exit 1;; esac