Basics of Debian Packages
Debian packages are easy installation packages for Debian or Debian-based distributions. This tutorial is divided into two parts; the parts Verification & Installation are destined to any user, and the parts Getting the package's code & How to Build to programmers or more advanced users.
Verification
Most GNU/Linux software is Libre Software, which means anyone can take its source code, modify it, and redistribute it. While this is a strength, it also opens the door for potential abuse — like inserting malicious changes. That's why verifying the package you're installing is important.
The most common way to verify a package is by checking its SHA hash.
What is SHA verification?
An SHA (Secure Hash Algorithm) creates a sort of digital fingerprint of a file. When a package is created, a hash is calculated. If the file changes — even by a single byte — the hash will be completely different. So, by comparing the hash of your downloaded file with the one provided by the developer, you can confirm whether the file was modified or not.
Repository vs Manual Downloads
If you've installed software on GNU/Linux before, you probably did it using a software repository —
either through a graphical app store or by using commands like apt install.
When you install this way, the system automatically checks the integrity and authenticity
of the packages in the background.
However, if you manually download a .deb file from a website, those automatic checks don't happen.
In this case, it's crucial to verify the file yourself using the SHA hash.
How to check it
Here are the steps to verify the SHA sum of a package:
- Download the
.debfile. - Find the expected hash (usually listed on the download page).
- Run this command in the terminal:
echo "<expected_hash> <file_path>" | sha256sum --check
If it says OK, it means the file matches the one provided by the source.
A note about signatures
Before 2016, Debian packages could be signed and directly verified using GPG signatures.
But the Debian teams, updated the architecture of the packages & repositories, and since
then individual .deb files are not directly signed.
Instead, developers sign the package set when they upload it to the official Debian repository. This signature is used to verify the repository's index files and after that, when you install a package, only its SHA hash is verified — the hash listed in the index is compared to the one of the downloaded file.
Installation
To install Debian packages, it is necessary to use a package manager, and in some distributions it's even possible to avoid using the terminal and install them by doing a double-left-click.
Personally, I rather do the installation from the terminal because sometimes the packages display messages (errors, warnings, etc...) that get hidden in graphical interfaces. It really depends on the distribution and the package manager, but in any case doing it from the terminal always provides the maximum amount of information.
On Debian systems, several package managers are usually available, such as dpkg, apt-get, and apt.
While dpkg is the low-level tool that installs .deb files, it does not automatically install dependencies,
which can cause errors for beginners.
The method I advise you, is to use apt, which will automatically install required dependencies and recommended packages.
For example, to install a local .deb package use apt install ./package.deb :
root@debian:/home/user/Downloads# apt install ./phantom-player-2.0.1.r48.g00054f5-all.deb
Note, selecting 'phantom-player' instead of './phantom-player-2.0.1.r48.g00054f5-all.deb'
Installing:
phantom-player
Installing dependencies:
gstreamer1.0-gtk3 python3-gi-cairo python3-magic python3-send2trash
Summary:
Upgrading: 0, Installing: 5, Removing: 0, Not Upgrading: 0
Download size: 0 B / 180 kB
Space needed: 1,135 kB / 2,170 MB available
Continue? [Y/n] y
Get:1 /home/user/Downloads/phantom-player-2.0.1.r48.g00054f5-all.deb phantom-player all 2.0.1.r48.g00054f5 [105 kB]
Selecting previously unselected package gstreamer1.0-gtk3:amd64.
(Reading database ... 196548 files and directories currently installed.)
Preparing to unpack .../gstreamer1.0-gtk3_1.26.5-1ubuntu2_amd64.deb ...
Unpacking gstreamer1.0-gtk3:amd64 (1.26.5-1ubuntu2) ...
Selecting previously unselected package python3-gi-cairo.
Preparing to unpack .../python3-gi-cairo_3.50.0-7_amd64.deb ...
Unpacking python3-gi-cairo (3.50.0-7) ...
Selecting previously unselected package python3-send2trash.
Preparing to unpack .../python3-send2trash_1.8.3-1_all.deb ...
Unpacking python3-send2trash (1.8.3-1) ...
Selecting previously unselected package python3-magic.
Preparing to unpack .../python3-magic_2%3a0.4.27-3_all.deb ...
Unpacking python3-magic (2:0.4.27-3) ...
Selecting previously unselected package phantom-player.
Preparing to unpack .../phantom-player-2.0.1.r48.g00054f5-all.deb ...
Unpacking phantom-player (2.0.1.r48.g00054f5) ...
Setting up python3-send2trash (1.8.3-1) ...
Setting up gstreamer1.0-gtk3:amd64 (1.26.5-1ubuntu2) ...
Setting up python3-magic (2:0.4.27-3) ...
Setting up python3-gi-cairo (3.50.0-7) ...
Setting up phantom-player (2.0.1.r48.g00054f5) ...
Processing triggers for gnome-menus (3.36.0-3ubuntu2) ...
Processing triggers for man-db (2.13.1-1) ...
Processing triggers for desktop-file-utils (0.28-1) ...
If after using the previous command, the dependencies aren’t installed, it means that the repositories don’t have the missing packages. You can then manually install them or add a repository.
The steps for adding a repository are the following:
- Add the repository into
/etc/apt/sources.list.d/debian.sources, or create a new file. -
If the repository is PGP signed:
-
Download the developer's PGP key and add it to your trusted keys
curl -fsSL https://example.com/repo-public.gpg | gpg --dearmor -o /usr/share/keyrings/example.gpg - Link the PGP key to the repository block, with the following line
Signed-By: /usr/share/keyrings/example.gpg
-
Download the developer's PGP key and add it to your trusted keys
- A repository block should look like the following:
Types: deb deb-src URIs: https://deb.debian.org/debian Suites: bookworm bookworm-updates Components: main non-free-firmware Enabled: yes Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
- Update the software list:
apt-get update - Install the missing packages:
apt-get -f install
Getting the package's code
Debian packages are basically divided into two contents; the software's files and the information for the package manager.
-
To get the software files, it is only necessary to decompress the package with any decompression tool like
p7zip, ex:7z x /path/to/the/deb. -
To obtain the package manager information, it is necessary to use
dpkg, ex:dpkg -e /path/to/the/debian.
Some distributions allow extracting the package by doing right-click > decompress
and sometimes even both parts are extracted.
How to build
The right way of building a Debian package is by using dpkg-buildpackage, but it may be a little bit complicated.
Instead, it is possible to use dpkg -b <folder>.
These are the basics for creating Debian packages with dpkg -b <folder path> for any binary or interpreted
language (Python, Bash, etc..):
-
Create a DEBIAN files & folders structure
ProgramName-Version/ ProgramName-Version/DEBIAN ProgramName-Version/DEBIAN/control ProgramName-Version/usr/ ProgramName-Version/usr/bin/ ProgramName-Version/usr/bin/executable_script
Here is an example of the control file. To create it, paste the following text into an empty file:
ProgramName-Version/DEBIAN/controlPackage: ProgramName Version: VERSION Architecture: all Maintainer: YOUR NAME <EMAIL> Depends: python3 (>=3.10), etc, Installed-Size: in_kb Homepage: https://foo.com Description: Here you can put a one line description. This is the short Description. Here you put the long description, indented by 1 space.
Remarks:
- The folder structure will be the structure of the program once it's installed.
-
Scripts placed at
/usr/bin/are directly called from the terminal, and their extension should not be added. This is the location where the main executable must be placed.As a general rule, if the program has multiple files, they should be placed under
ProgramName-Version/usr/share/ProgramName/all the files.For more information about this, you can read about the GNU-Linux structure since there are many locations for different stuff. For example, if the package is a python library, you will probably not have a script in
/usr/bin/and the python module shall be added to/usr/lib/pythonX.X/site-packages/python_module.py. -
It is possible to add pre-installation, post-installation, pre-removal scripts to the package. They only need to be added
inside the
DEBIANfolder with their respective name (preinst,postinst,prerm, etc..). -
For adding a graphical launcher (application icon), it is only necessary to create a
program_name.desktopfile into the applications folder/usr/share/applications/. To figure out the content of the file, sniff the files of your system's application directory, and you will probably find good examples.
-
Change all the folder permission to root
chown root:root -R /path/to/ProgramName-Version -
Change the script's permissions to executable
chmod a+x /path/to/the/scripts -
Finally, build the package
dpkg -b /path/to/the/ProgramName-Version
How to automate the build
Doing all the previous steps and filling the control file can become annoying and time-consuming.
That's why I created build-deb ,
it allows easily creating packages without doing any effort.
Additional Information
-
The article was published on August 8, 2014,
and last updated on Nov 23, 2025
- The section "PGP Signature" was replaced with "Verification" on May 18, 2025
- The section "Installation" was updated with the sources deb822 format on May 20, 2025
- The section "Installation" was simplified by replacing
dpkgwithapton Nov 23, 2025
- The preview image was taken from Packaging of Net Mono Application On Linux
.
- The content of this article is released under the CC BY 4.0
license.