This post is about creating a deb package to install on your Raspberry Pi, however it’s mostly applicable to any device running a debian based OS. In this post we’ll cover what a deb package is, how to create one and install it.
Before continuing I’d like to mentioned Ian Murdock, the Ian of debian, who passed away on 28th of December last year. Thank you for bringing debian into the world.
What is a deb Package?
I think Wikipedia best answers this question:
Debian packages are standard Unix ar archives that include two tar archives optionally compressed with gzip (zlib), Bzip2, lzma, or xz (lzma2): one archive holds the control information and another contains the program data.
Essentially they are a kind of installer. They contain meta data such as dependencies, conflictions, support platforms, version number, etc., as well as the actual package content itself mimicking the file structure to be installed into.
What is a Needed?
In order to create a deb package you’ll need a debian machine, this can be a Raspberry Pi however it may take some time to package. If you’re moving files from Windows to your debian machine then I also recommend using something like WinSCP to transfer them easily.
Creating a deb Package
1. File Structure
The first step is to create working directory to use for packaging. In this folder you should only place files you intend to include in your package. Excluding one special directory, which we’ll cover in a moment, everything in here will be deployed to the target machine in the same folder relative to the root drive.
The above example shows our working directory, called package-folder in your home directory, and two files in separate locations with our special directory and control file. When this package is installed program.exe will be deployed into /usr/bin and the Program script will be deployed into /etc/init.d. The first directory shown above is where our meta data and deployment scripts will be located: these are not unpacked on to the target machine except for execution during deployment.
2. Installation Scripts
During the deployment there are a few scripts that can be ran, these occur before and after installation or removal. They are located in a folder called DEBIAN, as shown in step one. Here are four common scripts I’ve used before:
DEBIAN/preinst – Executed before installation
DEBIAN/postinst – Executed after installation
DEBIAN/prerm – Executed before removal
DEBIAN/postrm – Executed after removal
These files are bash scripts which are optional to the package, they don’t need to be included however it’s likely you’ll need at least one of the install and removal scripts.
When writing these scripts it’s important to remember they must be stored using Unix line ending; if you’re creating them on Windows notepad++ can save files using EOL Unix by going to Edit -> EOL Conversion -> UNIX/OSX Format.
Furthermore they must be executable before packaging, so that when they are unpackaged on the host machine they can be executed. You can do this by running the following command:
chmod +x DEBIAN/postint
3. Package Information
In order for the host machine to understand what is included in this package you will need a control file. As with the instillation scripts above this is located in the DEBIAN folder, however this file is required for packaging.
Section: custom Priority: optional Architecture: armhf Essential: no Installed-size: 1024 Depends: mono-complete (&amp;amp;amp;amp;amp;gt;=3.2.8), cron, ftp Maintainer: 2PersonGames [firstname.lastname@example.org] Description: Example package for my blog.
Above is an example control file. Most of these are self-explanatory, however the important ones of note here are architecture, depends and pre-depends (not shown).
Depends and pre-depends are very similar, both declare what other packages are required to be installed before continuing. However, where apt-get will install all these dependencies regardless dpkg will halt installation if you are missing any pre-depends.
The architecture denotes what architecture of debian your package supports, e.g. armhf, amd64, i386, all, etc. Because C# compiles to MSIL it’s likely that your executable will run on anything that mono runs on.
The last step is to package everything into a .deb. To do this navigate to into working directory and run the following command:
dpkg-deb --build ./ "mypackage_18.104.22.168_armhf.deb"
This will output a .deb package containing everything in the working directory of the name mypackage_22.214.171.124_armhf.deb.
The name of this has three important parts: first the name of the package, this identifies the package so that if you install a different version later debian knows it’s the same package.
Second the version, in the above example it’s 126.96.36.199, but it can of course be any numbers you wish. Although dpkg will install whatever you ask it to over the top of existing packages, when using apt-get to install updates it will recognise version numbers greater than others and find the package of the greatest verison number.
Third the architecture, this is the same as mentioned in the control file.
Installing Your deb Package
The easiest way to install your package is to copy it to the target machine and run the following command:
dpkg -i mypackage_188.8.131.52_armhf.deb
This will install your package and overwrite any existing package of the same name.
You can use apt-get install to install your package, however it must be hosted on an apt repository included in /etc/apt/sources. This is a bit more complicated, however it’s necessary for deploying updates over the internet in an easy manner.
Setting up and using an apt repository will be covered in the next post.