In this post we learn how to create our first Debian package. We get lost in the maze of Debian documentation available out there. We try not to fall asleep reading these endless pages. And finally we succeed creating a simple yet beautiful Debian package.

PNMixer is being packaged here, as it’s a project I’m working on, and it’s indeed my first Debian package.


The most complete piece of information out there is the Debian New Maintainers’ Guide. If you’re a noob like me, you’d better take some time to read it. I refer to it often in this post.

We also use a little bit of the Debian Policy Manual.

The Overview of Debian Maintainer Tools can be a good reading.

I also found a good tutorial at this address, it’s quick but there are every steps you need:
How to create debian package from source

Installing stuff

We’re gonna use dh_make (dh stands for Debian helper) to make the package. Beware of the tricky naming, the package name has an hyphen while the binary has an underscore.

apt-get install dh-make

To package a software that uses autotools, we will need dh-autoreconf.

apt-get install dh-autoreconf

We will also need plenty of other utilities, and they all come from the devscripts package.

apt-get install devscripts

To check the package for errors, we will use lintian.

apt-get install lintian

Creating the package skeleton

Before using dh_make we may define some environment variables. dh_make will pick them up, and use them automatically, making our task easier. You can even add that to your .bashrc if you feel like packaging often.

export DEBEMAIL=''
export DEBFULLNAME='Your Name'

OK, so now, let’s grab the archive of the software we’re packaging.


Unpack it, enter the directory:

tar -xzf pnmixer-0.6.1.tar.gz
cd pnmixer-0.6.1

Then create the package skeleton.

dh_make --copyright gpl3 -f ../pnmixer-0.6.1.tar.gz

Here, you just have one question to answer: the type of package. A quick man dh_make will give you hints. For PNMixer, the package type is “single binary”.

dh_make created a debian sub-directory: this is the skeleton, holding all the files needed to build the package. You can have a look at it, don’t be shy.

ls debian

But also (and that’s a little bit unusual), dh_make created some files in the parent directory.

$ ls -1 ..

You have to get used to that, because that’s the way the Debian helpers work. So you’d better have a clean parent directory, otherwise you’ll be confused quickly. Just for you to know, the package will end up here after it’s built.

OK, now let’s start the real job: edit the skeleton files created by dh_make.

The control file


At first, the most important: read the doc I just mentioned :) Then, you can safely edit the control file:

vi debian/control

Start by filling the obvious fields, like Maintainer or Homepage. Uncomment the VCS-* fields if you intend to submit your package to Debian.

To fill the Section, have a look at the Debian list of sections.

It’s all easy to fill, except for the field Build-Depends. As you can see, it is already populated with a few things:

  • debhelper because we’re building the package using Debian helpers.
  • autotools-dev because PNMixer uses the autotools.

build-essential is not mentioned, but it is implicit for binary packages. It is mentioned here and here.

At first, if the package uses autoreconf, it is recommanded to use dh-autoreconf instead of autotools-dev. It is not clear in the documentation, but I was told to do so by a reviewer of my package. Then I found the Debian Autoreconf Wiki page, where everything is explained.

OK, so good-bye autotools-dev.

sed -i 's/autotools-dev/dh-autoreconf/' debian/control

Now we must add the other dependencies of our package. Libraries are probably easy to figure if you know well the program you’re packaging. But the exact list of build tools needed is more complicated than it seems.

Indeed, what exactly implies build-essential ? And dh-autoreconf ?


apt-cache show build-essential outputs an interesting line:

the real definition is in the Debian Policy Manual.

OK, where’s the Debian Policy ? I googled it, and after digging a little bit, here is the info we’re after:

The required packages are called build-essential, and an informational list can be found in /usr/share/doc/build-essential/list (which is contained in the build-essential package).

Alright, let’s have a look at the file !

vi /usr/share/doc/build-essential/list

From what I understand, it contains make, gcc and libc6-dev (the C standard library).


From the wiki page mentioned above:

In general dh-autoreconf is a superset of autotools-dev…

Ok, so let’s try to know more about autotools-dev. apt-cache show autotools-dev is our friend in this matter, let me quote it:

It also documents in /usr/share/doc/autotools-dev/README.Debian.gz best practices and guidelines for using autoconf, automake and friends on Debian packages. This is a must-read for any developers packaging software that uses the GNU autotools, or GNU gettext.

OK, let’s go there:

vi /usr/share/doc/autotools-dev/README.Debian.gz

It’s a big piece of writing, that I barely read to be honest. But from my average knowledge of what are the autotools, I assume it provides autoconf, automake and gettext.

what’s missing then ?

Alright, after this little hide & seek game through the documentation, let’s get back to our matter. What other build tool do I need for my package ? Answer is: pkg-config and intltool. I believe there not implied by any of the dependencies we just went through, so I wrote them down.


Figuring out the libraries you package need may be easy if it’s a little piece of software and you know it well. A quick look at the should tell you the truth. For PNMixer, I could write the libraries needed without the need of any tool.

However, being curious, I gave a try to dpkg-depcheck, as suggested by the Debian manual.

pkg-depcheck -d ./configure

The output is rather… crowded. It’s difficult to pick up the right things in such a long list. So, I don’t know if there a better tool for the job, but I was not really convinced by this one.

The final control file

Source: pnmixer
Section: sound
Priority: optional
Maintainer: My Name <>
Build-Depends: debhelper (>= 9), dh-autoreconf, pkg-config, intltool,
 libasound2-dev, libglib2.0-dev, libgtk-3-dev (>= 3.6), libnotify-dev, libx11-dev
Standards-Version: 3.9.6
Vcs-Git: git://

Package: pnmixer
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Simple mixer application for system tray
 PNMixer is a simple mixer application designed to run in your system tray.
 It integrates nicely into desktop environments that don't have a panel that
 supports applets and therefore can't run a mixer applet. In particular it's
 been used quite a lot with fbpanel and tint2, but should run fine in any
 system tray.
 PNMixer is designed to work on systems that use ALSA for sound management.
 Any other sound driver like OSS or FFADO, or sound server like PulseAudio
 or Jackd, are currently not supported (patches welcome).


OK ! Now it’s time to take care of the copyright file. Read the doc mentioned above, then edit the file and add what’s missing.

vi debian/copyright

Don’t forget to read the comments at the end of the file, and remove it afterward.

The changelog file


Easy to setup, just stick to the syntax and you’ll be fine. Here’s my changelog as an example:

pnmixer (0.6.1-1) unstable; urgency=low

  * Initial release (Closes: #745669)

 -- My Name <>  Sun, 06 Dec 2015 19:18:02 +0700

The bug number here is the ITP (Intent To Package) bug number. It makes sense if you want your package to make it to Debian upstream, and therefore follow the procedure for package submission.

The rules file


As you can see, this is a Makefile (hopefully you’re familiar with the syntax).

You can remove the rules.dh7 file, which is the same as rules.

Then, edit the rules file. You can remove everything that’s not needed, ie every comment line, to make the file more readable. I was told by a reviewer to remove also the two uncommented lines, so in the end there’s nothing left in the file, except the build rule.

Now, you may remember that earlier on this page, we decided to use dh-autoreconf instead of autotools-dev. It’s now time to make this change effective. Edit the main rule so that dh is invoked with autoreconf instead of autotools-dev.

#!/usr/bin/make -f

        dh $@  --with autoreconf

The docs file


Specify documentation files that should be installed. By default, it already includes some standard files. Just add other files if you want. As an example:

echo '' >> debian/docs

The man page


If your package doesn’t provide a man page, you should write one. Example files are provided, written in different languages, it’s up to you to pickup your favorite language and write your manual page. As a quick example:

cd debian
mv manpage.1.ex pnmixer.1
vi pnmixer.1
man -l pnmixer.1

Then, list your manual pages in the file package.manpages. So in our case, we just have one file to list:

echo 'debian/pnmixer.1' > debian/pnmixer.manpages

The watch file


The watch file is not so easy to setup. Some common upstream source sites are mentioned in the watch.ex file, but Github is not amongst them. However you can find more here:

To test your setup, type something like that:

uscan pnmixer-0.6.1 --report --verbose

The menu file

At the moment of this writing, it seems that the menu file shouldn’t be used anymore if your package already provides a desktop file. It was not very clear at the beginning. If you add a menu file, and check your package with lintian (see below), you will have this warning:

The command is listed both in a menu file and a desktop file
Per the tech-ctte decision on #741573, this is now prohibited.
Please remove the reference from the menu file.

But after removing the command line from the menu file, I get an error:

pnmixer: menu-item-missing-required-tag command usr/share/menu/pnmixer:5

Puzzled I was, and indeed, the messages are a little bit misleading. I had to dig the net, and I found a few interesting discussions on that matter. I’ll provide the links here for the sake of history, and for people who like to read IT stories :)

The last link tells the end of the story.

The other files

All the other exemple files that are unused should be removed. It’s best to use lintian (explained below) for that, it will help you in that process.

In the end, here is what my archive looks like:

$ ls -1 debian

Building the package

Now it’s time to build the package. If you’re lucky like me, the command will succeed at the first try.

dpkg-buildpackage -us -uc

Now have a look at the parent directory, this is where the package files are created:

$ ls -1 ..

You can have a look at the content of your packages with the debc command.

debc pnmixer_0.6.1-1_amd64.changes


You may want to try to install the package. The manual recommends to use the debi command:

sudo debi pnmixer_0.6.1-1_amd64.changes

Checking for errors


To check a package for errors, we use lintian. The basic command:

lintian -i -I --show-overrides pnmixer_0.6.1-1_amd64.changes

You will probably have warnings and errors, nobody gets it right the first time. Be patient and fix them one by one :)

More tips and tricks

Adding a missing file to the skeleton

Let’s suppose that, when you created your package skeleton for the first time, your forgot to specify the licence. How to add it afterward ? It’s really easy !

rm debian/copyright
dh_make --addmissing --copyright gpl3 -f ../pnmixer-0.6.1.tar.gz

Getting rid of the “useless dependency” warning

Let’s suppose you have this kind of warning messages when building the package:

dpkg-shlibdeps: warning: package could avoid a useless dependency if debian/pnmixer/usr/bin/pnmixer was not linked against ...

If you feel that you’re not responsible for this (ie, you’re not explicitely linking against an unused library), you can get rid of that by adding this line to the rules file:

export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed