If you have worked with Linux for any length of time, you have had to deal with a Debian Packages. Have you ever seen what goes into making a Debian Package? It gets a little intimidating with all of the helper methods, and configuration necessary to make a well rounded deb. Lets not do any of that. Instead let’s explore the absolute minimum requirements to spit out a functional Debian Package… and maybe a few necessary bells and whistles.

Directory Structure

james@testbox:~$ mkdir -p example/DEBIAN
james@testbox:~$ touch example/DEBIAN/{control,changelog,copyright}

This is the minimum necessary directory structure to produce a debian package(.deb). Now we just need a control file, and some stuff to package as proof it worked.


james@testbox:~$ cat <<EOF  >> example/DEBIAN/control
> Package: james-example
> Version: 0.1
> Provides: james-example
> Section: headers
> Priority: optional
> Architecture: amd64
> Essential: no
> Depends:
> Installed-Size: 1M
> Maintainer: James <>
> Description: some example
james@testbox:~$ mkdir -p example/etc/
james@testbox:~$ echo "test" > example/etc/testfile

Here, we provided all of the metadata necessary to produce a dpkg. The metadata goes in a file called “control”. There are also various options here like dependencies that you should familiarize yourself with if you dont already know it.
We also added “testfile”, which we will use as a litmus test to confirm our package built what we intended. The absolute path on the target system, is dependent on the relative path here. For example, our build root is going to be ~/example. This means ~/example/etc, will become /etc on the target system.


james@testbox:~$ dpkg -b example james-example-0.1-0_amd64.deb
dpkg-deb: building package 'james-example' in 'james-example-0.1-0_amd64.deb'.
james@testbox:~$ dpkg -c james-example-0.1-0_amd64.deb
drwxr-xr-x james/james               0 2019-10-28 12:09 ./
drwxr-xr-x james/james               0 2019-10-28 12:14 ./etc/
-rw-r--r-- james/james               5 2019-10-28 12:14 ./etc/testfile

As you can see, the package built. Using the ‘-c’ parameter, we can spit out the contents of the deb, including our testfile.

Pre/Post Install (Optional)

You dont need a pre or post install for a deb to build. But just to round this out, lets talk about pre/post install scripts.
We have two locations to worry about
examples/DEBIAN/postinst examples/DEBIAN/preinst The names make it pretty obvious.

james@testbox:~$ cat <<EOF  >> example/DEBIAN/postinst
> #!/bin/bash
> touch /tmp/post_was_here
james@testbox:~$ dpkg -b example james-example-0.1-1_amd64.deb
dpkg-deb: building package 'james-example' in 'james-example-0.1-1_amd64.deb'.

We created a post install, and then rebuilt our dpkg to include the post install script. We didnt need to add any config, it just knows where it should be.

james@testbox:~$ sudo dpkg -i james-example-0.1-1_amd64.deb
[sudo] password for james:
Selecting previously unselected package james-example.
(Reading database ... 74802 files and directories currently installed.)
Preparing to unpack james-example-0.1-1_amd64.deb ...
Unpacking james-example (0.1) ...
Setting up james-example (0.1) ...
james@testbox:~$ ls -l /tmp
total 0
-rw-r--r-- 1 root root    0 Oct 30 13:09 post_was_here
james@testbox:~$ ls -l /etc/testfile
-rw-r--r-- 1 james james 5 Oct 28 12:14 /etc/testfile

Here, we installed our package. We can confirm the post install script ran, as the touch file was created in /tmp.


Honestly, the conclusion you should draw from this is that packaging is only as hard as you need to make it. If this is something you plan on doing long term, you may also want to check out the dh_* build helpers.