Written on December 28th, 2007.

Update: I’ve switched from Fedora Core to Debian, and I’m no longer maintaining packages by hand—Debian’s repository is great. Several people have pointed me to the GNU Stow program, which makes maintaining packages in the way described below quite a bit easier.

This site is hosted on a VPS running an outdated Fedora Core release. Upgrading Fedora Core between major versions is unsupported, and the previous attempt at upgrading failed horribly. Therefore, I’m stuck on this release.

This also means that there are no up-to-date packages anymore, so the only way to upgrade installed stuff is to compile it from source.

Managing Packages by Hand Sucks… usually

Usually, packages not maintained by the system or a package manager live in /usr/local. Using this location to install packages compiled from source is not a bad choice, because that way it can’t interfere with packages installed either by the system or a package manager.

One problem with this approach is that it is very hard to figure out what package a file belongs to. For example, what installed /usr/local/bin/spawn-fcgi? (Answer: lighttpd, not FastCGI). This makes uninstalling packages hard.

Uninstalling packages is not a problem when using a package manager, because nothing is easier than sudo pkg uninstall blah. Some source tarballs have a makefile with an “uninstall” target, which can be quite useful as well, but most makefiles don’t.

There is an easy way to make managing packages by hand a lot easier.

An Alternative Filesystem Hierarchy

As a small experiment, I’ve started using an alternative filesystem layout for managing packages I install from source. The idea comes from GoboLinux, which uses a drastically different filesystem hierarchy as well. Here’s what I do:

Every package lives in its own directory, and every version lives in its own subdirectory. For example, the latest version of Lighttpd is installed in /opt/pkgs/lighttpd/1.4.18. The lighttpd configuration file lives at /opt/pkgs/lighttpd/common/etc/lighttpd.conf since it’s not version-dependent.

This filesystem hierarchy doesn’t work right out of the box, though. To start an app, you have to specify the absolute path to the executable. Or, you can also adjust $PATH, but $PATH may grow to enormous proportions that way. I’ve decided to create /opt/bin and /opt/sbin directories with symlinks to the actual binaries.

Here’s an example of what my directories look like now:

/
    opt/
        bin/
            transmission-cli    (symlink)
            transmission-daemon (symlink)
            transmission-proxy  (symlink)
            transmission-remote (symlink)
        pkgs/
            lighttpd/
                common/
                    etc/
                        lighttpd.conf
                1.4.18/
                    bin/
                        spawn-fcgi
                    lib/
                        mod_access.la
                        mod_access.so
                    sbin/
                        lighttpd
                        lighttpd-angel
            transmission/
                0.96/
                    bin/
                        transmission-cli
                        transmission-daemon
                        transmission-proxy
                        transmission-remote
        sbin/
            lighttpd       (symlink)
            lighttpd-angel (symlink)

This filesystem layout has a few advantages:

This way of organising files is not entirely compatible with the Filesystem Hierarchy Standard. According to the FHS, The /opt directory can have subdirectories for each package, but packages can’t have subdirectories for each version. Also, configuration files for /opt have to be stored in /etc/opt. Whatever. I don’t care much about the FHS anyway.

You’d expect using such a different filesystem layout would break a lot of functionality, but I’ve been using this file hierarchy for a few days without any trouble at all.

Whether this alternative hierarchy really works well in the long run remains to be seen, but I’m optimistic. I’ll let you know how this worked out in a year or so.