Creating a Debian Package

Wednesday , 14, August 2019

Ever wonder how to create packages for your operating system distro? I did – in fact for a long time I didn’t know much about how they worked – they just did. For linux users, life would be rough without these amazing helpers that keep track of versions and dependencies. They install, upgrade, remove and manage software and the repositories that software comes from.

Many of us just accept the packaging systems without learning how they do their magic. But what if you wanted to distribute a program across a group of machines in an automated way that managed the neccessary files and such in an easy way? We’re going to do that using the snow program we reviewed recently in our Digital Text Based Steganography post.

Package managers have been a fixture in the *nix world for many years. This includes *BSD using pkg, which has given way on OSX to homebrew – a serious upgrade from the predecessor MacPorts. In the linux world, Debian distros use dpkg and apt/apt-get to manage software. CentOS and Redhat use yum and rpm for software management, Arch linux uses pacman. Suse also has rpms but uses zypper to manage them. As you might have guessed from the title of this post, I’m going to be talking about apt and dpkg today – probably the most common package management systems in use today.

OK, first the basics of Debian package management, then we create one. dpkg interacts with software packages in all the basic ways, but is less convenient to use than apt for some common operations. dpkg will tell you all about a package and list files belonging to that package, or list all the packages you have on your system including the state of those packages. One reason you might want to build a package is to distribute your program, but even for programs that you did not write it saves a lot of time when installing on multiple machines. Packages can contain detailed sets of tasks to be performed including compiling, configuring and cleaning up after installing but we’re going to just stick to the basics in today’s post.

apt is the command typically used to manage the installation, removal and searching for software packages, although technically you can manage everything with dpkg. Installing software is easier with apt for example, because dpkg does not locate dependencies from your sources.list – it’s up to you to find and install dependencies which is why people use apt instead. apt has a sidekick, apt-get that does the same kind of things but is geared toward use in scripts. So if you’re at the command line apt is what you want to use, whereas remotely installing software on many machines is a task for scripting with apt-get.

I’d be remiss if I didn’t mention aptitude as well, which provides more detailed searching ability – specifically searching through package names and descriptions. I’m skipping entirely explanations of the actual common commands to install, purge, list and so on, as well as explanations about where files ar kept, caches, repository sources, backports and probably a dozen other things in order to keep this post manageable.

Today we’ll build a Debian package for distributing the snow program as mentioned earlier. We’ll do that in the easiest way, by packaging up a binary, so let’s first compile snow. Snow is trivial to compile, so let’s download and compile as shown below:

We begin making our package by creating a directory structure that replicates the target filesystem, so we can specify where our binary, man page, license info and the package install instructions will all go. So we’ll first create the directory structure, then create a few files we want to include in our package.
$ mkdir -p packages/{DEBIAN,usr/bin,usr/man/man1,usr/share/doc/snow}

Now that we’ve got our directory structure created, we can copy the snow binary into packages/usr/bin. Substitute usr/share or wherever you want to install the program on the target machines – I’m just going to install right into usr/bin.

Now let’s create the man page to include for all installations. Man pages are organized into sections 1-9 depending on what they’re for – user programs are section 1, hence the directory usr/man/man1 that we created. For more information about this, see
$ man man
If you look at your man page files, you’ll see that they’re all gzipped:
$ ls /usr/share/man/man1
so we’ll want to gzip ours too as soon as we create it.

Man pages use a simple markup with .TH for the title and .SH for section headers. In this case we have all the content we need on the snow website, so it’s just a matter of copy and paste, but for your own programs you’ll need to write this yourself. We use a text editor like vim, gedit, etc. to create the file:
with sections for NAME, SYNOPSIS, DESCRIPTION and so on using the website content:

Save the file and gzip it:
$ gzip -9 packages/usr/man/man1/snow.1
and we’re halfway there. Now let’s create the control file for Debian. dpkg will show you the metadata related to this package after installation if you type:
$ dpkg -l snow
Important things to note here are that the version number and architecture fields ar strict and need to be correct. To list architecture options, type:
$ dpkg-architecture -L
Note also that the description field should be less than 80 characters so it will fit in a single line in a terminal window.

Here are the contents of our packages/DEBIAN/control file:

Package: snow
Version: 20130616-1
Section: misc
Priority: optional
Architecture: amd64
Depends: libc6
Maintainer: Mike <>
Description: a program for concealing messages in text files

Now let’s create the license file and we’ll be ready to build our package. snow comes licensed using the Apache2 license, so we’ll edit the boilerplate text from their website. Just change the author name and date to the real values. In this case, 2013 and Matthew Kwan. Our packages/usr/share/doc/snow/copyright file looks like this:

Copyright 2013 Matthew Kwan
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.

That’s it – our directories and files should look like this, and we’re now ready to create our package using dpkg-deb but make sure that root user owns and group-owns all directories and files. After we create our package, we can check it by using the utility lintian which may or may not come installed on your distro. If it’s not installed already, it should be available from your repo.

$ sudo chown -R root.root packages
$ dpkg-deb --build packages snow-1.0-0-amd64.deb
$ ls -l snow-1.0-0-amd64.deb
$lintian -c snow-1.0-0-amd64.deb

Let’s install this new package and see if it works! Normally if you were installing this program on some machines on a local network you might setup a local repository and allow local machines to access it by HTTP. If you’re just following along at home with no other machines or VMs, then you can simply install the package on the same machine. Here is how it went when I did it:

Install this snow package by using: dpkg -i and look to see if there were any errors. Use dpkg -l to show details for installed packages.

As you can see, I checked the manpage and even ran the program to make sure everything looks kosher and it all checked out. If your results were similar then congratulations, you just created and used your first Debian package.