git-pbuilder cheat sheet. For a tutorial about the pbuilder stack (including git-pbuilder), see pbuilder. For general packaging information, see Packaging.
Contents
Usage
First, create an environment for use by git-buildpackage (e.g. when you call gbp buildpackage --git-pbuilder).
Initialization and Variants
You can create base images for any architecture (e.g. i386 or amd64) and distribution (e.g. bullseye (oldstable), bookworm (stable) or sid (unstable), Ubuntu xxx, ...) that your hardware can run on.
Normal Usage
Call git-pbuilder with no further options to create a sid (unstable) build environment with the architecture you are currently running on. For example, if you are using amd64, the environment will also be created for amd64:
git-pbuilder create
The base build image is created in /var/cache/pbuilder/base.cow/.
Creating packages for other architectures
If you want to explicitly create an i386 environment while running e.g. amd64:
ARCH=i386 git-pbuilder create
The base build image is created in /var/cache/pbuilder/base-sid-i386.cow/.
Creating packages for other releases
If you want to explicitly create a trixie environment while running e.g. sid:
DIST=trixie git-pbuilder create
The base image is created in /var/cache/pbuilder/base-[your-platform].cow/.
The updates and security mirrors are not available by default. Switch to mmdebstrap if you need such packages to be available in your environments.
The incoming, backports and experimental mirrors are not available by default. Include them manually if you need such packages to be available in your environments.
Using a Mirror
pbuilder runs several apt-get commands to upgrade and install packages. It maintains a package cache in /var/cache/pbuilder/aptcache/ that significantly reduces downloads, but may not be enough in some cases. For example, you might want to cache Release files from apt-get update, or might want to share a cache between all the devices on your network.
Install apt-cacher-ng then add this to your /etc/pbuilderrc:
APTCACHE=""
export http_proxy=http://127.0.0.1:3142
This will switch from pbuilder's built-in caching mechanism to apt-cacher-ng, both while building packages and while creating environments.
See also AptCacherNg.
Updating
When pbuilder builds a package, it starts by running apt-get update and apt-get upgrade. This will only take a few seconds when you first create an environment, but becomes increasingly time-consuming as your base image gradually falls behind.
Updating an environment in place can cause weird bugs, like config files not being updated as expected. Instead of calling pbuilder update, it's better to just delete and recreate your environments.
The best schedule for updating your packages depends on your personal workflow. For example, if you're a Debian developer who builds packages all day, you might want to automatically recreate each of your environments overnight. Or if you maintain a mature project and want to check each year's release builds properly, you might prefer to just build new environments as part of the release process and delete them once it's done.
Installing Extra Packages
Sometimes you need extra packages installed on the base image. This is helpful for working off-line or to speed up the packaging.
Here is one solution:
git-pbuilder login --save-after-login
# first step, update the package list
root@host:/# apt-get update
# then you can install any package
root@host:/# apt-get install vim screen less
You have to repeat those steps for each base image you use:
DIST=bullseye ARCH=amd64 git-pbuilder login --save-after-login
...
See add extra packages for solutions that suit other workflows.
Using Local Packages
Sometimes you need to build one package, then have the next package depend on it. For example, you might create a library and a service that uses the library.
First, create a local package repository (e.g. with reprepro).
Then, put your (public) signing key in the base of that repository:
# Fingerprint is the long string on the line below the line ending `[SC]`:
gpg --list-secret-key
gpg --export-options export-minimal --export <fingerprint> \
> /path/to/your/repo/signing-key.pgp
Then put something like the following in your /etc/pbuilderrc:
# Make local repo available to all environments:
BINDMOUNTS="$BINDMOUNTS /path/to/your/repo"
OTHERMIRROR="$OTHERMIRROR | deb [signed-by=/path/to/your/repo/signing-key.pgp] file:///path/to/your/repo ${DIST:-sid} main"
You will need to add the mirror to any existing environments manually. For example, by updating the /etc/apt/sources.list file in the environment.
if you would prefer to use a signing key in /usr/share/keyrings, pass --debootstrapopts --keyring=/usr/share/keyrings/<name>.pgp to your pbuilder create command.
Tips
Use of eatmydata
ccache caches compilations between runs, which can significantly reduce build times when you're trying to diagnose a packaging issue in a large compiled project.
Read ccache for general advice, then decide where to put your ccache directory. It's recommended to create a new directory like /var/cache/pbuilder/ccache, to avoid any risk of data from your local builds leaking into built packages. Wherever you put the directory, make it writeable by a user with UID 1234 and GID 1234.
Finally, add the following to your /etc/pbuilderrc:
export CCACHE_DIR="/path/to/your/ccache"
export PATH="/usr/lib/ccache:$PATH"
EXTRAPACKAGES="$EXTRAPACKAGES ccache"
BINDMOUNTS="$CCACHE_DIR"
You will need to manually install the ccache package in any environments you have already created, and should also run update-ccache-symlinks. See Add extra packages.
Using ccache
ccache caches compilations between runs, which can significantly reduce build times when you're trying to diagnose a packaging issue in a large compiled project.
Read ccache for general advice, then decide where to put your ccache directory. It's recommended to create a new directory like /var/cache/pbuilder/ccache, to avoid any risk of data from your local builds leaking into built packages. Wherever you put the directory, make it writeable by a user with UID 1234 and GID 1234.
Finally, add the following to your /etc/pbuilderrc:
export CCACHE_DIR="/path/to/your/ccache"
export PATH="/usr/lib/ccache:$PATH"
EXTRAPACKAGES="$EXTRAPACKAGES ccache"
BINDMOUNTS="$CCACHE_DIR"
You will need to manually install the ccache package in any environments you have already created, and should also run update-ccache-symlinks. See Add extra packages.
Creating a specific base chroot
Sometimes, you need to spend a lot of time with a single package. For example, you might be trying to fix a packaging error or debug a problem that only occurs in oldoldstable on i386. It would be useful to have an environment that already has your project's dependencies installed, so you can iterate over the problem more quickly.
Here's one way to create such an environment:
# Get build-dependencies of your project:
sed -n -e 's/[ \t()]//g' -e 's/,/ /g' -e 's/^Build-Depends://p' \
/path/to/your/project/debian/control
# Clone a base environment into a "-tmp" environment:
sudo cp -al /var/cache/pbuilder/base-oldoldstable-i386.cow \
/var/cache/pbuilder/base-oldoldstable-tmp-i386.cow
# Install extra packages in the "-tmp" environment:
sudo cowbuilder login --save-after-login \
--basepath /var/cache/pbuilder/base-oldoldstable-tmp-i386.cow
apt-get update && apt-get upgrade && apt-get -yy install <dependencies>
You can then use your -tmp environment like any other environment:
sudo cowbuilder build \
--basepath /var/cache/pbuilder/base-oldoldstable-tmp-i386.cow \
...
You can also start a shell in your environment:
sudo cowbuilder login \
--basepath /var/cache/pbuilder/base-oldoldstable-tmp-i386.cow \
--bindmounts "/path/to/your/project"
cd /path/to/your/project
make test
Delete the environment when you're done:
# Check for leftover mount points:
mount | grep /var/cache/pbuilder
sudo rm -rf --one-file-system /var/cache/pbuilder/base-oldoldstable-tmp-i386.cow
Troubleshooting
Slow copying and removing of the COW directory
What cowbuilder does is:
cp -al /var/cache/pbuilder/base.cow /tmp/new
rm -rf /tmp/[new]
Of course cowbuilder uses a different location than /tmp/[new]. You need to optimize those 2 commands on your computer. They should take no more than a few milliseconds each.
