How to create your .deb packages

How to create your .deb packages
.deb logo

You've just created a beautiful application and now you want to deploy it.

You may want to create your .DEB package

Create the folder structure

First, create the following structure (adapt the path /opt/sample-app to match your need)

sample-app
├── DEBIAN
│   ├── control
│   └── postinst
└── opt
    └── sample-app
mkdir sample-app/DEBIAN sample-app/opt/sample-app -p

The idea here is to recreate the structure of the target host that you want to create and/or copy files to.

Here we want to create the folder /opt/sample-app on the target server and copy our application inside it.

Next, copy your application into your sample-app/opt/sample-app folder

cp -r /home/user/sample-app sample-app/opt/sample-app/

Control your package

Now, create a control file that gives some information about your application:

vi sample-app/DEBIAN/control

with the following content:

Package: sample-app
Version: 2
Maintainer: John Malkovich
Architecture: all
Description: This app does some wonderful things

Installation process

You will often need to run a script to adjust the installation, such as changing file permissions and ownership, creating a database, or modifying a configuration file.

To do so create another file into the DEBIAN folder called postinst

vi sample-app/DEBIAN/postinst

Then, write your script inside it:

#!/usr/bin/bash

chown www-data:www-data /opt/sample-app -R

Change the permission of postinst to make it executable

chmod 0555 sample-app/DEBIAN/postinst

Removal process

Next we want to create two scripts to be able to remove the package cleanly, prerm and postrm.

prerm will perform some actions before removing any files, like stoping a service and ensuring the service is filly stopped before going any further.

postrm will remove all files of the package including links, logs, cache files, etc...

To do so create another file into DEBIAN folder called prerm

vi sample-app/DEBIAN/prerm

Then, write your script inside it:

#!/bin/bash

chown www-data:www-data /opt/sample-app -R

To do so create another file into DEBIAN folder called postrm

vi sample-app/DEBIAN/postrm

Then, write your script inside it:

#!/usr/bin/bash

chown www-data:www-data /opt/sample-app -R

Change the permission of postinst to make it executable

chmod 0555 sample-app/DEBIAN/postinst

Create your .DEB file

Finally, create your .DEB package using the dpkg-deb command:

dpkg-deb --build sample-app

This will create the file sample-app.deb

You can then install it using:

apt install ./sample-app.deb

You can list all installed packages using:

apt list --installed

And remove it using:

apt remove sample-app

That's it, you've now created your own .DEB package that you can distribute easily like a PRO.

Troubleshooting

If you are having some error when installing your package or recreate your package over and over, make sure to remove the cach files located in /var/lib/dpkg/info/ to make sure that the script of your package is used and not the cached file.

Professional package exemple

As it always a good idea to look how the PRO's are doing it, you can have a look at the php package to see how they handle installation and removal process.

wget http://security.debian.org/debian-security/pool/updates/main/p/php8.2/php8.2-fpm_8.2.26-1~deb12u1_amd64.deb
ar -x php8.2-fpm_8.2.26-1~deb12u1_amd64.deb  # Extract the content of .deb package
unxz control.tar.xz   # Uncompress the archive
tar -xvf control.tar  # Expand the .tar archive

Now you can edit the post* and pre* files and see how they are doing it.

ls -l
total 3468
-rw-r--r-- 1 root root     158 Nov 25 17:21 conffiles
-rw-r--r-- 1 root root    1316 Nov 25 17:21 control
-rw-r--r-- 1 root root   20480 Dec  8 11:25 control.tar
-rw-r--r-- 1 root root 1743156 Dec  8 11:25 data.tar.xz
-rw-r--r-- 1 root root       4 Dec  8 11:25 debian-binary
-rw-r--r-- 1 root root     665 Nov 25 17:21 md5sums
-rw-r--r-- 1 root root 1746424 Nov 26 10:03 php8.2-fpm_8.2.26-1~deb12u1_amd64.deb
-rwxr-xr-x 1 root root    3572 Nov 25 17:21 postinst
-rwxr-xr-x 1 root root    1753 Nov 25 17:21 postrm
-rwxr-xr-x 1 root root     409 Nov 25 17:21 preinst
-rwxr-xr-x 1 root root    1211 Nov 25 17:21 prerm
-rw-r--r-- 1 root root      41 Nov 25 17:21 triggers