Ubuntu Hardy template creation
This article summarizes the experience of creating Ubunty Hardy Heron (a.k.a. 8.04) template for OpenVZ.
Template creation is based on debootstrap, and the procedure is similar to Ubuntu Gutsy template creation, but it differs in some subtle details.
Contents
Prerequisites
debootstrap
You have to have a debootstrap
working for Hardy, i.e. you should have
debootstrap
and its dependencies/usr/lib/debootstrap/scripts/hardy
file
The simplest way to have it all is to work on an Ubuntu Hardy 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
You need vzctl-3.0.22 or later to work with Ubuntu Hardy Heron. If vzctl-3.0.18 or earlier is used, you will not be able to run your Ubuntu Hardy 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/rc.local.
Creating template
Running debootstrap
Create a working directory:
[HW]# mkdir hardy-chroot
Run debootstrap to install a minimal Ubunty Hardy system into that directory:
[HW]# debootstrap [--arch ARCH] hardy hardy-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
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.
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
You should move the contents of hardy-chroot
directory into new container private area, like this:
# mv hardy-chroot /vz/private/777
Setting container config
An initial config for the container is needed:
# vzctl set 777 --applyconfig vps.basic --save
Setting container OSTEMPLATE
Also, we need OSTEMPLATE
to be set in container configuration file, for the vzctl to work properly.
# echo "OSTEMPLATE=ubuntu-8.04" >> /etc/vz/conf/777.conf
Setting container IP address
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
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
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
Now start the container:
# vzctl start 777
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 container).
First, enter a container:
# vzctl enter 777
Warning: Do not run the commands below on the hardware node, they are only to be run within the container! |
Remove unneeded packages
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 console-setup \ xkb-data usbutils mii-diag ethtool \ module-init-tools console-tools \ console-terminus busybox-initramfs libvolume-id0 \ ntpdate eject 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 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
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 the 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 getty
s.
Set sane permissions for /root directory
[container]# chmod 700 /root
Disable root login
[container]# usermod -L root
"fake-modprobe" needed for IPv6 addresses
[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
[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
[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
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
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
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
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
Set proper hostname:
[container]# echo "localhost" > /etc/hostname
Set /etc/hosts
[container]# echo "127.0.0.1 localhost.localdomain localhost" > /etc/hosts
Add ptys to /dev
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
Note: the warning "/sbin/MAKEDEV: warning: can't read /proc/devices" is safe to ignore.
Remove nameserver(s)
Remove DNS entries:
[container]# > /etc/resolv.conf
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.
[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?
Think of what else could be done to better suit your needs.
Exit from the container
Now everything is done. Exit from the template and go back to the hardware node.
[container]# exit
Preparing for and packing template cache
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 czf /vz/template/cache/ubuntu-8.04-<arch>-minimal.tar.gz .
Look at the resulting tarball to see its size is sane (i.e. tens of megabytes):
# ls -lh /vz/template/cache/ubuntu-8* -rw-r--r-- 1 root root 46M May 13 12:20 /vz/template/cache/ubuntu-8.04-i386-minimal.tar.gz
Testing template cache
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-8.04-<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
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