2010-02-19

How to create a Debian/Ubuntu package (.deb) manually

This blog post gives some hints how to create a .deb package file (to be used with Debian, Ubuntu and similar Linux distributions). The intended audience is programmers and system administrators, both with a strong Debian or Ubuntu Linux background and strong scripting skills. It is assumed that you know almost everything about your Linux system, you have installed .deb packages by hand (with dpkg. and apt-get), you understand the dependencies etc., and the only information you need how to create a .deb package from your software.

This blog post describes a low-level, hacky and quick approach with little automatic validation and instrumentation. This approach is useful for packages which don't require compilation or complicated runtime configuration. To start learning the more consistent, heavy-weight, validated approaches, fetch some source packages with apt-get source, and have a look at their debian subdirectories. The merit of our approach is simplicity (you have to understand only a few basic concepts to create your first package) and speed. Disadvantages are that it lets you create suboptimal, nonworking or nonstandard packages since there is only very little automatic validation, so you may sometimes recognize problems with your .deb packages too late, when it's too expensive to fix them; also this approach doesn't force you learn and follow the conventions and best practices of your Linux distribution.

First, have a look at the contents of .deb packages similar to your software. To get the .deb file, use apt-get install --reinstall ${PACKAGENAME}, abort the process once all files are downloaded, and fetch the file you are interested in from /var/cache/apt/sources. Once you have the .deb file, extract it with dpkg-deb:

$ dpkg-deb -x .../${MYFILE}.deb /tmp/${MYFILE}
$ dpkg-deb -e .../${MYFILE}.deb /tmp/${MYFILE}/DEBIAN

Important text files are:

  • /tmp/${MYFILE}/DEBIAN/control: all meta-information: package name, size, version number, dependencies, short description, long description
  • /tmp/${MYFILE}/DEBIAN/md5sums: md5sum values for all regular files in the package
  • /tmp/${MYFILE}/DEBIAN/postinst: executable script which will be run by dpkg -i after dependencies are installed, and files of this package are extracted
  • /tmp/${MYFILE}/DEBIAN/preinst: a similar executable script
  • /tmp/${MYFILE}/DEBIAN/prerm: another similar executable script
  • /tmp/${MYFILE}/DEBIAN/postrm: another similar executable script

Use Google to find out more about these (and possibly other) special files. To get examples, look at the special files of the packages installed to your system; those special files are in /var/lib/dpkg/info.

Google is your friend. Search for how to build a debian package. The first two results I've found seem to be useful, I strongly recommend you read them: http://tldp.org/HOWTO/html_single/Debian-Binary-Package-Building-HOWTO/; http://www.linuxfordevices.com/c/a/Linux-For-Devices-Articles/How-to-make-deb-packages/. However, be prepared that some of the information you find is outdated or obsoleted. Always compare the instructions found on the web to what the packages of your distribution contain. Also be prepared that you don't find any definitive, comprehensive, up-to-date or useful documentation on a particular subtopic: learn from examples then.

Follow the these steps to create your .deb package:

  1. Learn everything you possible need to know, as indicated above. Learn primarily from examples (by examining some relevant packages on your Linux distribution).
  2. Create a directory named ${PACKAGENAME}_${VERSION}_${ARCHITECTURE}. We'll call this the package directory.
  3. Create subdirectories and files in the package directory. For example, if you want to have your package contain /usr/bin/footool, then create usr, create usr/bin and copy your prebuilt footool binary to usr/bin.
  4. Make sure the owner, group and permission bits are right (as intended on the target system) for all files and directories.
  5. Create the DEBIAN subdirectory in the package directory.
  6. Create your DEBIAN/control file, possibly copying a similar one, and modifying some fields.
  7. If you need to run some code during installation after the package files are extracted to /, then create DEBIAN/postinst as a script (usually starting with #! /bin/sh), and make it executable. To prevent future troubles, make this script robust and idempotent, i.e. it should exit successfully even after a previous half-finished package installation. However, if there is something wrong in the system, the script should exit with a non-zero exit code. set -e can help here: it makes the shell running the script exit at the first nonsuccessful command (outside a subshell).
  8. Compute md5sums by running md5sum `find . -type f | grep -v '^[.]/DEBIAN/'` >DEBIAN/md5sums in the package directory.
  9. Set the Installed-Size: field of the DEBIAN/control file to last number in the total output of du run in the package directory.
  10. Make sure that the package name, version number and architecture in the package directory name are the same is what's indicated in DEBIAN/control.
  11. Make sure there are no backup files (*~, especially DEBIAN/*~) or temporary files lying around inside the package directory.
  12. Go one level above the package directory, and run dpkg-deb -b ${PACKAGENAME}_${VERSION}_${ARCHITECTURE} . This creates ${PACKAGENAME}_${VERSION}_${ARCHITECTURE}.deb.
  13. Your .deb package is ready. Try installing it to your system (sudo dpkg -i ${PACKAGENAME}_${VERSION}_${ARCHITECTURE}.deb . Play with it. Fix problems and rebuild it as many times as necessary. Increase the version number.

4 comments:

Dima said...

Much easier to do a read deb source package!

You need debian/changelog debian/rules debian/control debian/compat debian/install

In changelog right debian-style changelog with versions numbers.

in contol write package meta-data. In compat just write "7"

in install list files relative to the top package directory and where you want them to end up.

In rules write:
%:
dh $@

Of if you want to build something or run some scripts

%:
dh $@
override_dh_auto_build:
make universe-explode

Then running dpkg-buildpackage will create an awesome fully compliant debian-source and debian binary packages!

By using bzr-buildpackage you can even keep this versioned tracked and build out of bzr using builddeb plugin!

Tyrael said...

to download a package, its easier to use the -d option of the apt-get:

-d Download only - do NOT install or unpack archives

for summing the output of du, you can use du -s its just prints the otherwise last line.

Tyrael

tarunno said...

Dude,

Thanks for your effort.

I have just notice a minor flaw in the command described in 8th step. It says: `find . -type -f it should be `find . -type f.

Thanks.

pts said...

@tarunno: Thanks, fixed.