using pbuilder as a non-privileged user

pbuilder is a handy tool for making sure that your debian packages will build cleanly even on minimal systems.

how does pbuilder work?

It performs this process the way you'd expect:

  • create a minimal system
  • transfer the source into it
  • satisfy the minimal build dependencies for the source
  • build the package

Unfortunately, these steps (creating the system, satisfying build dependencies) tend to require superuser privileges, at least with the normal way that it works (which involves a chroot environment).

how does pbuilder-user-mode-linux work?

To avoid the need for superuser privileges, pbuilder can take advantage of User Mode Linux. UML is a way to run a separate version of the linux kernel as an unprivileged process within a completely isolated environment. With a little bit of configuration, you can perform a full pbuilder run as a regular user. Even better, UML supports a "copy-on-write" mode, which allows for easy rollback of changes for the virtual block device it uses. This means you don't need to re-create your minimal system each time you run pbuilder, which greatly speeds things up.

resolving dependencies without a real network stack

It's simple enough to run a UML kernel with a virtual block device. But when that kernel needs to talk to the network (e.g. to resolve build dependencies with apt), it needs to talk to the real network, not the virtual one. The common way to do this is to hook a virtualized serial device in the UML instance to a socket in the host filesystem, and then create a PPP link over that connection. If your non-privileged user is incapable of modifying the state of the network stack on the host system, the host side should be connected to a daemon like slirp, which is capable of doing the equivalent of NAT and then passing on most of the traffic to the outside world.


I created my pbuilder-uml setup like this:

mkdir ~/tmp
pbuilder-user-mode-linux create --eth0 slirp,12345,/usr/bin/slirp-fullbolt

And when i want to build version $VERS of a debian package named $FOO, i fetch the .dsc, orig.tar.gz, and diff.gz files, and do:

pbuilder-user-mode-linux update --eth0 slirp,12345,/usr/bin/slirp-fullbolt
pbuilder-user-mode-linux build --eth0 slirp,12345,/usr/bin/slirp-fullbolt --buildresult /home/dkg/tmp $FOO_$VERS.dsc

Things to note:

  • i'm not sure why pbuilder needs a ~/tmp directory to be present before creating the environment.
  • i explicitly specify that i'm using [DebianPacakge:slirp] for the network connection. Otherwise, i think UML will default to trying some sort of tunnel, which requires special privileges
  • i update the pbuilder instance before the build to make sure it's working against the current sid environment
  • i needed to specify --buildresult for the build phase, otherwise i got this error:
     -> mounting /dev/pts filesystem
     -> policy-rc.d already exists
    E: failed creating buildresult dir: 
     -> Aborting with an error
    It's not clear to me why this is necessary yet.


local resolving nameservers

I run a local resolving nameserver on the loopback of my host machine. This is reflected by an /etc/resolv.conf which points to This file gets copied into the UML instance, where it causes problems: since no local resolving nameserver is running within the UML instance, DNS requests attempt to contact the UML instance's loopback and then fail. (this is DebianBug:486747)

limitations of slirp

When you're using slirp as a non-privileged user to provide the UML instance connectivity with the outside network, there are some forms of traffic that cannot be adequately passed on, including for example ICMP echo requests (ping packets). This is because the part of the PPP connection on host side is still running as the non-privileged user, and regular users don't (and shouldn't) have raw access to the network interface. The reason normal users can emit pings on a typical unix machine is that /bin/ping is setuid root. slirp doesn't have this extra privilege, so it is limited to manipulating the host's IP stack through standard system calls, instead of emitting arbitrary ethernet frames or even IP packets.

Last modified 9 years ago Last modified on Jun 18, 2008, 1:21:21 PM