1. Overview
Debian packages, often referred to as .deb packages, are a common way to distribute software on Debian and Debian-based Linux distributions such as Ubuntu and Linux Mint.
In this tutorial, we’ll see how to unpack, modify, and repack a .deb package to suit our specific needs or to fix problems.
2. Prerequisites
To follow this tutorial, we’ll need the dpkg-deb tool, which is usually installed by default on Debian-based distributions, as it’s a basic tool for handling packages. However, if it’s missing, we can install it using apt:
$ sudo apt install dpkg
We can download the .deb package we want to modify from an official or third-party repository. As a test case, we’ll modify the fonts-aenigma package provided by the Ubuntu jammy repository (compatible with Ubuntu 22.04 and Linux Mint 21):
$ mkdir deb
$ cd deb
$ wget -O 'fonts-aenigma-original.deb' \
'http://mirrors.kernel.org/ubuntu/pool/universe/f/fonts-aenigma/fonts-aenigma_0.0.20080511+dfsg-4_all.deb'
The same .deb is also available in other Ubuntu and Debian repositories.
This package installs 465 free fonts from Brian Kent. Our goal is to add another font to the package, the public domain Operation Napalm Font by GGBotNet:
$ wget https://get.fontspace.co/download/family/gx6w9/bf43cdbfcb454b8dbf5c56fd74d1a93a/operation-napalm-font.zip
[...]
$ 7z x operation-napalm-font.zip
[...]
$ tree
.
├── fonts-aenigma-original.deb
├── info.txt
├── operation-napalm-font.zip
├── OperationNapalmItalic-1GgAv.ttf
└── OperationNapalm-nRBWO.ttf
As we can see from the last output, this font consists of two .ttf files.
As a side note, we used 7z v.16.02 with this particular .zip file because Debian’s unzip v.6.00 produces unreadable data.
3. Unpacking the .deb Package
To unpack a .deb package, we need to use the dpkg-deb command with the -R (–raw-extract) option, followed by the .deb filename and the target directory that dpkg-deb will create if it’s missing:
$ dpkg-deb -R fonts-aenigma-original.deb debdir
Let’s take a look at the unpacked contents:
$ tree debdir
debdir
├── DEBIAN
│ ├── control
│ └── md5sums
└── usr
└── share
├── doc
│ └── fonts-aenigma
│ ├── 1015saturdaynight.txt
│ ├── 36daysago.txt
[...]
└── fonts
└── truetype
└── aenigma
├── 1015snr.ttf
├── 1015sn.ttf
[...]
8 directories, 761 files
Let’s discuss this directory structure and contents:
- DEBIAN/control → metadata and package control information, specifying details about the package, its dependencies, and other installation-related information
- DEBIAN/md5sums → MD5 checksums for the files in the package, used to verify the integrity of the package during installation
- usr/share/doc/fonts-aenigma → documentation for each font in a separate .txt file
- usr/share/fonts/truetype → directory where TrueType fonts are typically stored on a Debian-based system
- usr/share/fonts/truetype/aenigma → main directory for the Ænigma font family, containing all the TrueType (.ttf) font files
Other packages have more complex structures, including configuration scripts.
For a detailed view of package meta-information, we can consult The Debian Administrator’s Handbook.
4. Modifying Package Contents
Our changes should follow Debian conventions as well as any conventions adopted by the package maintainer.
4.1. Add the New Files
First, let’s move the two extra ttfs into the same folder where all the other ttfs are:
$ mv *.ttf ./debdir/usr/share/fonts/truetype/aenigma
Then, let’s do the same with the documentation. In this case, it’s the same for both ttfs:
cp info.txt ./debdir/usr/share/doc/fonts-aenigma/OperationNapalmItalic-1GgAv.txt
mv info.txt ./debdir/usr/share/doc/fonts-aenigma/OperationNapalm-nRBWO.txt
As an optional extra check, we can verify that the permissions of the added files are the same as those of all other files in the package.
4.2. DEBIAN/control
Before we go any further, let’s take a look at the contents of DEBIAN/control:
$ cat ./debdir/DEBIAN/control
Package: fonts-aenigma
Version: 0.0.20080511+dfsg-4
Architecture: all
Maintainer: Ubuntu Developers <[email protected]>
Original-Maintainer: Debian Fonts Task Force <[email protected]>
Installed-Size: 23873
Conflicts: ttf-aenigma
Breaks: ttf-aenigma (<< 0.0.20080510.dfsg-3)
Replaces: ttf-aenigma (<< 0.0.20080510.dfsg-3)
Section: fonts
Priority: optional
Multi-Arch: foreign
Description: 465 free TrueType fonts by Brian Kent
Fonts included in this package:
.
* 10.15 Saturday Night, R
* 18 Holes
[...]
All these elements in the DEBIAN/control file are described in detail in the Debian Policy Manual. In order for our distribution to understand that our custom package replaces the original one, we need to give it a different version number:
$ sed -i 's/Version: 0.0.20080511+dfsg-4/Version: 0.0.20080511+dfsg-4+custom1/' ./debdir/DEBIAN/control
$ cat ./debdir/DEBIAN/control | grep "Version: "
Version: 0.0.20080511+dfsg-4+custom1
Let’s take a closer look at the version numbers used by Debian:
- 0.0.20080511+dfsg is the upstream version
- 4 is the Debian revision number of the original package
- +custom1 indicates that we’ve made custom modifications to the package
We can increment the +custom part each time we make further modifications to our custom version to keep track of the changes.
4.3. DEBIAN/md5sums
The DEBIAN/md5sums file is formatted in a standard way:
$ cat ./debdir/DEBIAN/md5sums
2209cebd6e707ff1abf24a7bd08861a3 usr/share/doc/fonts-aenigma/1015saturdaynight.txt
02117ed270377b6e4163e58697de615b usr/share/doc/fonts-aenigma/36daysago.txt
15000f8ff84238312a20ed7f3c76d7c3 usr/share/doc/fonts-aenigma/3dlet.txt
[...]
Let’s rebuild it:
$ cd debdir/
$ find . -type f -not -path "./DEBIAN/*" -exec md5sum {} + | sort -k 2 | sed 's/\.\/\(.*\)/\1/' > DEBIAN/md5sums
This command regenerates a DEBIAN/md5sums identical to the original, except for the addition of the new files:
- Finds all files in the current directory and its subdirectories, excluding the DEBIAN subdirectory
- Runs the md5sum command on each file and prints the checksum and file path
- Sorts the output by the second column, which is the file path, in alphabetical order
- Removes the ./ prefix from each file path using sed
- Redirects the final output to the DEBIAN/md5sums file
Now we’ve finished the changes.
Let’s note that if the original .deb package had included a Debian changelog, we’d have had to change that as well.
5. Repacking and Testing the Modified Package
We are ready to create the new package using the -b (–build) option of dpkg-deb:
$ cd ..
$ ls
debdir fonts-aenigma-original.deb operation-napalm-font.zip tree.txt
$ dpkg-deb -b debdir fonts-aenigma-custom.deb
dpkg-deb: building package 'fonts-aenigma' in 'fonts-aenigma-custom.deb'.
Let’s use fc-list to verify that the Operation Napalm font we added to the original package isn’t currently installed:
$ fc-list | grep Napalm
Let’s install our custom package and repeat the font check:
$ sudo apt install ./fonts-aenigma-custom.deb
[...]
Note, selecting 'fonts-aenigma' instead of './fonts-aenigma-custom.deb'
The following packages will be upgraded:
fonts-aenigma
1 upgraded, 0 newly installed, 0 to remove and 16 not upgraded.
[...]
Get:1 /home/francesco/deb/fonts-aenigma-custom.deb fonts-aenigma all 0.0.20080511+dfsg-4+custom1 [8.352 kB]
[...]
$ fc-list | grep Napalm
/usr/share/fonts/truetype/aenigma/OperationNapalm-nRBWO.ttf: Operation Napalm:style=Regular
/usr/share/fonts/truetype/aenigma/OperationNapalmItalic-1GgAv.ttf: Operation Napalm:style=Italic
apt correctly recognized our custom .deb package as an update to the original. Also, everything worked as expected because the two new ttfs were installed.
6. Conclusion
In this article, we discussed how to use the dpkg-deb tool, which is part of every Debian-based system, to unpack, edit, and repack the contents of a .deb package. It’s helpful for fixing problems, adding features, or customizing software on Debian-based systems.
In our example, we strictly followed Debian conventions to ensure the integrity and functionality of our custom package:
- The new files respected the structure and contents of the original .deb package
- The new version number in DEBIAN/control was recognized by Debian as a custom update
- We created a new DEBIAN/md5sums file to reflect the changes
Finally, we installed our custom package and verified its functionality. Our changes had the desired effect, and the package interacted correctly with the system.