Last active
June 25, 2018 19:21
-
-
Save dwoz/5549405 to your computer and use it in GitHub Desktop.
An lxc container creation script that works on a Debain Wheezy host and created a Debian Wheezy guest. Put this file into /usr/share/lxc/templates/ and the name should remain 'lxc-create-wheezy'. Run with lxc-create -n <container name> -t debian-wheezy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| == Prepare Debian Wheezy for LXC == | |
| Install lxc and some utils. | |
| apt-get install lxc bridge-utils libvirt-bin debootstrap | |
| Add a cgroup filesystem that will be mounted at boot. Edit /etc/fstab and add: | |
| cgroup /cgroup cgroup defaults 0 0 | |
| Add some kernel options to enable cgroup and swap support to your kernel in grub. Edit | |
| the GRUB_CMDLINE_LINUX variable in /etc/default/grub | |
| GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1 quiet" | |
| Create a bridged interface. The following assumes you want to bridge to eth1 | |
| with a static addrress. Note the old configuration is commented out and | |
| essentially moved to the new bridge iterface. | |
| # auto eth1 | |
| # iface eth1 inet static | |
| # address 10.0.0.1 | |
| # netmask 255.255.255.0 | |
| # broadcast 10.0.0.255 | |
| auto br0 | |
| iface br0 inet static | |
| bridge_ports eth1 | |
| bridge_stp on | |
| bridge_maxwait 0 | |
| address 10.0.0.1 | |
| netmask 255.255.255.0 | |
| broadcast 10.0.0.255 | |
| Now reboot the box and let all the configuration changes take effect. After the | |
| reeboot check your configuration by running lxc-checkconfig. You should have | |
| everything 'Enabled', if you see anything 'Disabled' there is a problem with | |
| your setup. I'll spare you the output of lxc-checkconfig as its self explanitory. | |
| == Create an LXC Guest == | |
| The default create script for debian guests in wheezy is broken. Download a | |
| working guest creation script. | |
| cd /usr/share/lxc/templates/ | |
| wget https://gist.github.com/dwoz/5549405/raw/25098afb4a794ce5bd5e6fdf1be28e70f9ec9f23/lxc-debian-wheezy | |
| chmod +x lxc-debian-wheezy | |
| Next prepare the guest config and root filesystem. In the following command the | |
| name given to the guest container is 'vm0' and we are sepecifying a type of | |
| 'debian-wheezy' which will call the 'lxc-debain-wheezy' creation script. | |
| lxc-create -n vm0 -t debian-wheezy | |
| Add a veth pair name and Mac to /var/lib/lxc/vm0/config. Note the name 'vm0' is | |
| the directory name needed here. | |
| lxc.network.veth.pair = vethvm0 | |
| lxc.network.hwaddr = 02:01:01:66:00:01 | |
| Now you can start the container. | |
| lxc-start -n vm0 | |
| == Useful references == | |
| http://wiki.debian.org/LXC (Mostly out of date) | |
| http://cblog.burkionline.net/lxc-linux-container/ (wheezy create script) | |
| http://jtrancas.wordpress.com/2011/02/09/fuse-filesystems-lxc-container/ (mount fuse filesystems inside containers) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| configure_debian() | |
| { | |
| rootfs=$1 | |
| hostname=$2 | |
| # configure the inittab | |
| cat <<EOF > $rootfs/etc/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 | |
| EOF | |
| # create tty devices | |
| chroot $rootfs mknod -m 666 /dev/tty1 c 4 1 | |
| chroot $rootfs mknod -m 666 /dev/tty2 c 4 2 | |
| # disable selinux in debian | |
| mkdir -p $rootfs/selinux | |
| echo 0 > $rootfs/selinux/enforce | |
| # configure the network using the dhcp | |
| cat <<EOF > $rootfs/etc/network/interfaces | |
| auto lo | |
| iface lo inet loopback | |
| auto eth0 | |
| iface eth0 inet dhcp | |
| EOF | |
| # set the hostname | |
| cat <<EOF > $rootfs/etc/hostname | |
| $hostname | |
| EOF | |
| # set dhcp hostname | |
| cat <<EOF >> $rootfs/etc/dhcp/dhclient.conf | |
| send host-name "$hostname"; | |
| EOF | |
| # set default locale | |
| cat <<EOF > $rootfs/etc/locale.gen | |
| en_US.UTF-8 UTF-8 | |
| EOF | |
| # reconfigure some services | |
| if [ -z "$LANG" ]; then | |
| chroot $rootfs locale-gen en_US.UTF-8 | |
| chroot $rootfs update-locale LANG=en_US.UTF-8 | |
| else | |
| chroot $rootfs locale-gen $LANG | |
| chroot $rootfs update-locale LANG=$LANG | |
| fi | |
| # remove pointless services in a container | |
| chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove | |
| chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove | |
| chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove | |
| echo "root:root" | chroot $rootfs chpasswd | |
| echo "Root password is 'root', please change !" | |
| return 0 | |
| } | |
| download_debian() | |
| { | |
| packages=\ | |
| ifupdown,\ | |
| locales,\ | |
| libui-dialog-perl,\ | |
| dialog,\ | |
| isc-dhcp-client,\ | |
| netbase,\ | |
| net-tools,\ | |
| iproute,\ | |
| vim,\ | |
| emacs23-nox,\ | |
| iputils-ping,\ | |
| openssh-server | |
| cache=$1 | |
| arch=$2 | |
| # check the mini debian was not already downloaded | |
| mkdir -p "$cache/partial-$arch" | |
| if [ $? -ne 0 ]; then | |
| echo "Failed to create '$cache/partial-$arch' directory" | |
| return 1 | |
| fi | |
| # download a mini debian into a cache | |
| echo "Downloading debian minimal ..." | |
| debootstrap --verbose --variant=minbase --arch=$arch \ | |
| --include $packages \ | |
| wheezy $cache/partial-$arch http://ftp.us.debian.org/debian | |
| if [ $? -ne 0 ]; then | |
| echo "Failed to download the rootfs, aborting." | |
| return 1 | |
| fi | |
| mv "$1/partial-$arch" "$1/rootfs-$arch" | |
| echo "Download complete." | |
| return 0 | |
| } | |
| copy_debian() | |
| { | |
| cache=$1 | |
| arch=$2 | |
| rootfs=$3 | |
| # make a local copy of the minidebian | |
| echo -n "Copying rootfs to $rootfs..." | |
| cp -a $cache/rootfs-$arch $rootfs || return 1 | |
| return 0 | |
| } | |
| install_debian() | |
| { | |
| cache="/var/cache/lxc/debian-wheezy" | |
| rootfs=$1 | |
| mkdir -p /var/lock/subsys/ | |
| ( | |
| flock -n -x 200 | |
| if [ $? -ne 0 ]; then | |
| echo "Cache repository is busy." | |
| return 1 | |
| fi | |
| arch=$(arch) | |
| if [ "$arch" == "x86_64" ]; then | |
| arch=amd64 | |
| fi | |
| if [ "$arch" == "i686" ]; then | |
| arch=i386 | |
| fi | |
| echo "Checking cache download in $cache/rootfs-$arch ... " | |
| if [ ! -e "$cache/rootfs-$arch" ]; then | |
| download_debian $cache $arch | |
| if [ $? -ne 0 ]; then | |
| echo "Failed to download 'debian base'" | |
| return 1 | |
| fi | |
| fi | |
| copy_debian $cache $arch $rootfs | |
| if [ $? -ne 0 ]; then | |
| echo "Failed to copy rootfs" | |
| return 1 | |
| fi | |
| return 0 | |
| ) 200>/var/lock/subsys/lxc | |
| return $? | |
| } | |
| copy_configuration() | |
| { | |
| path=$1 | |
| rootfs=$2 | |
| name=$3 | |
| cat <<EOF >> $path/config | |
| lxc.tty = 4 | |
| lxc.pts = 1024 | |
| 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 | |
| lxc.cgroup.devices.allow = c 136:* rwm | |
| lxc.cgroup.devices.allow = c 5:2 rwm | |
| # rtc | |
| lxc.cgroup.devices.allow = c 254:0 rwm | |
| # mounts point | |
| lxc.mount.entry=proc $rootfs/proc proc nodev,noexec,nosuid 0 0 | |
| lxc.mount.entry=devpts $rootfs/dev/pts devpts defaults 0 0 | |
| lxc.mount.entry=sysfs $rootfs/sys sysfs defaults 0 0 | |
| lxc.utsname = $name | |
| # networking | |
| lxc.network.type = veth | |
| lxc.network.flags = up | |
| lxc.network.link = br0 | |
| lxc.network.name = eth0 | |
| # It is fine to be commented out | |
| #lxc.network.ipv4 = 192.168.10.21/24 | |
| # Change this | |
| # lxc.network.hwaddr = 00:11:22:33:44:00 | |
| EOF | |
| if [ $? -ne 0 ]; then | |
| echo "Failed to add configuration" | |
| return 1 | |
| fi | |
| return 0 | |
| } | |
| clean() | |
| { | |
| cache="/var/cache/lxc/debian-wheezy" | |
| if [ ! -e $cache ]; then | |
| exit 0 | |
| fi | |
| # lock, so we won't purge while someone is creating a repository | |
| ( | |
| flock -n -x 200 | |
| if [ $? != 0 ]; then | |
| echo "Cache repository is busy." | |
| exit 1 | |
| fi | |
| echo -n "Purging the download cache..." | |
| rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 | |
| exit 0 | |
| ) 200>/var/lock/subsys/lxc | |
| } | |
| usage() | |
| { | |
| cat <<EOF | |
| $1 -h|--help -p|--path=<path> --clean | |
| EOF | |
| return 0 | |
| } | |
| options=$(getopt -o hp:n:c -l help,path:,name:,clean -- "$@") | |
| if [ $? -ne 0 ]; then | |
| usage $(basename $0) | |
| exit 1 | |
| fi | |
| eval set -- "$options" | |
| while true | |
| do | |
| case "$1" in | |
| -h|--help) usage $0 && exit 0;; | |
| -p|--path) path=$2; shift 2;; | |
| -n|--name) name=$2; shift 2;; | |
| -c|--clean) clean=$2; shift 2;; | |
| --) shift 1; break ;; | |
| *) break ;; | |
| esac | |
| done | |
| if [ ! -z "$clean" -a -z "$path" ]; then | |
| clean || exit 1 | |
| exit 0 | |
| fi | |
| type debootstrap | |
| if [ $? -ne 0 ]; then | |
| echo "'debootstrap' command is missing" | |
| exit 1 | |
| fi | |
| if [ -z "$path" ]; then | |
| echo "'path' parameter is required" | |
| exit 1 | |
| fi | |
| if [ "$(id -u)" != "0" ]; then | |
| echo "This script should be run as 'root'" | |
| exit 1 | |
| fi | |
| rootfs=$path/rootfs | |
| install_debian $rootfs | |
| if [ $? -ne 0 ]; then | |
| echo "failed to install debian" | |
| exit 1 | |
| fi | |
| configure_debian $rootfs $name | |
| if [ $? -ne 0 ]; then | |
| echo "failed to configure debian for a container" | |
| exit 1 | |
| fi | |
| copy_configuration $path $rootfs $name | |
| if [ $? -ne 0 ]; then | |
| echo "failed write configuration file" | |
| exit 1 | |
| fi | |
| if [ ! -z $clean ]; then | |
| clean || exit 1 | |
| exit 0 | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment