Recently myself with help from Pino Toscano and Hilko Bengen rewrote supermin [git repo] to make it more featureful and robust. Supermin is a clever tool that lets you distribute very tiny (< 100K) Linux appliances, which are reconstituted to full appliances just before they run.
There’s an Adam West-era Batman film where the UN Security Council is dehydrated by The Penguin, leaving little piles of powder. Batman (sorry to reveal the ending here!) saves the day by adding water and rehydrating the UN. Supermin works in much the same way — by observing that you don’t need to store (eg)
/bin/bash in the appliance, since
/bin/bash already exists on the host. By just storing a pointer to
/bin/bash instead, you get the amazing compression ratios. Just add water.
Supermin 4 (the previous version) stored a list of filenames that would be copied into the full appliance. This was somewhat fragile if the host distro changed, eg. moving files around.
Supermin 5 stores the list of package names, and it resolves the dependencies and filenames using the RPM/dpkg/other package manager database just before reconstituting the full appliance. This solves the fragility problem completely. It also means we are now able to split libguestfs dependencies as described here.
Locking and caching
The other part of supermin which made it difficult to use in practice was locking, or rather the absence of locking. If you wanted to use supermin 4 from multiple threads, or multiple processes, you had the problem that they could race to build the full appliance potentially overwriting each other’s output. So you had to implement some sort of locking in the higher layers. And you also had to work out yourself if the full appliance needed to be rebuilt at all or if you could use a cached copy.
In supermin 5, locking and caching is now managed entirely by supermin itself and all the caller has to do is to pass two simple command line arguments:
supermin --build \
--lock /run/lock/supermin.lock \
and supply the location of a lock file. This also works if the application is multithreaded, and if the application wants to build multiple appliances (you supply a different lock file per appliance).
Supermin used to be called “febootstrap”. That was a bad, confusing name. However one feature that febootstrap had was the ability to build chroots, which we dropped in supermin. It turns out that lots of people liked building chroots for containers — indeed it is even the recommended way to build RHEL/CentOS 6 chroots for Docker.
Supermin 5 can build chroots again by selecting the
--format chroot output format. Here’s how you could build a chroot from scratch:
$ supermin --prepare -o /tmp/supermin.d \
$ supermin --build --format chroot \
-o /tmp/appliance.d /tmp/supermin.d
Tarballs, hostfiles, excludefiles
Supermin has always allowed you to customize the full appliance by specifying extra static files or host-copied files in the supermin appliance. However in supermin 4 you had to use a specially formatted cpio file to do this.
In supermin 5 you just use a regular tarball, eg:
$ tar zcf /tmp/supermin.d/init.tar.gz ./init
Supermin 5 also lets you specify files to be copied from the host. Just create a list of wildcards, one per line:
$ cat > /tmp/supermin.d/hostfiles <<EOF
Additionally you can specify a list of files to be excluded from the full appliance, which is useful for dropping documentation and other irrelevant stuff:
$ cat > /tmp/supermin.d/excludefiles <<EOF
For more information about supermin, read the supermin(1) manual page online. You can also build it from the git repository, and it is available in Fedora Rawhide and Debian/experimental.
Supermin 5 will be required for libguestfs ≥ 1.26 when it is released shortly.