For other-$WORK I am doing a bit of Debian packaging (prep-work) and upstream wrangling to bring some projects into a more-modern world. So now I have a Debian 13 workstation and need to build things for Debian Unstable without breaking my host system. On FreeBSD, this is a job for Poudriere. Here’s my notes on how I do something half-assedly similar on Debian (as usual, mostly documentation for “future me”).

As an example of something I’m updating, libaccounts is one. KDE is moving away from it, but there are other consumers.

The “Poudriere-alike” for Debian seems to be SBuild, and the instructions are quite extensive. For my rinky-dink use, though, the setup section is mostly-enough.

Start with a plain Debian 13 (Trixie) installation. I have one with KDE Plasma 6 Wayland on it, which is quite nice.

Creating a Tarball

These commands verbatim from the SBuild instructions, as my own local user:

sudo apt install sbuild mmdebstrap uidmap
mkdir -p ~/.cache/sbuild
mmdebstrap \
  --include=ca-certificates,cmake,git,gnupg,libqt6widgets6,libqt5widgets5 \
  --skip=output/dev \
  --variant=buildd \
  unstable \
  ~/.cache/sbuild/unstable-amd64.tar.zst \
  https://deb.debian.org/debian

This creates a tarball. The tarball includes whatever you tell it to install additionally – so I have a couple of typical-Qt-developer things listed.

This list isn’t nearly complete for anything like “Qt5 and Qt6 parallel-development”, because it is missing -dev packages and qmake and many other things. Debian packaging naming is an exercise in inconsistency, IMO, so it is always an adventure to figure out what I need.

The steps above are sort-of like creating a “base jail” in Poudriere. The tarball is a basic Debian Unstable that can be unpacked anywhere (creating a “jail”) and then used for whatever development work is needed. Unlike a jail, the unpacked tarball is just a chroot(1), so it doesn’t have special networking or other restrictions.

The chroot, once unpacked, is persistent. That means that stuff that is installed in it remains there and is available later. I don’t need to care about disk space, so it’s fine to litter my filesystem with multiple chroots, one for each project.

Extracting Tarball

Create a place for the chroot of a project, and extract the tarball there:

mkdir -p ~/src/chroot-libaccounts
sudo tar x --zstd -f ~/.cache/sbuild/unstable-amd64.tar.zst -C ~/src/chroot-libaccounts

GNU tar doesn’t have the advanced features of BSD tar which automatically understands the compression, so it needs to be specified by hand.

To enter the chroot, use sudo chroot ~/src/chroot-libaccounts. Since it’s persistent, it is probably worthwhile to update and upgrade it and maybe install additional packages, or whatever else one does with a Debian system.

Using a chroot with external sources

Inside the chroot is where builds happen. Outside the chroot is where the source lives, so I need to mount the source directory of whatever I’m working on, in the chroot. I do so before entering the chroot.

sudo mkdir ~/src/chroot-libaccounts/home/src
sudo mount --bind ~/src/libaccounts-qt/ ~/src/chroot-libaccounts/home/src
sudo chroot ~/src/chroot-libaccounts

Why not Docker?

Now that I’ve written this down in this detail, I realize that a suitable Docker image and container might have been what I was looking for. Well, almost: persistence is a thing. It’s a feature of Docker that the container re-starts in a pristine state every time. It’s an anti-feature for what I’m doing here. There’s ways of dealing with that, and I do so at $WORK. But not for this project.