Introduction
Debian Package tool dpkg
is used on Debian, Ubuntu, Kali, Linux Mint,
and other Debian based Linux distributions.
This tutorial covers the basics of creating custom .deb
packages
and managing them with dpkg
and apt
.
We will cover the process of creating your own deb
file to distribute
your package easily.
It is aimed at people who are interested in learning the basics of
creating and managing packages in Debian based distributions.
Read more about
The .deb file format
A .deb
file is a Debian package, but really it is just a standard
Unix archive (.ar
) file.
The dpkg
tool is the Debian package manager and apt
is a higher level
tool for managing packages which uses dpkg
under the hood.
List installed packages
List packages with dpkg
or apt
:
dpkg -l # List installed packages
dpkg -s mypkg # Get status of specific package
apt list --installed # List installed packages
apt list # List *all* packages in available repos
Create a package
You can make and distribute your own .deb
package very easily.
To start fresh, create a new directory named after your package.
For example, mypkg
.
This directory will store the package metadata and the package contents.
Inside the project directory, there needs to be one special
directory (DEBIAN
) with one special file inside it (control
).
Read more about Debian control file fields.
# Minimum required structure for a package
mypkg-1.0.0/ # Directory
└── DEBIAN/ # Directory
└── control # File
A more practical example with a post-installation script:
mypkg/ # Directory
├── DEBIAN/ # Directory
│ └── control # Control file
│ └── postinst # Post install script
├── etc/my.ini # Optionally any other files that you need to include
└── opt/mylib/ # on the destination system during installation
This is a minimal example of the DEBIAN/control
file:
Package: mypkg
Version: 1.0.0
Maintainer: Your Name <you@example.com>
Description: My test package, please ignore
Homepage: https://github.com/username/projectname
Architecture: all
Depends: git, python3 (>=3.5), openjdk-8-jre-headless|openjdk-8-jre|openjdk-8-jdk-headless|openjdk-8-jdk
The Depends
line is optional, but frequently needed.
The example above shows how to add multiple dependencies,
how to specify a minimum version with python3,
and how to add a dependency that is satisfied by one of many options.
There are many versions of java listed and any one will satisfy the requirement.
If none of them are installed, it will start from the first
one in the list and try to install it.
This way, it will work if the user has version 8 of the JDK or JRE in full or headless variant.
If none of them are installed it will install the smallest version (the headless jre).
Build the package by running dpkg -b
on the project directory like this:
# Build mypkg directory in to .deb package
dpkg -b ./mypkg ./mypkg_1.0.0-0_amd64.deb
# Naming format: <name>_<version>-<release>_<arch>.deb
# Version is the version number of the app being packaged
# Release number is the version number of the *packaging* itself.
# The release number might increment if the package maintainer
# updated the packaging, while the version number of the application
# being packaged did not change.
# Inspect information like size, version, dependencies
dpkg -I mypkg.deb
# Example output of `dpkg -i mypkg.deb`
new debian package, version 2.0.
size 666 bytes: control archive=301 bytes.
238 bytes, 6 lines control
Package: mypkg
Version: 1.0.0
Maintainer: Your Name <you@example.com>
Description: My test package, please ignore
Architecture: all
Depends: git, python3 (>= 3.5), openjdk-8-jre-headless|openjdk-8-jre|openjdk-8-jdk-headless|openjdk-8-jdk
It's a special little package, but it's lonely without any files to install. Normally a package has some contents like a shared library, man pages, documentation, an executable program, or systemd service files.
The next thing we'll need to do is add files to the package. Some examples of things you might include are:
- an executable or a shell script launcher in
/usr/local/bin/
- man pages in
/usr/share/man
- configuration files in
/etc/
- libraries in
/usr/local/lib
- header files in
/usr/local/include
In this example, we'll add a shell launch script for a Java JAR file:
/usr/bin/mylauncher
#!/bin/bash
# Launch script to kick off Java JAR (/usr/bin/mylauncher)
java -jar /usr/share/java/myapp.jar "$@"
Be sure to chmod +x
the script and place it in the
mypkg/usr/local/bin/
directory.
Configuration files
List configuration files in DEBIAN/conffiles
This will allow configuration files to optionally remain when
uninstalling (remove vs purge).
It also prevents updates from overwriting configuration files.
Example DEBIAN/conffiles
:
/etc/myapp.conf
/etc/some/other/conf.ini
Pre/post install scripts
Examples:
DEBIAN/preinst
DEBIAN/postinst
An example DEBIAN/postinst
script:
#!/bin/bash
# This `DEBIAN/postinst` script is run post-installation
mkdir /dir/needed/for/package
Package interrelationships
There are some other variables you can specify in the control
file:
Depends
Recommends
Suggests
Breaks
Conflicts
Provides
Replaces
Enhances
These can be useful to warn people if your package conflicts with another package that is already installed. You can also replace or enhance existing packages. If other packages would make your package work better, you can recommend and suggest other packages when the user installs your package.
Read more about package interrelationship fields.
Print package information
You can use dpkg
and apt-cache
to get some information about
packages.
# Print details about a package file (size, version, dependencies)
dpkg -I mypkg.deb
# Print status (is it installed?)
dpkg -s <package_name>
# Show package info (even uninstalled ones from repos)
apt-cache show <package_name>
Print package contents
If you want to review the contents of a .deb
package before installing
it, you can print the contents with the -c
flag.
dpkg -c mypkg-1.0.0-0_amd64.deb
Extract package contents
If you want to extract the contents of a .deb
file,
use the -X
flag for verbose extraction,
or -x
for quiet extraction.
dpkg -X mypkg-1.0.0-0_amd64.deb /where/to/exctact/
Install a package
Usually, two options are available for installing .deb packages.
One is dpkg
and the other is apt
which is built on top of dpkg
.
If you don't have the dependencies installed you will have to install them
yourself if you use dpkg -i
.
Alternatively, you can use apt
.
I recommend using apt
because it still uses dpkg
under the hood,
but it handles dependencies and is more user-friendly.
# Install package along with any dependencies it needs
sudo apt install ./mypkg.deb
# Install package, ignore and warn about unmet dependencies
sudo dpkg -i mypkg.deb
# If you need to install dependencies that were not
# installed because you used `dpkg -i` instead of `apt install`
sudo apt --fix-broken install
# Get status of package
dpkg -s mypkg
Searching for packages in apt repositories
You can use apt-cache
to search for packages
in your apt
repositories. These will need to be
installed with apt install
though not dpkg
.
Search like this:
apt-cache search alien
Uninstall a package
You can uninstall a package using remove
but it will leave the
configuration files.
To also remove the configuration files, use purge
.
dpkg --remove package_name # Leaves config files
dpkg --purge package_name # Removes config files too
# Or with apt
apt remove package_name
apt purge package_name
Listing files that belong to a package
This can be useful when trying to figure out what the executable file names are in /usr/bin or when trying to find local documentation.
# List all files that are included in the `ruby` package
dpkg -L ruby
dpkg -L ruby2.5-doc
Find which package owns a file
If you have a file on your system and you want to see if it belongs to a
package, you can use dpkg -S <filepath>
to see which package owns it.
You can also use apt-file search <filename>
to see which packages in
the repositories contain a file with that name.
For example "What package created this /etc/qwerty.conf file?" or
"Which package owns this executable?", or
"Which packages do I need to install to get gl.h
?" can be answered with:
# Figure out which package owns a specific file
dpkg -S /etc/qwerty.conf
dpkg -S /usr/bin/python3
# Search apt repositories for packages that contain file
# Find any package that includes a `gl.h`
apt-file search "gl.h"
Security notes
Only Use trusted packages and repositories only. You install packages with root privileges and you will be giving full reign on your machine with a package. Do not run any package you are not 100% confident it is from a trusted source.
GPG signing is a good way to ensure integrity and authenticity, that is, it has not been modified and the package came from the expected author.
You can learn more about how to sign files with GPG in my GPG Basics Tutorial. GPG is a great cryptography tool to be familiar with and worth taking the time to learn it. You can also use it to encrypt emails so only the intended recipient can read it, encrypting archives or PDFs, verifying signatures from others, and and many other practical uses.
Convert a .deb
to .rpm
and other formats
If you need a RedHat .rpm
file to install in CentOS, RedHat, or Fedora,
you can use the alien
tool to convert packages.
http://joeyh.name/code/alien/
sudo apt install alien
alien --help
alien --to-rpm my_pkg.deb
Some other options are:
-d, --to-deb Generate a Debian deb package (default).
-r, --to-rpm Generate a Red Hat rpm package.
--to-slp Generate a Stampede slp package.
-l, --to-lsb Generate a LSB package.
-t, --to-tgz Generate a Slackware tgz package.
Debhelper tool
I do not have much experience with this tool but it is worth a mention. The debhelper tool provides some utility and code generation features. Here is how you can install it and explore more.
sudo apt install debhelper
man dh
# See what tools are available by entering
dh_<tab><tab> # Get the autocomplete options
# Generate a new Debian package template
sudo apt install dh-make
# From inside a directory w/ name like: mypkg-1.0.0
dh_make --createorig
Conclusion
You should now feel comfortable working with and creating your own Debian packages, how to get information about a package, how to find which package a file belongs to, and other common tasks.