So, I have been using LXC to host my server services for a period of time, with a view to keeping things portable should I need to change provider. It’s very good in that it’s integrated into the Linux kernel and in Ubuntu at least it’s not too difficult to setup, however there are a number of problems with it.
First and foremost, every time the container operating system upgrades anything to do with init scripts, it won’t boot any more, so you are forced to hold back packages with varying amounts of success. Secondly, there does seem to be some overhead running things in an LXC container, and thirdly it isn’t as portable as it could be i.e. there is no live migration. and you will have to change config files if you move hoster to reflect you new IP address.
As I’m not selling containers as VPS, I only need to run 1 server instance, and therefore don’t really need containerisation at all, enter schroot. Schroot is like chroot without the hassle and with added flexibility, in a nutshell it will mount and start everything correctly for you to the point where you can automate startup and running of services in the chroot, it doesn’t suffer from init script borkage since the init system isn’t used at all, and it’s more portable as networking is irrelevant to a chroot (it simply uses the hosts networking).
Ok so where to start, well if you are already using LXC you can use the directory your container is stored in. I opted to move mine to a sane location before starting, in the interests of convention and easy administration. So, I created a “schroot” directory in the /home directory i.e.
and moved the LXC container directory like so
mv /home/lxc/server/rootfs /home/schroot
Then we have to setup the schroot config file which lives in /etc/schroot/schroot.conf
The un-commented part of my file reads as follow
[lucid] type=directory description=Ubuntu Lucid directory=/home/schroot/rootfs users=root groups=root root-groups=root
We also need to edit “mount-defaults” so that it won’t overwrite existing user directories (you may already have data in user directories from the LXC container if you are using mail services in there) so
and it should read like this:-
# fstab: static file system information for chroots. # Note that the mount point will be prefixed by the chroot path # (CHROOT_PATH) # # <file system> <mount point> <type> <options> <dump> <pass> /proc /proc none rw,rbind 0 0 /sys /sys none rw,rbind 0 0 /dev /dev none rw,rbind 0 0 #/home /home none rw,bind 0 0 /tmp /tmp none rw,bind 0 0
Notice the “#” at the start of “/home” to comment that out.
We also want to comment out everything in the “nssdatabases-defaults” file as we have a full system inside the chroot and doing so will mean some services won’t start because of non-existent users. So
which should read:-
# System databases to copy into the chroot from the host system. # # <database name> #passwd #shadow #group #services #protocols #networks #hosts
You should be able to go into the chroot at this stage to confirm you have got everything right so far:-
schroot -c lucid
The prompt should change to indicate you are in the chroot. If everything worked you are ready to move on to the next level of ascension.
At this point we can start services and treat the chroot “nearly” like a separate system. Important things to note here are that everything is shared between the 2 systems except environment variables and filesystem, so for instance when you start a service that port is then in use as far as the host system and chroot are concerned, things are therefore only “logged” on the host system. Exit out of the chroot and continue on.
We can automate startup and shutdown of the chroot and services using some shell scripts inside /root of the chroot, so on my system
which depending on what services you want started will look like this:-
#!/bin/sh service amavis start service clamav-daemon start service courier-authdaemon start service courier-imap start service courier-imap-ssl start service courier-pop start service courier-pop-ssl start service fetchmail start service mysql start service nginx start service php5-fpm start service postfix start service postgrey start service zabbix-agent start service zabbix-server start
Don’t forget to make the script executable i.e.
chmod +x /home/schroot/rootfs/root/startupservices
Conversely make a stopservices script
!/bin/sh service amavis stop service clamav-daemon stop service courier-authdaemon stop service courier-imap stop service courier-imap-ssl stop service courier-pop stop service courier-pop-ssl stop service fetchmail stop service mysql stop service nginx stop service php5-fpm stop service postfix stop service postgrey stop service zabbix-agent stop service zabbix-server stop
and make that executable also. We make the chroot start and stop by adding the relevant commands to “/etc/rc.local”, for startup, and “/etc/rc0.d/schroot” and “/etc/rc6.d/schroot” for shutdown/reboot, again making the last 2 scripts executable using chmod.
So my /etc/rc.local reads:-
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. SESSION=$(schroot --begin-session -c lucid) schroot --run-session -c "$SESSION" -- /root/startservices exit 0
and /etc/rc0.d/schroot and /etc/rc6.d/schroot reads:
schroot --run-session -c "$SESSION" -- /root/stopservices schroot --end-session -c "$SESSION"
Reboot to test and I apologise if it’s borked. It’s important to note that you can go into the chroot at any time when after boot to change things by typing
schroot --run-session -c "$SESSION"