Table of Contents

Creating a LXC virtual machine template (from scratch)

I have chosen to put all virtual machines in a /mnt/vm folder, for which I've created a separate partition. Here I will put the virtual machine files, configs and scripts.

Making a template out of your container saves you a lot of time when you need to add an extra container.

creating a lxc container template from scratch (using debootstrap) Install debootstrap:

apt-get install debootstrap

Download the 'squeeze' debian distribution files into a tarball archive:

vm-mgr:/mnt/vm# debootstrap --make-tarball=debootstrap-squeeze-tarball.tar squeeze <BEGIN GeSHi>/mnt/vm/vm-template<END GeSHi>

It will create a .tar file of about 60MB. Install a base system using the just created tarball archive. I've selected the 'minimal base' debian installation variety, as I want to keep the size of the debian container small. I opted to extract the files to /mnt/vm/vm-template.:

debootstrap --variant=minbase --unpack-tarball=debootstrap-squeeze-tarball.tar squeeze <BEGIN GeSHi>/mnt/vm/vm-template<END GeSHi>

Add a network bridge (make sure bridge-utils is installed on the vm-mgr): In /etc/network/interfaces, comment 'allow-hotplug eth0' out, then add:

auto br0
iface br0 inet static
        address <BEGIN GeSHi><END GeSHi>
        netmask <BEGIN GeSHi><END GeSHi>
        gateway <BEGIN GeSHi><END GeSHi>
        bridge_ports <BEGIN GeSHi>eth0<END GeSHi>
        bridge_fd 0

Create the bridge by hand by entering:

brctl addbr br0 eth0
#brctl addif br0 eth1

Configuration files and scripts

nano <BEGIN GeSHi>/mnt/vm/<END GeSHi>vm-template.config
lxc.tty = 4
lxc.pts = 1024
lxc.rootfs = <BEGIN GeSHi>/mnt/vm/vm-template<END GeSHi>
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 /mnt/vm/vm-template/proc proc nodev,noexec,nosuid 0 0
lxc.mount.entry=devpts /mnt/vm/vm-template/dev/pts devpts defaults 0 0
lxc.mount.entry=sysfs /mnt/vm/vm-template/sys sysfs defaults  0 0
#lxc.mount.entry=/mnt/vm/vm-template.fstab /mnt/vm/vm-template/etc/fstab none bind 0 0
lxc.utsname = vm-template = veth = up = br0
nano vm-template.fstab
#<BEGIN GeSHi>vm-mgr<END GeSHi>:<BEGIN GeSHi>/shared/nfs4/path<END GeSHi> <BEGIN GeSHi>/mount/point<END GeSHi> nfs4 defaults,_netdev,noauto      0       0
lxc-stop -n <BEGIN GeSHi>vm-template<END GeSHi>
lxc-destroy -n <BEGIN GeSHi>vm-template<END GeSHi>
lxc-create -n <BEGIN GeSHi>vm-template<END GeSHi> -f <BEGIN GeSHi>/mnt/vm/vm-template.config<END GeSHi>
sleep 2
lxc-start -n <BEGIN GeSHi>vm-template<END GeSHi> -d
sleep 2
lxc-console -n <BEGIN GeSHi>vm-template<END GeSHi>
chmod ugo+x

I haven't checked the neccessity of 'sleep 2' yet.

Fixing things

Running Debian from a lxc container requires some small adjustments to make things work.

Before fixing these things, we will have to make debian think it is running from the vm-template directory we've just created. We can do this with the change-root command ('chroot'):

cd <BEGIN GeSHi>/mnt/vm/vm-template<END GeSHi>
root@vm-mgr:/mnt/vm/vm-template# chroot .

Change the root password

This is a basic but very important step to do, as you don't want your container to have a default password.

root@vm-mgr:/# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

Disable some TTY's

Disabling tty's is required to make lxc containers work.

nano /etc/inittab


5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6


<BEGIN GeSHi>#<END GeSHi>5:23:respawn:/sbin/getty 38400 tty5
<BEGIN GeSHi>#<END GeSHi>6:23:respawn:/sbin/getty 38400 tty6

Create some devices:

cd /dev
mknod -m 666 tty1 c 4 1
mknod -m 666 tty2 c 4 2
mknod -m 666 tty3 c 4 3
mknod -m 666 tty4 c 4 4

Remove the time/clock files

Some of the init scripts try to initialize the hardware clock. We will prevent this by making these init-script non-executable:

chmod ugo-x /etc/init.d/hwclock*


startpar: service(s) returned failure: ... failed!

Remove the files in rc#.d as well.. ? ?

Configuring network

nano /etc/network/interfaces

auto eth0
iface eth0 inet static
        address <BEGIN GeSHi><END GeSHi>
        netmask <BEGIN GeSHi><END GeSHi>
        gateway <BEGIN GeSHi><END GeSHi>
        dns-nameservers <BEGIN GeSHi><END GeSHi>

nano /etc/hostname


Append vm-template to /etc/hosts file:

nano /etc/hosts       localhost <BEGIN GeSHi>vm-template<END GeSHi>


Edit the apt sources list (where it downloads the software packages from)

nano /etc/apt/sources.list

change mirror to something local, see add security update server to the file:

deb squeeze/updates main contrib non-free

Update the list of packages:

apt-get update

Install apt-utils, which contain some basic tools for package maintenance:

apt-get install apt-utils

Correcting the hostname

Edit the hostname (make sure you are still in the chroot!):

echo "vm-template" > /etc/hostname
nano /etc/hosts

add: localhost vm-template

perl: warning: Setting locale failed.

Perl complaining about locale settings:

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
        LANGUAGE = "en_US:en",
        LC_ALL = (unset),
        LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
debconf: delaying package configuration, since apt-utils is not installed

Fix it by entering:

echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
apt-get -y --force-yes install locales
dpkg-reconfigure locales

In dpkg-reconfigure, select the correct locale (mine is 'en_US.UTF-8')

'Dialog' warning message during apt-get:

debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/ line 75.)
debconf: falling back to frontend: Readline

Fix it:

apt-get install dialog

The following NEW packages will be installed: dialog libncursesw5

Fixing /etc/mtab

ln -s /proc/mounts /etc/mtab
root@debian:/etc# ls -al /etc/mtab
lrwxrwxrwx 1 root root 12 Dec  1 23:09 /etc/mtab -> /proc/mounts

install extra software

apt-get --no-install-recommends install -y adduser apt-utils iproute netbase sudo iputils-ping iptables rsyslog
apt-get install --no-install-recommends openssh-blacklist openssh-blacklist-extra openssh-server 
apt-get install net-tools ifupdown sockstat
apt-get install wget less lsof screen apt-utils nano telnet inetutils-ping psmisc

(psmisc contains killall) ?apt-get install bridge-utils


root@vm-mgr:/# apt-get install dhcp3-client

Networking in the container: add the following to /etc/network/interfaces:

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

Waiting for /dev to be fully populated... # apt-get remove –purge udev


ping6 ? /etc/network/interfaces??

exit the chroot

root@vm-mgr:/etc/network# exit

Testing the newly created vm-template

edit start script


starting it using the script

root@vm-mgr:/mnt/virtualmachines# sh 'vm-template' does not exist 'vm-template' created Type <Ctrl+a q> to exit the console

Debian GNU/Linux squeeze/sid vm-template tty1

template login: root Password: Linux vm-template 2.6.32-5-686 #1 SMP Thu Nov 25 18:43:34 UTC 2010 i686

The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. root@vm-template:~#

try: ssh localhost

Decreasing size of the vm-template

Clear /var/cache/apt/archives and do an 'autoremove' (removes orphaned packages(?)):

apt-get clean
apt-get autoremove

The '/usr/share/locale' folder takes a lot of space:

du -c -s /usr/share/locale/
  33548   locale/

So let's remove these locales (select correct locale when asked, I chose 'en_US UTF8(?)'):

apt-get install localepurge
  localepurge: Disk space freed in /usr/share/locale: 32704 KiB
  localepurge: Disk space freed in /usr/share/man: 2376 KiB
  Total disk space freed by localepurge: 35080 KiB


screen - screen manager with VT100/ANSI terminal emulation

apt-get install screen

When started, screen displays an introduction screen, to remove this,

nano /etc/screenrc


#startup_message off


startup_message off

You can use screen to start the containers, remember: ctrl-a a to send a ctrl-a to the 'inside' process. To end a 'lxc-start -n container_name' command (if you haven't used the '-d' option to daemonize it), open another shell and use 'lxc-stop -n container_name'

Regenerate SSH system keys

in the manager:

root@vm-mgr:~/# ssh-keygen
root@vm-mgr:~/# cat /root/.ssh/ >> /vm-template/root/.ssh/authorized_keys
root@vm-net:~/.ssh# nano -w authorized_keys
na het kopieëren van een template naar een nieuwe vm, ssh-keygen draaien:
echo y | /usr/bin/ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key
echo y | /usr/bin/ssh-keygen -t dsa -N "" -f /etc/ssh/ssh_host_dsa_key
'echo y'  because it may ask to overwrite the ssh_host_dsa/rsa_key file if it already exists.
?-C comment ?  -t rsa1?

after copy template to new folder, EDIT CONFIG!

Clearing the message of the day (motd

rm /etc/motd /etc/motd.tail

echo "export BLOCKSIZE=MB" » /root/.profile []

firewall on vm's IN AND OUTGOING!

apt-get ?remove exim4* set window title putty add this to /root/.bashrc: function settitle { if [ "$TERM" == "xterm" ] ; then

      # Remove the old title string in the PS1, if one is already set.
      PS1=`echo $PS1 | sed -r 's/^\\\\\[.+\\\\\]//g'`
      export PS1="\[\033]0;\u@\h:\w\007\]$PS1 "


      echo "You are not working in xterm. I cannot set the title."

fi } function cd() { command cd "$@"; settitle `pwd -P`; } 4.3 bash


case $TERM in
        PS1="\[\033]0;\u@\h:\w\007\]\u@\h:\w\\$ "
        PS1="\u@\h: \w\\$ "

echo BLOCKSIZE=MB » ~/.bashrc OF PROFILE??

nfs client

nfs algemeen:

nfs server draait nog niet in vm, behalve als user daemon root@vm-template# apt-get install nfs-common portmap vm-nfsd# nano /etc/exports vm-nfsd#exportfs -rav

=== zooi Err squeeze/main libldap-2.4-2 i386 2.4.23-6

404  Not Found [IP: 80]

Failed to fetch 404 Not Found [IP: 80] E: Unable to fetch some archives, maybe run apt-get update or try with –fix-missing?

na kopieren template, apt-get update draaien

switch to syslog-ng

apt-get install man

Installing extra software packages

apt-get install telnet apt-get install man lsof

Setting up a basic iptables firewall

#! /bin/sh

#. /lib/lsb/init-functions


do_start() {

set -x

# Clear any existing firewall stuff before we start
iptables --flush
iptables -t nat --flush
iptables -t mangle --flush

# As the default policies, drop all incoming traffic but allow all
# outgoing traffic.  This will allow us to make outgoing connections
# from any port, but will only allow incoming connections on the ports
# specified below.
iptables --policy INPUT DROP
iptables --policy OUTPUT ACCEPT

# Allow all incoming traffic if it is coming from the local loopback device
iptables -A INPUT -i lo -j ACCEPT

# Related and established connections: see 
# Accept all incoming traffic associated with an established
# connection, or a "related" connection
# This will automatically handle incoming UDP traffic associated with
# DNS queries, as well as PASSIVE mode FTP (provided the
# ip_conntrack_ftp module is loaded)

for f in $INTERFACES
iptables -A INPUT -i $f -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow connections on selected ports to the firewalled computer:
#   22 ssh
#   25 smtp (mail)
#   143 and 993 imap and imaps(imap over ssl)

for f in $INTERFACES
iptables -A INPUT -p tcp -i eth0 --dport 22 -m state --state NEW -j ACCEPT
iptables -A INPUT -p udp -i eth0 --dport 137 -m state --state NEW -j ACCEPT
iptables -A INPUT -p udp -i eth0 --dport 138 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 139 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 445 -m state --state NEW -j ACCEPT
#UDP/137    - used by nmbd
#UDP/138    - used by nmbd
#TCP/139    - used by smbd
#TCP/445    - used by smbd

#iptables -A INPUT -p tcp -i eth0 --dport 25 -m state --state NEW -j ACCEPT
#iptables -A INPUT -p tcp -i eth0 --dport 80 -m state --state NEW -j ACCEPT
#iptables -A INPUT -p tcp -i eth0 --dport 143 -m state --state NEW -j ACCEPT
#iptables -A INPUT -p tcp -i eth0 --dport 993 -m state --state NEW -j ACCEPT


# Allow icmp input so that people can ping us
iptables -A INPUT -p icmp -j ACCEPT

# Logging: first, eliminate any packets that are going to broadcast
# addresses, since they will overwhelm the log files if there are any
# windows computers on our network. Also, don't log pesky multicast
# packets that we block. 
iptables -A INPUT -d -j DROP
iptables -A INPUT -d -j DROP

# Log all other blocked packets, and change DROP to REJECT to be
# polite and allow people connecting to a blocked port to receive a
# "connection refused" message instead of timing out after 30 seconds.
iptables -A INPUT -j LOG
iptables -A INPUT -j REJECT


do_stop() {

iptables --flush
iptables -t nat --flush
iptables -t mangle --flush

iptables --policy INPUT ACCEPT
iptables --policy OUTPUT ACCEPT


case "$1" in
        echo -n "Starting firewall:"
	echo " done."
        echo -n "Stopping firewall:"
	echo " done."
        $0 stop  &&  $0 start
        echo "Usage: $0 {start|stop|restart}"
        exit 1

# Load needed kernel modules
#modprobe ip_conntrack
#modprobe ip_conntrack_ftp

Using a LXC container template to create a new container

-edit config file -edit hostname -ssh-keygen (dsa + rsa) -edit network interfaces file (=set ip address) -edit any batch files, -apt-get update [test] -add container name to boot script [reboot]? or vm-mgr# /etc/init.d/lxc restart

# cp -Rp vm-template vm-//new_container_name//
# cd vm-ldap/
# ls
config  rootfs
# nano config
# nano rootfs/etc/hostname

change occurences of vm-template to vm-new_container_name

Bash colors

root@vm-mgr:# set | grep -i color

Bash prompt colors

Script to check if lxc container is running ok

#!/bin/sh VPS_DOM="/mnt/virtualmachines" vps="vm-net" VPS_VAR="" VPS_LOG="/var/log" timeout=10 while true; do

echo -n .
      # time of 5 minutes on it JUST IN CASE...
echo ${vps_utmp}
      inotifywait -qqt ${timeout} ${vps_utmp}
      if [ $(wc -l < ${VPS_VAR}/cgroup/${vps}/tasks) -eq 1 ]; then
          runlevel="$(runlevel ${vps_utmp})"
    echo $runlevel
          case $runlevel in
              # nothing for new boot state
              # halted...  kill vps.
              lxc-stop -n "${vps}"
	echo rebooting...
              # rebooting...  kill vps and start again...
              lxc-stop -n ${vps}
              lxc-wait -n ${vps} -s STOPPED
              lxc-start -d -n ${vps} -o ${VPS_LOG}/${vps}.log
              # loop again.
              # make sure vps is still running
              state="$(lxc-info -n "${vps}" | sed -e 's/.* is //')"
	echo $state
              [ "$state" = "RUNNING" ] || break
	echo container ${vps} not running
mount /lxc/
cd /lxc
apt-get install debootstrap
debootstrap --make-tarball=debootstrap-squeeze-tarball.tar squeeze /lxc/vm-template/rootfs(?)
debootstrap --variant=minbase --unpack-tarball=/lxc/debootstrap-squeeze-tarball.tar squeeze /lxc/vm-template/rootfs
tar -czf vm-template.tgz vm-template

apt-get install encfs
   51  nano 
   55  nano config 
   58  nano /etc/fstab 
   60  mkdir /cgroup
   61  mount /cgroup
   62  cd /etc/
   63  cd network
   64  cat interfaces 
   65  mv interfaces interfaces.original
   67  nano interfaces
   69  exit
   70  cat /etc/fstab 
   71  cat /lxc/vm-template/ 

  108  reboot
  111  ftp
  114  nano /etc/resolv.conf 
  125  enc2xs 
  126  man enc2xs
  127  apt-get install encfs

  129  debootstrap --variant=minbase --unpack-tarball=/mnt/virtualmachines/debootstra-squeeze-tarball.tar squeeze vm-template2
  137  cd proc/
  140  rm kcore 
  163  cp -Rp cur /mnt/virtualmachines/
  185  cat /proc/mounts 
  204  sh 
  205  lxc-stop -n vm-template

  208  tar -czf vm-template.tgz vm-template/
  209  lxc-destroy -n vm-template

  213  cp -Rp vm-template vm-net
  216  nano config 
  217  cd rootfs/etc/
  219  nano hostname 

  220  ls /var/lib/lxc/
  221  lxc-ls
  222  ifconfig
  225  cp /etc/network/interfaces .
  227  nano interfaces 
  249  apt-get clean
  251  apt-get --no-install-recommends install mc
  254  nano network/interfaces
  263  apt-get install ipset
  264  ipset 
  267  apt-get remove ipset
  271  iptables -L
  272  ip6tables -L
  273  pwd
  277  route del default gw
  278  route add default gw
  285  cd /etc/network/
  287  nano interfaces
  288  ifup eth0
  289  ifup br0
  292  ifconfig br0

  298  cp 
  299  nano 
  301  sh 
  302  lxc-stop -n vm-net
  303  cd vm-net/
  304  cd rootfs/
  305  ls

  306  chroot .
  307  ifconfig eth0
  308  dhclient eth0
  309  nano /etc/resolv.conf 
  328  nano /etc/resolv.conf 
  332  chroot .

apt-get remove udev udevd ?
  356  dpkg -l > pkglist-na-bsd-mailx-verwijderen
  388  cd init.d/
  389  nano lxc 
  390  ifdown br0
  391  ifup br
  392  ifup br0
  394  ssh localhost

  397  nano /etc/init.d/lxc 
  400  nano /etc/default/lxc 

  407  ln -s /lxc/vm-template/config /etc/lxc/vm-template.conf
  450  ./lxc stop
  451  ./lxc start
  452  lxc-console -n vm-net
  453  modprobe iptables
  454  lsmod
  455  lsmod > modsnow
  456  modprobe netfilter
  457  lsmod | grep net
  458  lsmod | grep filter
  459  apt-get install iptables
  460  apt-get install ip6tables
  461  iptables -L
  468  ip6tables
  469  lsmod 
  475  route del default gw .1
  476  route add default gw .2
  478  ftp
  492  reboot
  496  lxc-console -n vm-net
apt-get install nano
nano /etc/apt/sources.list

Append the following to the list (or change 'nl' to a local debian mirror):

deb http://ftp.<BEGIN GeSHi>nl<END GeSHi> squeeze main

Finish with an 'apt-get update' command to load the new indexes.

Please leave feedback or questions at the main page.