Building RPMs Without Root Access

This week at work I had the opportunity to build an RPM for some third-party software package.

My previous experiences with RPM date back to SuSE 5 almost ten years ago and I haven't touched it ever since. Packaging for Debian or even NetBSD is mostly a painless process, so I hoped today's RPM wouldn't be much different. Things worked out fine, except for one thing: RPM uses a well-known base directory (/usr/src/packages on SuSE) which only root can write to. Sure, you can pass ownership to another user, but without root access in the first place you're out of luck.

Using ~/.rpmmacros, users can define their own private staging area, but that's no elegant solution either. Not even The RPM Guide came up with a usable receipe for this.

After some unsuccessful experiments, I decided to have a look at how python's distutils solve this problem. With distutils, you can build RPMs from python packages (python setup.py bdist_rpm) without superuser privileges. That's why I figured it had to be possible.

Distutils uses rpmbuild's --define switch (undocumented in the man page) and the _topdir macro:

rpmbuild -ba --define "_topdir /path/to/staging_dir"
   /path/to/staging_dir/SPECS/package.spec

Note that /path/to/staging_dir has to be an absolute path, leading to the directory which contains the same directory structure /usr/src/packages has. `pwd` can be used to avoid hardcoding the path.

From a script, I create the directory structure in my local working directory, copy source tarball and spec file to SOURCES and SPECS and execute rpmbuild.

The created RPM can then be found in the RPMS directory.

social