Skip to content

Instantly share code, notes, and snippets.

@pklaus
Created January 25, 2011 01:08
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save pklaus/794335 to your computer and use it in GitHub Desktop.
Save pklaus/794335 to your computer and use it in GitHub Desktop.
Automates the steps to set up LXC containers with virtualized environments on Ubuntu Linux
#!/bin/bash
### Bash Script that automates the steps to set up an LXC (Linux Container) boxed environment on Ubuntu Linux
### <http://blog.philippklaus.de/2011/01/container-virtualization-using-lxc-on-ubuntu/>
###
### More inspiration can be found in <https://github.com/phbaer/lxc-tools> and in
### <https://github.com/halcyon/lxc-tools/commit/b428a6973dd12b75c2400d41f60c454e752c10c6> and
### <http://mindref.blogspot.com/2011/01/debian-lxc-create.html>.
###
### Written by Philipp Klaus <philipp.l.klaus @ web.de>
###
### This bash script may be distributed under the license terms of the GNU GPL v3.
## to debug this script uncomment the following line:
#set -x
## constants
PACKAGE_LIST="lxc debootstrap bridge-utils libcap2-bin"
FSTAB_ENTRY="none /cgroup cgroup defaults 0 0"
DEFAULT_DEV=eth0
DEFAULT_DIR=~/lxc
DEFAULT_HOSTNAME=guest
echo "Making sure /etc/fstab containes an entry for 'cgroup'"
grep cgroup /etc/fstab
not_contained=$?
if [ $not_contained = 1 ]; then
echo -e "\n$FSTAB_ENTRY\n" | sudo tee -a /etc/fstab > /dev/null
sudo mkdir /cgroup
sudo mount /cgroup
echo "cgroup added to /etc/fstab and mounted"
fi
all_installed=1
echo "Making sure the needed packages for LXC are installed."
for package in $PACKAGE_LIST; do
dpkg -l $package; not_installed=$?
if [ $not_installed = 1 ]; then
all_installed=0
echo "$package not installed yet."
fi
done
if [ $all_installed = 0 ]; then
echo "Installing the required packages on the host system."
sudo aptitude update
sudo aptitude install $PACKAGE_LIST
fi
echo "Making sure there is a network bridge set up in the the network configuration."
grep "auto br0" /etc/network/interfaces
not_contained=$?
if [ $not_contained = 1 ]; then
echo "No bridge found, setting it up now."
read -p "Please enter the network device to be bridged [$DEFAULT_DEV]: " device
device=${device:-$DEFAULT_DEV}
cat - <<EOF | sudo tee -a /etc/network/interfaces
# LXC-Config
auto br0
iface br0 inet dhcp
# ethX is the interface with which the bridge should be bridged
bridge_ports $device
bridge_stp off
bridge_maxwait 5
post-up /usr/sbin/brctl setfd br0 0
EOF
sudo /etc/init.d/networking restart
fi
echo "The prerequisites have been met. Continuing with the LXC itself."
########### Start the setup of the LXC container itself
## ask for basic parameters
read -p "Please enter the directory to install the new LXC container to [$DEFAULT_DIR]: " directory
directory=${directory:-$DEFAULT_DIR}
read -p "Please enter the hostname for the new LXC container [$DEFAULT_HOSTNAME]: " hostname
hostname=${hostname:-$DEFAULT_HOSTNAME}
read -p "Please enter a username with future sudo permissions on the LXC container [$USER]: " username
username=${username:-$USER}
#read -p "Please enter the future password for the user $username: " password
#password=${password:-empty}
package_list="openssh-server language-pack-en"
echo "Creating the LXC directory $directory"
sudo mkdir -p $directory/rootfs.$hostname
echo "Creating the fstab file for the new LXC"
cat - <<EOF | sudo tee -a $directory/fstab.$hostname
none $directory/rootfs.$hostname/dev/pts devpts defaults 0 0
#none $directory/rootfs.$hostname/dev/run tmpfs defaults 0 0
none $directory/rootfs.$hostname/dev/shm tmpfs defaults 0 0
EOF
DEFAULT_RELEASE=`lsb_release -c | cut -s -f 2`
read -p "Please enter a the codename for the release you want to install for the LXC container [$DEFAULT_RELEASE]: " release
release=${release:-$DEFAULT_RELEASE}
echo "Installing the base system"
sudo debootstrap --arch amd64 $release $directory/rootfs.$hostname http://archive.ubuntu.com/ubuntu ## for Ubuntu
#sudo debootstrap sid rootfs http://debian.osuosl.org/debian/ ## for debian sid
echo "Clean up the included /lib/init/fstab"
sudo cp $directory/rootfs.$hostname/lib/init/fstab $directory/rootfs.$hostname/lib/init/fstab.old
sudo cat $directory/rootfs.$hostname/lib/init/fstab | grep -v "/proc " | grep -v "/dev " | grep -v "/dev/pts" | sudo tee $directory/rootfs.$hostname/lib/init/fstab > /dev/null
echo "Correcting the languages in /etc/environment"
cat - << EOF | sudo tee -a $directory/rootfs.$hostname/etc/environment > /dev/null
LANG="en_US.UTF-8"
LANGUAGE="en_US.UTF-8"
LC_ALL="en_US.UTF-8"
LC_CTYPE="C"
EOF
echo "Setting the hostname"
echo -e "127.0.0.1 localhost $hostname\n" | sudo tee $directory/rootfs.$hostname/etc/hosts > /dev/null
echo -e "$hostname\n" | sudo tee $directory/rootfs.$hostname/etc/hostname > /dev/null
echo "Creating the new user account including sudo rights"
### TODO: adduser on the command line in non interactive mode does not set a sensible password!!!
### something like 'passwd $u' or 'echo "root:root" | chpasswd; echo "$u:$u" | chpasswd' should do it.
sudo sed -i 's/%sudo/%admin/g' $directory/rootfs.$hostname/etc/sudoers
echo 'u='$username'; g=admin; adduser $u; addgroup $g; adduser $u $g' | sudo chroot $directory/rootfs.$hostname /bin/bash
echo "Installing packages: $package_list"
echo "apt-get upgrade; apt-get -y --force-yes install $package_list" | sudo chroot $directory/rootfs.$hostname /bin/bash
echo "Creating the LXC configuration file $directory/conf.$hostname"
cat - << EOF | sudo tee -a $directory/conf.$hostname
lxc.utsname = $hostname
lxc.tty = 4
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.hwaddr = 08:00:12:34:56:78
#lxc.network.ipv4 = 0.0.0.0
lxc.network.ipv4 = 192.168.102.99
lxc.network.name = eth0
lxc.mount = $directory/fstab.$hostname
lxc.rootfs = $directory/rootfs.$hostname
lxc.pts = 1024
# Forbid all devices:
lxc.cgroup.devices.deny = a
# /dev/null and /dev/zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles: /dev/console, /dev/tty, /dev/tty0, /dev/tty1
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/urandom, /dev/random, ? and /dev/ptmx
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc: /dev/rtc0
lxc.cgroup.devices.allow = c 254:0 rwm
## workaround for failing udev upgrade on Ubuntu 10.10 (uncomment):
lxc.cgroup.devices.allow = c 108:0 rwm
lxc.cgroup.devices.allow = b 7:0 rwm
lxc.cgroup.devices.allow = c 10:200 rwm
EOF
echo "Creating the LXC from the configuration file"
sudo lxc-create -n $hostname -f $directory/conf.$hostname
echo
cat << REALEOF
Successfully created the guest operating system installation of $hostname
in the directory $directory. First you should set the password for $username:
sudo chroot $directory/rootfs.$hostname /bin/bash
passwd $username
You can then start the new operating system (into daemon mode [-d]) by
sudo lxc-start -n $hostname -d
And stop it using
sudo lxc-stop -n guest
If you change its configuration $directory/conf.$hostname run
sudo lxc-destroy -n $hostname
sudo lxc-create -n $hostname -f $directory/conf.$hostname
If you want to more software to be available on the machine, then you
should change the apt source file similar to this:
cat << EOF | tee /etc/apt/sources.list
deb http://archive.ubuntu.com/ubuntu $release main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu $release-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu $release-security main restricted universe multiverse
EOF
REALEOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment