Difference between revisions of "Ubuntu Gutsy template creation"

From OpenVZ Virtuozzo Containers Wiki
Jump to: navigation, search
(Get rid of tmpfs mounts)
(Modify the installation)
 
(33 intermediate revisions by 8 users not shown)
Line 2: Line 2:
 
[[Category: Templates]]
 
[[Category: Templates]]
 
[[Category: Ubuntu]]
 
[[Category: Ubuntu]]
 
 
This article summarizes the experience of creating Ubunty Gutsy Gibbon (a.k.a. 7.10) template for OpenVZ.
 
This article summarizes the experience of creating Ubunty Gutsy Gibbon (a.k.a. 7.10) template for OpenVZ.
  
Line 10: Line 9:
  
 
=== debootstrap ===
 
=== debootstrap ===
You have to have a debootstrap working for Gutsy, i.e. you should have
+
You have to have a <code>debootstrap</code> working for Gutsy, i.e. you should have
* debootstrap and its dependencies
+
* <code>debootstrap</code> and its dependencies
* /usr/lib/debootstrap/scripts/gutsy file
+
* <code>/usr/lib/debootstrap/scripts/gutsy</code> file
  
The simplest way to have it all is to work on an Ubunty Gutsy system (be it on a real machine or inside a VE). If you don't have debootstrap installed, this is the command to install it:
+
The simplest way to have it all is to work on an Ubuntu Gutsy system (be it on a real machine or inside a container). If you don't have <code>debootstrap</code> installed, this is the command to install it:
  
 
  # apt-get install debootstrap
 
  # apt-get install debootstrap
 +
 +
On a Gentoo Linux, <code>debootstrap</code> is also available, this is how you can install it:
 +
 +
# emerge \>=debootstrap-1.0.0
 +
 +
Note you need at least version 1.0.0, since earlier versions do not have Ubuntu scripts. So, possible you will first need to add it to package.keywords, like this:
 +
 +
# echo dev-util/debootstrap >> /etc/portage.package.keywords
 +
 +
On a Fedora system (at least Fedora 8, not sure about earlier versions):
 +
 +
# yum install debootstrap
  
 
=== vzctl ===
 
=== vzctl ===
  
You need vzctl-3.0.19 or later to work with Ubuntu Gutsy Gibbon. If vzctl-3.0.18 or earlier is used, you will not be able to run your VE. See {{bug|662}} for details.
+
You need vzctl-3.0.22 or later to work with Ubuntu Gutsy Gibbon. If vzctl-3.0.18 or earlier is used, you will not be able to run your Ubuntu Gutsy container. See {{bug|662}} for details.
 +
 
 +
Note: Older versions of vzctl are working if you install <code>sysvinit</code> (which will remove <code>upstart</code>). The only problem I had was the network did not start, so I added "/etc/init.d/networking restart" to /etc/re.local.
  
 
== Creating template ==
 
== Creating template ==
Line 26: Line 39:
 
=== Running debootstrap ===
 
=== Running debootstrap ===
  
Create some directory:
+
Create a working directory:
  
 
  [HW]# mkdir gutsy-chroot
 
  [HW]# mkdir gutsy-chroot
Line 34: Line 47:
 
  [HW]# debootstrap [--arch ''ARCH''] gutsy gutsy-chroot  
 
  [HW]# debootstrap [--arch ''ARCH''] gutsy gutsy-chroot  
  
If ARCH of VE0 is equal to VE, you can skip the --arch option, but if you need to build an OS template for another ''ARCH'', specify it explicitly:
+
If ARCH of CT0 is equal to container, you can skip the --arch option, but if you need to build an OS template for another ''ARCH'', specify it explicitly:
 
* for AMD64/x86_64, use <code>amd64</code>
 
* for AMD64/x86_64, use <code>amd64</code>
 
* for IA64, use <code>ia64</code>
 
* for IA64, use <code>ia64</code>
 
* for i386 <code>i386</code>
 
* for i386 <code>i386</code>
  
=== Preparing/starting a VE ===
+
=== Preparing/starting a container ===
  
Now then you have an installation created by <code>debootstrap</code>, you can run it as a VE. In the example below VE ID of 777 is used; of course you can use any other non-allocated ID.
+
Now then you have an installation created by <code>debootstrap</code>, you can run it as a container. In the example below CT ID of 777 is used; of course you can use any other non-allocated ID.
  
{{Note|an alternative way is using chroot instead of running a VE. This is not recommended because of security concerns.}}
+
{{Note|an alternative way is using chroot instead of running a container. This is not recommended because of security concerns.}}
  
==== Moving installation to VE private area ====
+
==== Moving installation to container private area ====
  
You should move the contents of gutsy-chroot directory into new VE private area, like this:
+
You should move the contents of gutsy-chroot directory into new container private area, like this:
  
# mkdir /vz/private/777
+
  # mv gutsy-chroot /vz/private/777
  # mv gutsy-chroot/ /vz/private/777
 
  
==== Setting VE config ====
+
==== Setting container config ====
An initial config for the [[VE]] is needed:
+
An initial config for the [[container]] is needed:
 
  # vzctl set 777 --applyconfig vps.basic --save
 
  # vzctl set 777 --applyconfig vps.basic --save
  
==== Setting VE OSTEMPLATE ====
+
==== Setting container OSTEMPLATE ====
Also, we need <code>OSTEMPLATE</code> to be set in VE configuration file, for the [[vzctl]] to work properly.
+
Also, we need <code>OSTEMPLATE</code> to be set in container configuration file, for the [[vzctl]] to work properly.
  
 
  # echo "OSTEMPLATE=ubuntu-7.10" >> /etc/vz/conf/777.conf
 
  # echo "OSTEMPLATE=ubuntu-7.10" >> /etc/vz/conf/777.conf
  
==== Setting VE IP address ====
+
==== Setting container IP address ====
For the [[VE]] to be able to download updates from the Internet, we need a valid IP address for it:
+
For the [[container]] to be able to download updates from the Internet, we need a valid IP address for it:
 
  # vzctl set 777 --ipadd x.x.x.x --save
 
  # vzctl set 777 --ipadd x.x.x.x --save
  
{{Note|if you use private IP for the VE, you have to set up NAT as described in [[Using NAT for VE with private IPs]].}}
+
{{Note|if you use private IP for the container, you have to set up NAT as described in [[Using NAT for container with private IPs]].}}
  
==== Setting DNS server for the VE ====
+
==== Setting DNS server for the container ====
For the [[VE]] to be able to download updates from the Internet, we also need to specify a DNS for it:
+
For the [[container]] to be able to download updates from the Internet, we also need to specify a DNS for it:
 
  # vzctl set 777 --nameserver x.x.x.x --save
 
  # vzctl set 777 --nameserver x.x.x.x --save
  
 
Instead of <code>x.x.x.x</code>, specify the same IP that you have in your <code>/etc/resolv.conf</code>.
 
Instead of <code>x.x.x.x</code>, specify the same IP that you have in your <code>/etc/resolv.conf</code>.
  
==== Starting VE ====
+
==== Starting container ====
Now start the VE:
+
Now start the container:
 
  # vzctl start 777
 
  # vzctl start 777
  
 
=== Modify the installation ===
 
=== Modify the installation ===
  
You have to do some things in order to modify the installation to better suit the environment it will be run in (i.e. a VE).
+
You have to do some things in order to modify the installation to better suit the environment it will be run in (i.e. a container).
  
First, enter a VE:
+
First, enter a container:
 
  # vzctl enter 777
 
  # vzctl enter 777
  
{{Warning|Do not run the commands below on the hardware node, they are only to be run within the VE!}}
+
{{Warning|Do not run the commands below on the hardware node, they are only to be run within the container!}}
 
 
 
==== Remove unneeded packages ====
 
==== Remove unneeded packages ====
  
Some packages does not make sense in a VE. Remove those:
+
Some packages does not make sense in a container, or are really optional. Remove those:
  
  [VE]# dpkg -P ubuntu-minimal wpasupplicant wireless-tools \
+
  [container]# dpkg -P ubuntu-minimal wpasupplicant wireless-tools \
 
   udev pcmciautils initramfs-tools volumeid console-setup \
 
   udev pcmciautils initramfs-tools volumeid console-setup \
 
   xkb-data usbutils mii-diag alsa-base alsa-utils ethtool \
 
   xkb-data usbutils mii-diag alsa-base alsa-utils ethtool \
 
   module-init-tools linux-sound-base console-tools \
 
   module-init-tools linux-sound-base console-tools \
 
   console-terminus busybox-initramfs libvolume-id0 \
 
   console-terminus busybox-initramfs libvolume-id0 \
   ntpdate
+
   ntpdate eject libasound2 pciutils tasksel tasksel-data \
 +
  laptop-detect
 +
 
 +
{{Note|On removing the deb-package "module-init-tools", a fake-modprobe is needed for IPv6 addresses, see below!}}
 +
 
 +
Note that the above list of packages may be too extensive. Say, if you want to use <code>tasksel</code> tool, do not remove it — but then you have to let laptop-detect stay.
  
 
Clean up after udev:
 
Clean up after udev:
  
  [VE]# rm -fr /lib/udev
+
  [container]# rm -fr /lib/udev
  
 
==== Disable getty ====
 
==== Disable getty ====
On a usual Linux system, getty is running on a virtual terminals, which a VE does not have.
+
On a usual Linux system, <code>getty</code> is running on a virtual terminals, which a container does not have. So, having <code>getty</code> running doesn't make sense; more to say, it complains it can not open terminal device and this clutters the logs.
  
There are two ways to disable it:
+
So, first of all we stop all <code>getty</code> processes:
 +
 
 +
[container]# initctl stop tty{1,2,3,4,5,6}
 +
 
 +
Next, we disable running <code>getty</code>. This can be done in two ways:
  
 
First way:
 
First way:
  [VE]# rm /etc/event.d/tty*
+
  [container]# rm /etc/event.d/tty*
  
 
Second way:
 
Second way:
  [VE]# dpkg -P system-services
+
  [container]# dpkg -P system-services
  
Second way can be dangerous for future versions of system-services, but it's OK for now since the only service they carry is running gettys.
+
Second way can be dangerous for future versions of <code>system-services</code>, but it's OK for now since the only service they carry is running <code>getty</code>s.
  
 
====  Set sane permissions for /root directory ====
 
====  Set sane permissions for /root directory ====
  
  [VE]# chmod 700 /root
+
  [container]# chmod 700 /root
  
 
==== Disable root login ====
 
==== Disable root login ====
  
  [VE]# usermod -L root
+
  [container]# usermod -L root
 +
 
 +
==== "fake-modprobe" needed for IPv6 addresses ====
 +
 
 +
[container]# ln -s /bin/true /sbin/modprobe
 +
 
 +
<small>On setup IPv6, the command "modprobe -Q IPv6" is called, which fails without the "fake-modprobe"</small>
  
 
==== Get new security updates ====
 
==== Get new security updates ====
  
  [VE]# apt-get update && apt-get upgrade
+
  [container]# apt-get update && apt-get upgrade
  
 
<small>This didn't show anything for me, but might do something in the future.</small>
 
<small>This didn't show anything for me, but might do something in the future.</small>
Line 130: Line 156:
 
==== Install some more packages ====
 
==== Install some more packages ====
  
  [VE]# apt-get install ssh quota
+
  [container]# apt-get install ssh quota
  
 
Feel free to add packages which you want to have in a default template to this command.
 
Feel free to add packages which you want to have in a default template to this command.
  
 
==== Fix SSH host keys ====
 
==== Fix SSH host keys ====
This is only useful if you installed SSH above.  Each individual [[VE]] should have its own pair of SSH host keys.  The code below will wipe out the existing SSH keys and instruct the newly-created [[VE]] to create new SSH keys on first boot.
+
This is only useful if you installed SSH above.  Each individual [[container]] should have its own pair of SSH host keys.  The code below will wipe out the existing SSH keys and instruct the newly-created [[container]] to create new SSH keys on first boot.
  
 
<!-- please DO NOT remove <pre>...</pre> pair of tags below,
 
<!-- please DO NOT remove <pre>...</pre> pair of tags below,
Line 149: Line 175:
 
chmod a+x /etc/rc2.d/S15ssh_gen_host_keys
 
chmod a+x /etc/rc2.d/S15ssh_gen_host_keys
 
</pre>
 
</pre>
 
  
 
==== Disable <code>sync()</code> for syslog ====
 
==== Disable <code>sync()</code> for syslog ====
Line 157: Line 182:
  
 
<!-- DO NOT remove <pre> here, it's useful -->
 
<!-- DO NOT remove <pre> here, it's useful -->
  <pre>[VE]# sed -i -e 's@\([[:space:]]\)\(/var/log/\)@\1-\2@' /etc/syslog.conf</pre>
+
  <pre>[container]# sed -i -e 's@\([[:space:]]\)\(/var/log/\)@\1-\2@' /etc/syslog.conf</pre>
  
 
==== Fix <code>/etc/mtab</code> ====
 
==== Fix <code>/etc/mtab</code> ====
 
Link <code>/etc/mtab</code> to <code>/proc/mounts</code>, so <code>df</code> and friends will work:
 
Link <code>/etc/mtab</code> to <code>/proc/mounts</code>, so <code>df</code> and friends will work:
  [VE]# rm -f /etc/mtab
+
  [container]# rm -f /etc/mtab
  [VE]# ln -s /proc/mounts /etc/mtab
+
  [container]# ln -s /proc/mounts /etc/mtab
  
 
After that, it would make sense to disable <code>mtab.sh</code> script which messes with <code>/etc/mtab</code>:
 
After that, it would make sense to disable <code>mtab.sh</code> script which messes with <code>/etc/mtab</code>:
  [VE]# update-rc.d -f mtab.sh remove
+
  [container]# update-rc.d -f mtab.sh remove
 
 
==== Get rid of tmpfs mounts ====
 
 
 
[VE]# sed -i -e '/tmpfs/d' /etc/init.d/mountkernfs.sh
 
[VE]# sed -i -e '/pre_mountall/d' -e '/post_mountall/d' \
 
  /etc/init.d/mountall.sh
 
  
 
==== Disable some services ====
 
==== Disable some services ====
Line 177: Line 196:
 
In most of the cases you don't want klogd to run -- the only exception is if you configure iptables to log some events -- so you can disable it:
 
In most of the cases you don't want klogd to run -- the only exception is if you configure iptables to log some events -- so you can disable it:
  
  [VE]# update-rc.d -f klogd remove
+
  [container]# update-rc.d -f klogd remove
  
 
==== Hostname ====
 
==== Hostname ====
 
Set proper hostname:
 
Set proper hostname:
  [VE]# echo "localhost" > /etc/hostname
+
  [container]# echo "localhost" > /etc/hostname
  
 
==== Set /etc/hosts ====
 
==== Set /etc/hosts ====
  
  [VE]# echo "127.0.0.1 localhost.localdomain localhost" > /etc/hosts
+
  [container]# echo "127.0.0.1 localhost.localdomain localhost" > /etc/hosts
  
 
==== Add ptys to /dev ====
 
==== Add ptys to /dev ====
  
This is needed in case /dev/pts will not me mounted after VE start. In case /dev/ttyp* and /dev/ptyp* files are present, and LEGACY_PTYS support is enabled in the kernel, vzctl will still be able to enter VE.
+
This is needed in case /dev/pts will not me mounted after container start. In case /dev/ttyp* and /dev/ptyp* files are present, and LEGACY_PTYS support is enabled in the kernel, vzctl will still be able to enter container.
  
  [VE]# cd /dev && /sbin/MAKEDEV ptyp
+
  [container]# cd /dev && /sbin/MAKEDEV ptyp
  
 
==== Remove nameserver(s) ====
 
==== Remove nameserver(s) ====
  
 
Remove DNS entries:
 
Remove DNS entries:
  [VE]# > /etc/resolv.conf
+
  [container]# > /etc/resolv.conf
  
 
==== Clean packages ====
 
==== Clean packages ====
 
After installing packages, you'll have some junk packages laying around in your cache.  Since you don't want your template to have those, this command will wipe them out.
 
After installing packages, you'll have some junk packages laying around in your cache.  Since you don't want your template to have those, this command will wipe them out.
  [VE]# apt-get clean
+
  [container]# apt-get clean
 +
 
 +
==== Cleaning up log files ====
 +
 
 +
[container]# cd /var/log
 +
[container]# > messages; > auth.log; > kern.log; > bootstrap.log
 +
[container]# > dpkg.log; > syslog; > daemon.log; > apt/term.log
 +
[container]# rm -f *.0 *.1
  
 
==== Anything else? ====
 
==== Anything else? ====
  
Think of what else could be done (like cleaning up log files, root history, …).
+
Think of what else could be done to better suit your needs.
  
==== Exit from the VE ====
+
==== Exit from the container ====
  
 
Now everything is done.  Exit from the template and go back to the hardware node.
 
Now everything is done.  Exit from the template and go back to the hardware node.
  
  [VE]# exit
+
  [container]# exit
  
 
== Preparing for and packing template cache ==
 
== Preparing for and packing template cache ==
  
The following commands are to be run in the host system (i.e. not inside a VE).
+
The following commands are to be run in the host system (i.e. not inside a container).
  
We don't need an IP for the VE anymore, and we definitely do not need it in template cache, so remove it:
+
We don't need an IP for the container anymore, and we definitely do not need it in template cache, so remove it:
 
  [HW]# vzctl set 777 --ipdel all --save
 
  [HW]# vzctl set 777 --ipdel all --save
  
Stop the VE:
+
Stop the container:
 
  [HW]# vzctl stop 777
 
  [HW]# vzctl stop 777
  
Change dir to the VE private:
+
Change dir to the container private:
 
  [HW]# cd /vz/private/777
 
  [HW]# cd /vz/private/777
  
Now create a cached OS tarball.  In the command below, you'll want to replace <arch> with your architecture (i386, amd64, ia64, etc).
+
Now create a cached OS tarball.  In the command below, you'll want to replace <arch> with your architecture (i386, amd64, ia64, etc). '''Note the space and the dot at the end of the command'''.
  [HW]# tar czf /vz/template/cache/ubuntu-7.10-<arch>-minimal.tar.gz .
+
  [HW]# tar --numeric-owner -czf /vz/template/cache/ubuntu-7.10-<arch>-minimal.tar.gz .
  
 
Look at the resulting tarball to see its size is sane:
 
Look at the resulting tarball to see its size is sane:
Line 233: Line 259:
  
 
== Testing template cache ==
 
== Testing template cache ==
We can now create a VE based on the just-created template cache.  Be sure to change <tt>i386</tt> to your architecture just like you did when you named the tarball above.
+
We can now create a container based on the just-created template cache.  Be sure to change <tt>i386</tt> to your architecture just like you did when you named the tarball above.
 
  [HW]# vzctl create 123456 --ostemplate ubuntu-7.10-<arch>-minimal
 
  [HW]# vzctl create 123456 --ostemplate ubuntu-7.10-<arch>-minimal
  
Now make sure that your new VE it works:
+
Now make sure that your new container it works:
 
  [HW]# vzctl start 123456
 
  [HW]# vzctl start 123456
 
  [HW]# vzctl exec 123456 ps axf
 
  [HW]# vzctl exec 123456 ps axf
Line 244: Line 270:
 
Other tests that could be done are:
 
Other tests that could be done are:
 
  [HW]# vzctl enter 123456
 
  [HW]# vzctl enter 123456
  [VE]# dpkg -l
+
  [container]# ps axf
  [VE]# logout
+
[container]# mount
 +
[container]# dpkg -l
 +
  [container]# logout
 
  [HW]#
 
  [HW]#
  
Line 251: Line 279:
  
 
== Final cleanup ==
 
== Final cleanup ==
Stop and remove the test VE you just created:
+
Stop and remove the test container you just created:
 
  [HW]# vzctl stop 123456
 
  [HW]# vzctl stop 123456
 
  [HW]# vzctl destroy 123456
 
  [HW]# vzctl destroy 123456
 
  [HW]# rm -f /etc/vz/conf/123456.conf.destroyed
 
  [HW]# rm -f /etc/vz/conf/123456.conf.destroyed
  
Finally, let's remove the VE we used for OS template cache creation:
+
Finally, let's remove the container we used for OS template cache creation:
 
  [HW]# vzctl destroy 777
 
  [HW]# vzctl destroy 777
 
  [HW]# rm -f /etc/vz/conf/777.conf.destroyed
 
  [HW]# rm -f /etc/vz/conf/777.conf.destroyed

Latest revision as of 08:24, 22 July 2012

This article summarizes the experience of creating Ubunty Gutsy Gibbon (a.k.a. 7.10) template for OpenVZ.

Template creation is based on debootstrap, and the procedure is similar to Debian template creation, but it differs in some subtle details.

Prerequisites[edit]

debootstrap[edit]

You have to have a debootstrap working for Gutsy, i.e. you should have

  • debootstrap and its dependencies
  • /usr/lib/debootstrap/scripts/gutsy file

The simplest way to have it all is to work on an Ubuntu Gutsy system (be it on a real machine or inside a container). If you don't have debootstrap installed, this is the command to install it:

# apt-get install debootstrap

On a Gentoo Linux, debootstrap is also available, this is how you can install it:

# emerge \>=debootstrap-1.0.0

Note you need at least version 1.0.0, since earlier versions do not have Ubuntu scripts. So, possible you will first need to add it to package.keywords, like this:

# echo dev-util/debootstrap >> /etc/portage.package.keywords

On a Fedora system (at least Fedora 8, not sure about earlier versions):

# yum install debootstrap

vzctl[edit]

You need vzctl-3.0.22 or later to work with Ubuntu Gutsy Gibbon. If vzctl-3.0.18 or earlier is used, you will not be able to run your Ubuntu Gutsy container. See OpenVZ Bug #662 for details.

Note: Older versions of vzctl are working if you install sysvinit (which will remove upstart). The only problem I had was the network did not start, so I added "/etc/init.d/networking restart" to /etc/re.local.

Creating template[edit]

Running debootstrap[edit]

Create a working directory:

[HW]# mkdir gutsy-chroot

Run debootstrap to install a minimal Ubunty Gutsy system into that directory:

[HW]# debootstrap [--arch ARCH] gutsy gutsy-chroot 

If ARCH of CT0 is equal to container, you can skip the --arch option, but if you need to build an OS template for another ARCH, specify it explicitly:

  • for AMD64/x86_64, use amd64
  • for IA64, use ia64
  • for i386 i386

Preparing/starting a container[edit]

Now then you have an installation created by debootstrap, you can run it as a container. In the example below CT ID of 777 is used; of course you can use any other non-allocated ID.

Yellowpin.svg Note: an alternative way is using chroot instead of running a container. This is not recommended because of security concerns.

Moving installation to container private area[edit]

You should move the contents of gutsy-chroot directory into new container private area, like this:

# mv gutsy-chroot /vz/private/777

Setting container config[edit]

An initial config for the container is needed:

# vzctl set 777 --applyconfig vps.basic --save

Setting container OSTEMPLATE[edit]

Also, we need OSTEMPLATE to be set in container configuration file, for the vzctl to work properly.

# echo "OSTEMPLATE=ubuntu-7.10" >> /etc/vz/conf/777.conf

Setting container IP address[edit]

For the container to be able to download updates from the Internet, we need a valid IP address for it:

# vzctl set 777 --ipadd x.x.x.x --save
Yellowpin.svg Note: if you use private IP for the container, you have to set up NAT as described in Using NAT for container with private IPs.

Setting DNS server for the container[edit]

For the container to be able to download updates from the Internet, we also need to specify a DNS for it:

# vzctl set 777 --nameserver x.x.x.x --save

Instead of x.x.x.x, specify the same IP that you have in your /etc/resolv.conf.

Starting container[edit]

Now start the container:

# vzctl start 777

Modify the installation[edit]

You have to do some things in order to modify the installation to better suit the environment it will be run in (i.e. a container).

First, enter a container:

# vzctl enter 777
Warning.svg Warning: Do not run the commands below on the hardware node, they are only to be run within the container!

Remove unneeded packages[edit]

Some packages does not make sense in a container, or are really optional. Remove those:

[container]# dpkg -P ubuntu-minimal wpasupplicant wireless-tools \
  udev pcmciautils initramfs-tools volumeid console-setup \
  xkb-data usbutils mii-diag alsa-base alsa-utils ethtool \
  module-init-tools linux-sound-base console-tools \
  console-terminus busybox-initramfs libvolume-id0 \
  ntpdate eject libasound2 pciutils tasksel tasksel-data \
  laptop-detect
Yellowpin.svg Note: On removing the deb-package "module-init-tools", a fake-modprobe is needed for IPv6 addresses, see below!

Note that the above list of packages may be too extensive. Say, if you want to use tasksel tool, do not remove it — but then you have to let laptop-detect stay.

Clean up after udev:

[container]# rm -fr /lib/udev

Disable getty[edit]

On a usual Linux system, getty is running on a virtual terminals, which a container does not have. So, having getty running doesn't make sense; more to say, it complains it can not open terminal device and this clutters the logs.

So, first of all we stop all getty processes:

[container]# initctl stop tty{1,2,3,4,5,6}

Next, we disable running getty. This can be done in two ways:

First way:

[container]# rm /etc/event.d/tty*

Second way:

[container]# dpkg -P system-services

Second way can be dangerous for future versions of system-services, but it's OK for now since the only service they carry is running gettys.

Set sane permissions for /root directory[edit]

[container]# chmod 700 /root

Disable root login[edit]

[container]# usermod -L root

"fake-modprobe" needed for IPv6 addresses[edit]

[container]# ln -s /bin/true /sbin/modprobe

On setup IPv6, the command "modprobe -Q IPv6" is called, which fails without the "fake-modprobe"

Get new security updates[edit]

[container]# apt-get update && apt-get upgrade

This didn't show anything for me, but might do something in the future.

Install some more packages[edit]

[container]# apt-get install ssh quota

Feel free to add packages which you want to have in a default template to this command.

Fix SSH host keys[edit]

This is only useful if you installed SSH above. Each individual container should have its own pair of SSH host keys. The code below will wipe out the existing SSH keys and instruct the newly-created container to create new SSH keys on first boot.

rm -f /etc/ssh/ssh_host_*
cat << EOF > /etc/rc2.d/S15ssh_gen_host_keys
#!/bin/sh
ssh-keygen -f /etc/ssh/ssh_host_rsa_key -t rsa -N ''
ssh-keygen -f /etc/ssh/ssh_host_dsa_key -t dsa -N ''
rm -f \$0
EOF
chmod a+x /etc/rc2.d/S15ssh_gen_host_keys

Disable sync() for syslog[edit]

Turn off doing sync() on every write for syslog's log files, to improve overall I/O performance. In Ubuntu this is already done for most log files and levels, so you can omit this step if you know what you are doing.

[container]# sed -i -e 's@\([[:space:]]\)\(/var/log/\)@\1-\2@' /etc/syslog.conf

Fix /etc/mtab[edit]

Link /etc/mtab to /proc/mounts, so df and friends will work:

[container]# rm -f /etc/mtab
[container]# ln -s /proc/mounts /etc/mtab

After that, it would make sense to disable mtab.sh script which messes with /etc/mtab:

[container]# update-rc.d -f mtab.sh remove

Disable some services[edit]

In most of the cases you don't want klogd to run -- the only exception is if you configure iptables to log some events -- so you can disable it:

[container]# update-rc.d -f klogd remove

Hostname[edit]

Set proper hostname:

[container]# echo "localhost" > /etc/hostname

Set /etc/hosts[edit]

[container]# echo "127.0.0.1 localhost.localdomain localhost" > /etc/hosts

Add ptys to /dev[edit]

This is needed in case /dev/pts will not me mounted after container start. In case /dev/ttyp* and /dev/ptyp* files are present, and LEGACY_PTYS support is enabled in the kernel, vzctl will still be able to enter container.

[container]# cd /dev && /sbin/MAKEDEV ptyp

Remove nameserver(s)[edit]

Remove DNS entries:

[container]# > /etc/resolv.conf

Clean packages[edit]

After installing packages, you'll have some junk packages laying around in your cache. Since you don't want your template to have those, this command will wipe them out.

[container]# apt-get clean

Cleaning up log files[edit]

[container]# cd /var/log
[container]# > messages; > auth.log; > kern.log; > bootstrap.log
[container]# > dpkg.log; > syslog; > daemon.log; > apt/term.log
[container]# rm -f *.0 *.1

Anything else?[edit]

Think of what else could be done to better suit your needs.

Exit from the container[edit]

Now everything is done. Exit from the template and go back to the hardware node.

[container]# exit

Preparing for and packing template cache[edit]

The following commands are to be run in the host system (i.e. not inside a container).

We don't need an IP for the container anymore, and we definitely do not need it in template cache, so remove it:

[HW]# vzctl set 777 --ipdel all --save

Stop the container:

[HW]# vzctl stop 777

Change dir to the container private:

[HW]# cd /vz/private/777

Now create a cached OS tarball. In the command below, you'll want to replace <arch> with your architecture (i386, amd64, ia64, etc). Note the space and the dot at the end of the command.

[HW]# tar --numeric-owner -czf /vz/template/cache/ubuntu-7.10-<arch>-minimal.tar.gz .

Look at the resulting tarball to see its size is sane:

# ls -lh /vz/template/cache
-rw-r--r-- 1 root root   53M Nov 15 12:40 ubuntu-7.10-i386-minimal.tar.gz

Testing template cache[edit]

We can now create a container based on the just-created template cache. Be sure to change i386 to your architecture just like you did when you named the tarball above.

[HW]# vzctl create 123456 --ostemplate ubuntu-7.10-<arch>-minimal

Now make sure that your new container it works:

[HW]# vzctl start 123456
[HW]# vzctl exec 123456 ps axf

You should see that a few processes are running.

Other tests that could be done are:

[HW]# vzctl enter 123456
[container]# ps axf
[container]# mount
[container]# dpkg -l
[container]# logout
[HW]#

Feel free to do more tests.

Final cleanup[edit]

Stop and remove the test container you just created:

[HW]# vzctl stop 123456
[HW]# vzctl destroy 123456
[HW]# rm -f /etc/vz/conf/123456.conf.destroyed

Finally, let's remove the container we used for OS template cache creation:

[HW]# vzctl destroy 777
[HW]# rm -f /etc/vz/conf/777.conf.destroyed

Updating the template cache[edit]

See Updating Ubuntu template