Creating Debian Packages

For some time I'm now working with Debian Linux. Since I'm happy with it, I decided to create binary packages from the source I have.

Now, how are debian packages created? Of course, there is the Debian New Maintainers' Guide. I started reading it but soon I recognized that this explains package creation the "complete way". The guide shows how to "./configure && make && make install" an arbitrary (not neccessarily own) source package. Now my point of view is different: I have a simple (no "./configure") but well known (my own) source package which creates a few files that have to been installed. At this point I dropped more or less the official guide.

Before you read on, notice that:

  1. I'm not a Debian programmer/maintainer/expert/whatever,
  2. this is not an official Debian guide,
  3. this document is far from being complete or exact.

However I think it's helpful to understand to to create debian packages for some particular programs. It might meet your requirements or not.

So what are debian packages?

To put it simple, debian packages are simple ar(1) archives. An example:

> ls -l
total 28
-rw-r--r--  1 root root 26030 2006-01-12 18:50 tcpproxy_2.0.0beta12-1_i386.deb
> ar tv tcpproxy_2.0.0beta12-1_i386.deb
rw-r--r-- 0/0      4 Jan 12 18:50 2006 debian-binary
rw-r--r-- 0/0    426 Jan 12 18:50 2006 control.tar.gz
rw-r--r-- 0/0  25412 Jan 12 18:50 2006 data.tar.gz

see ar's manpage for the details. A debian package contains three files:

contains a archive format version number which is "2.0" (without the quotes).

a gzip'ed tar archive of some package control files.

the gzip'ed tarball of the package files. This is what is installed with apt-get or dpkg.

The archived data.tar.gz dosn't show anything special:

> ar p tcpproxy_2.0.0beta12-1_i386.deb data.tar.gz | tar tzvf -
drwxr-xr-x root/root         0 2006-01-12 18:50:11 ./
drwxr-xr-x root/root         0 2006-01-12 18:50:11 ./usr/
drwxr-xr-x root/root         0 2006-01-12 18:50:11 ./usr/sbin/
-rwxr-xr-x root/root     40756 2006-01-12 18:50:11 ./usr/sbin/tcpproxy
drwxr-xr-x root/root         0 2006-01-12 18:50:11 ./usr/share/
drwxr-xr-x root/root         0 2006-01-12 18:50:11 ./usr/share/man/
drwxr-xr-x root/root         0 2006-01-12 18:50:11 ./usr/share/man/man1/
-rw-r--r-- root/root     17793 2006-01-12 18:50:11 ./usr/share/man/man1/tcpproxy.1

It's really just what you want to have installed. The control.tar.gz contains some package control files:

> ar p tcpproxy_2.0.0beta12-1_i386.deb control.tar.gz | tar tzvf -
drwxr-xr-x root/root         0 2006-01-12 18:50:11 ./
-rw-r--r-- root/root       116 2006-01-12 18:50:11 ./md5sums
-rw-r--r-- root/root       244 2006-01-12 18:50:11 ./control

The file is md5sums optional, control is the only thing that is really required, it describes the package. Let's take a look at it.

> ar p tcpproxy_2.0.0beta12-1_i386.deb control.tar.gz | tar xzvf - ./control
> cat control
Package: tcpproxy
Version: 2.0.0beta12-1
Section: net
Priority: optional
Architecture: i386
Depends: libc6 (>= 2.2.4-4)
Installed-Size: 58
Maintainer: Wolfgang Zekoll <>
Description: tcpproxy is a transparent TCP proxy.

Since every debian package contains a control file you have lot's of other examples around. The Debian Guide, "4.1 `control' file" what can be put into the file and how it should be done exactly.

You could now start creating the required tar files on your own, write "2.0" to debian-binary, pack everything together with ar and put the result into your repository. Good idea but it's not working. Or better, it's not fully working. Packages created that way are accepted by dpkg, apt-get will download and install them but will tell that the package is "not a valid DEB package". There is obviously some "hidden magic" in debian archives and it took me some time to figure out how to create packages the right way.

How to create debian packages

After some research on the net I found the hint that the debian archive format should be handled with dpkg-deb and assuming that it's an ar compatible thing is not correct. Interesting. dpkg-deb's manpage explains how to create debian packages in plain words. First you need the directory tree of files you want to have installed (exactly what you would put into the data.tar.gz). In this tree's top directory (the tree's "root" directory) you create a directoy named "DEBIAN" where you put the control files (the files for control.tar.gz). The whole stuff is then packed togheter with a "dpkg-deb -b".

Assuming that I use the directory tmp to contains all this stuff files, then the recursive listing for the tcpproxy package would be

> ls -lR tmp
total 8
drwxr-xr-x  2 root root 4096 Jan 12 20:03 DEBIAN/
drwxr-xr-x  4 root root 4096 Jan 12 20:03 usr/

total 8
-rw-r--r--  1 root root 244 Jan 12 20:03 control
-rw-r--r--  1 root root 116 Jan 12 20:03 md5sums

total 8
drwxr-xr-x  2 root root 4096 Jan 12 20:03 sbin/
drwxr-xr-x  3 root root 4096 Jan 12 20:03 share/

total 40
-rwxr-xr-x  1 root root 40756 Jan 12 20:03 tcpproxy*

total 4
drwxr-xr-x  3 root root 4096 Jan 12 20:03 man/

total 4
drwxr-xr-x  2 root root 4096 Jan 12 20:03 man1/

total 20
-rw-r--r--  1 root root 17793 Jan 12 20:03 tcpproxy.1


> dpkg-deb -b tmp tcpproxy_2.0.0beta12-1_i386.deb

in the directory above tmp creates then a debian package that is fully (at least to my understanding) compatible to dpkg and apt-get - no more "not a valid DEB package".

Control files

Let's look at another example debian package.

> ls -l ftpproxy_1.2.1-1_i386.deb
-rw-r--r--  1 wzk wzk 74108 2006-01-12 20:21 ftpproxy_1.2.1-1_i386.deb
> ar p ftpproxy_1.2.1-1_i386.deb control.tar.gz | tar xzvf -

The control file describes the archive, what's in in which version and what is required to install it, see deb-control(5) for a full description. md5sums is optional, if present it should list the MD5 sums of the files in the archive:

> cat md5sums
821541451ad557337fdd0a886b0c8831  usr/sbin/ftp.proxy
536c2e9eb89bef73b8d3d3f2aaf7b58b  usr/share/man/man1/ftp.proxy.1.gz
f784fed7d69b95b87888e27468ace25a  usr/share/doc/ftpproxy/copyright
669566801ef2f4142235f66ff61352a6  usr/share/doc/ftpproxy/HISTORY.gz
aeb17e33a3a169fe4173aebfeb857d9c  usr/share/doc/ftpproxy/README.debian

This file can be created with

> md5sum `find . -type f | awk '/.\// { print substr($0, 3) }'` >DEBIAN/md5sums

from the package's top directory.

preinst, postinst, prerm and postrm are optional scripts that are run before or after the package has been installed or removed.

> cat postinst
#!/bin/sh -e
update-inetd --comment-chars "#disabled#" --disable ftpproxy
update-inetd --group OTHER --add "ftpproxy      stream  tcp     nowait  root    /usr/sbin/tcpd /usr/sbin/ftpproxy -e -l"
# symlink management generated by debstd
if [ "$1" = "configure" ]; then
  if [ -d /usr/doc -a ! -e /usr/doc/ftpproxy -a -d /usr/share/doc/ftpproxy ]; then
    ln -sf ../share/doc/ftpproxy /usr/doc/ftpproxy

This example modifies the system's inetd configuration. Other possible actions are e.g. starting a standalone daemon after installation or shutting it down before removing it.

There are more files that could be in the control.tar.gz, unfortunately explains the official Debian guide the files only in conjunction with the dh_ tools.

Other useful information

Some other documents you might want to read: