As part of some recent project work, our team encountered the need to install an application remotely to a set of internationally spread developers using an Ubuntu environment. So to help spread some knowledge and serve as a resource for furture developers who may be sharing a similar problem – here’s how we learned to stop worrying and love the bomb debian packaging system.

For this guide I’m going to assume that you have a basic understanding of how Debian packages work from the consumer’s perspective – i.e. installing and removing packages using apt-get. In several portions below, I’ll be using dpkg and gdebi for installing the built packages locally.

Tools

There are only a couple of different tools used to build a Debian, I used the following:

  • dh-make – For initializing the debian directory
  • debhelper – For the actual packaging of the configured files
  • gdebi – For installing your package locally with dependencies
  • dpkg – The base means Ubuntu installs packages

If you don’t have some of these you should be able to get them via apt-get on your local package repository.

Understanding How a Debian is Built

While creating a Debian is fairly simple, I had a difficult time finding a decent step-by-step process for the things that need to be done and considered if your workflow is outside of the norm (build a simple package from source using a Makefile). This resulted in a lot of trial and error searching on my part, where I would realize I needed to do something my package wasn’t at the moment, search for a solution to that problem and repeat ad nauseam. While I don’t expect this to be complete, I do hope to head off many of the initial questions that I had about how things were roughly built.

Control File

The control file holds the package metadata which will eventually tell apt-get and other tools which package you are building, its dependencies, version, description – basically everything it can know. This file consists of a number of fields which each have a clearly defined purpose. While I won’t go into them in detail, their descriptions can be found here.

In general, you should complete all of the non-functional metadata in the control field and use the interrelationship fields only as needed. You’ll almost certainly need the depends, category however, so give those a read and apply them as appropriate.

Install File

Perhaps the hardest thing to search for information for was the Install file, which physically copies files from your debian directory to a location on disk. The following is a (contrived) example of the syntax:

relative/path/to/file /absolute/destination/path
I couldn’t get this to work with paths or wildcards, so I had to specify every file to be moved manually. You can do this with some command line-fu to make your life easier if your package was larger than mine.

Setup and Teardown Scripts

There are a number of scripts which, if created in the debian folder will happen at the designated step in the process. These scripts (preinst, postinst, prerm, postrm, etc) are not created by default, but make the process flexible enough to meet many needs. They can be used for a variety of things – generally preinst scripts stop running process, postinst restart them, and so on. These can do anything a normal shell script can do, just be sure to include the standard shell comment at the top.

Rules File

This file tells the debian how to ‘make’ the source directory. This file is simply another Makefile and can be modified according to that syntax.

Steps I Took

The following steps may be incomplete for use case, but they were everything that I needed to do to get up and running.

  1. Create and navigate to your desired Debian directory - If you’re using a real source directory you are mostly done.
  2. Run
    dh_make -s --indep --createorig
    - Your parameters may differ and I suggest you
    man dh_make
    before running with my arguments
  • This will create a ‘debian’ folder where you ran it. This folder contains all those file we just talked about.
  • One directory up from your source directory there will be a number of files that weren’t there before. They’ll be used when you actually package things up later. They aren’t a concern to you at the moment.
  1. Inside the ‘debian’ directory are a lot of *.ex files. You can do with these as you wish. I recommend having a look at some of them as an example and disposing of them afterwards.
  2. Modify the control file and any others you need to
  3. Run
    debuild -us -uc
    - Your parameters may differ, but these tell debuild to self-sign the package
  4. Remember those files one directory up from your source directory? There should now be a *.deb file amongst them. Hooray!
  5. Try and install it – you can choose your poison here - A basic
    sudo dpkg -i /path/to/*.deb
    does a barebones install and won’t do anything you didn’t tell it to do.
  • I prefer
    sudo gdebi *.deb
    This will do everything the dpkg command does, but will also try to use apt-get to fetch missing dependencies for you.
  1. Make sure everything looks kosher
    dpkg --get-selections | grep PACKAGE-NAME
    If it’s not there or doesn’t show as ‘Installed’ you’ll need to go back to step 4 and debug.
  2. Now that it’s installed check the actual files and make sure it works. If not, go back to step 4 and debug.
  3. Stress test it. Verify your package works in different environments – borrow a buddy’s VM and make sure it works over there. If not, (you guessed it) go back to step 4.

The End

That’s all I have for you. This should be sufficient to package whatever you want into a serviceable debian file. While this isn’t an exhaustive document, Google should be able to get you the rest of the way there with any more in depth questions. I hope this helps.