In this tutorial, you’ll learn how to:
- Take an upstream tarball (cmatrix 2.0 from GitHub)
- Create minimal Debian packaging files by hand
- Use
quiltto add a small patch - Build a
.debpackage and test it - Understand the version string
2.0-1~ppa1~rexbytes
This assumes you’re on an Ubuntu-based system (example: Ubuntu Noble).
We are going to use the Ubuntu package cmatrix as our upstream package.
0. Getting the cmatrix source
You can start this tutorial from either:
- The upstream cmatrix tarball from GitHub, or
- The Ubuntu/Debian source package via apt source (after enabling deb-src).
Both give you a cmatrix-2.0/ source tree to work in. Choose whichever matches what you want to learn.
0.1 Option 1: Upstream tarball (GitHub)
This is the “pure upstream” route we use in the main tutorial.
mkdir -p ~/scratch/cmatrix-ppa
cd ~/scratch/cmatrix-ppa
wget https://github.com/abishekvashok/cmatrix/archive/refs/tags/v2.0.tar.gz \
-O cmatrix_2.0.orig.tar.gz
tar -xzf cmatrix_2.0.orig.tar.gz
cd cmatrix-2.0
After this:
- cmatrix_2.0.orig.tar.gz is your upstream tarball.
- cmatrix-2.0/ is the unpacked source directory where you’ll create debian/.
0.2 Option 2: Source from Ubuntu (apt source)
If you’d rather start from Ubuntu’s existing packaging (Debian/Ubuntu-style “deb → deb”), you can fetch the source package instead.
0.2.1 Enable deb-src entries
Edit your APT sources:
Do this using the GUI for your distro.
Turn on the “source code repository” option.

You could manually edit the source lists… I include locations here but don’t recommend it.
But you could browse these files to check the deb-src is there.
sudo nano /etc/apt/sources.list
# Or you may find many source lists in /etc/apt/sources.list.d
# So instead,
sudo nano /etc/apt/sources.list.d/official-package-repositories.list
Make sure you have matching deb and deb-src lines, e.g. for Ubuntu Noble:
deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu noble-updates main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu noble-updates main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu noble-security main restricted universe multiverse
deb-src http://security.ubuntu.com/ubuntu noble-security main restricted universe multiverse
Save and exit, then update:
sudo apt update
If you’re using a PPA (e.g. ppa:rexbytes/cmatrix) and want its source too:
sudo add-apt-repository -s ppa:rexbytes/cmatrix
sudo apt update
!!! You do need to manually run this command for PPAs !!!
That adds a deb-src line for the PPA as well.
0.2.2 Fetch the cmatrix source
Now you can ask APT for the source package:
mkdir -p ~/scratch/cmatrix-ppa
cd ~/scratch/cmatrix-ppa
apt source cmatrix
This will download and unpack the source, giving you something like:
- cmatrix-2.0/ – source tree (already contains a debian/ directory)
- cmatrix_2.0.orig.tar.gz
- cmatrix_2.0-.debian.tar.xz
- cmatrix_2.0-.dsc
Then:
cd cmatrix-2.0
Now you are able to obtain package sources you can continue to read this tutorial.
!!! NOTE: Using apt source will mean there may already be an existing debian directory created by Ubuntu packagers. Delete the entire debian directory, you’ll spot this in the mkdir debian step of this tutorial. I will cover incremental upstream patching in another tutorial. Here we just want to get our hands on a tar.gz file.
1. Install required tools
First, install the packaging tools (including quilt) and build dependencies:
sudo apt update
sudo apt install devscripts build-essential debhelper-compat quilt \
autoconf automake libncurses5-dev libncursesw5-dev \
dput
2. Prepare a working directory and download cmatrix
Create a scratch directory for this packaging experiment:
mkdir -p ~/scratch/cmatrix-ppa
cd ~/scratch/cmatrix-ppa
Download the upstream tarball from GitHub and save it as a Debian-style orig.tar.gz:
wget https://github.com/abishekvashok/cmatrix/archive/refs/tags/v2.0.tar.gz \
-O cmatrix_2.0.orig.tar.gz
Note: The underscore in
cmatrix_2.0.orig.tar.gzis important for Debian naming conventions (<package>_<upstream-version>.orig.tar.gz).
Extract it:
tar -xzf cmatrix_2.0.orig.tar.gz
cd cmatrix-2.0
3. Create the debian/ directory
All packaging files live in a directory called debian inside the source tree.
mkdir debian
We’ll now create several files manually:
- debian/control
- debian/rules
- debian/changelog
- debian/copyright
debian/patches/*(for quilt)
4. Create debian/control
This file declares metadata about the package and build dependencies.
nano debian/control
Insert:
Source: cmatrix
Section: misc
Priority: optional
Maintainer: Good Boy <[email protected]>
Build-Depends: debhelper-compat (= 13), autoconf, automake, libncurses5-dev, libncursesw5-dev
Standards-Version: 4.6.0
Homepage: https://github.com/abishekvashok/cmatrix
Package: cmatrix
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Terminal-based "The Matrix" effect
CMatrix simulates the digital rain from "The Matrix" inside your terminal.
- Source: name of the source package.
- Build-Depends: tools and libraries needed to build.
- Package: the binary package name (the
.deb). - Depends: ${shlibs:Depends}, ${misc:Depends}: automatically generated deps.
Save and exit.
5. Create debian/rules
This is a makefile that tells debhelper how to build and install the package.
nano debian/rules
Insert:
#!/usr/bin/make -f
%:
dh $@ --with quilt
override_dh_auto_configure:
autoreconf -i
./configure --prefix=/usr
override_dh_auto_build:
make
override_dh_auto_install:
make DESTDIR=$(CURDIR)/debian/cmatrix install
Explanation:
dh $@calls the appropriate debhelper command for each step (build, install, clean, etc.).override_dh_auto_configurerunsautoreconfand./configurewith/usras the prefix.override_dh_auto_installinstalls into a temporary tree underdebian/cmatrix, not your real filesystem.
Make it executable:
chmod +x debian/rules
6. Create debian/changelog
We’ll write a minimal changelog entry by hand (no dch).
nano debian/changelog
Insert:
cmatrix (2.0-1~ppa1~rexbytes) noble; urgency=medium
* Initial PPA build with custom Debian packaging.
-- Good Boy <[email protected]> Wed, 26 Nov 2025 12:00:00 +0000
Key bits:
- 2.0-1~ppa1~rexbytes is the package version. We’ll explain it in detail near the end.
- noble is the target distribution (e.g. Ubuntu Noble).
- The last line is your signature line: name, email, date, and time.
7. Create debian/copyright
This tells Debian/Ubuntu about licensing and copyright terms.
nano debian/copyright
Insert (based on the Debian copyright file for cmatrix):
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: CMatrix
Source: https://github.com/abishekvashok/cmatrix
Files: *
Copyright: 1999-2017 Chris Allegretta
2017-2019 Abishek V Ashok <[email protected]>
License: GPL-3+
Files: debian/*
Copyright: 1999-2004 Edward Betts <[email protected]>
2006 Mohammed Adnène Trojette <[email protected]>
2008 Sandro Tosi <[email protected]>
2008-2014 Diego Fernández Durán <[email protected]>
2018-2023 Boyuan Yang <[email protected]>
2023 Guilherme de Paula Xavier Segundo <[email protected]>
License: GPL-3+
License: GPL-3+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Comment:
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
8. Prepare quilt for patches
Create the patches directory and an (initially empty) series file:
mkdir -p debian/patches
touch debian/patches/series
For this shell session, set quilt environment variables (so it uses debian/patches):
export QUILT_PATCHES=debian/patches
export QUILT_SERIES=debian/patches/series
9. Create a quilt patch
We’ll add a small patch that modifies the version output, for example to add a “Packaged By” line.
9.1. Start a new patch
quilt new add-debian-tag-to-version-output.patch
This creates a new patch entry and marks it as “current” for quilt.
9.2. Tell quilt which file you’re editing
quilt add cmatrix.c
This tells quilt to track changes in cmatrix.c for this patch.
9.3. Edit the source
Open cmatrix.c and modify the version() function to print your tag.
nano cmatrix.c
Find the version(void) function and add a line, e.g.:
void version(void) {
printf("CMatrix version %s (compiled %s, %s)\n",
VERSION, __TIME__, __DATE__);
printf("Email: [email protected]\n");
printf("Web: https://github.com/abishekvashok/cmatrix\n");
printf(" Packaged By: Rex Bytes - As part of a packaging tutorial.\n");
}
Save and exit.
9.4. Refresh the patch
Tell quilt to record the differences into the patch file:
quilt refresh
You can inspect the generated patch:
cat debian/patches/add-debian-tag-to-version-output.patch
It should look similar to:
Index: cmatrix-2.0/cmatrix.c
===================================================================
--- cmatrix-2.0.orig/cmatrix.c
+++ cmatrix-2.0/cmatrix.c
@@ -152,6 +152,7 @@ void version(void) {
VERSION, __TIME__, __DATE__);
printf("Email: [email protected]\n");
printf("Web: https://github.com/abishekvashok/cmatrix\n");
+ printf(" Packaged By: Rex Bytes - As part of a packaging tutorial.\n");
}
At this point, your debian/patches/series file should contain the patch name:
cat debian/patches/series
Expected content:
add-debian-tag-to-version-output.patch
10. Build the package
Go back to the top of the source tree (if you’re not already there):
cd ~/scratch/cmatrix-ppa/cmatrix-2.0
Build the package (no signing, local build):
dpkg-buildpackage -us -uc
-us= do not sign source.- -uc = do not sign the .changes file.
If everything succeeds, you’ll have .deb and related files in ~/scratch/cmatrix-ppa.
11. Install and test the package
Go up one directory and install the freshly built .deb:
cd ..
sudo dpkg -i cmatrix_2.0-1~ppa1~rexbytes_amd64.deb
Now test the version output:
cmatrix -V
Expected output (similar to):
CMatrix version 2.0 (compiled 12:00:00, Nov 26 2025)
Email: [email protected]
Web: https://github.com/abishekvashok/cmatrix
Packaged By: Rex Bytes - As part of a packaging tutorial.
12. Understanding the version: 2.0-1~ppa1~rexbytes
Let’s decode this, because it’s important and very useful for PPA-style builds.
Debian version format:
[epoch:]upstream-version[-debian-revision]
For your package:
- Upstream version:
2.0 - Debian revision: 1~ppa1~rexbytes
Break it down:
- 2.0
The upstream project version (cmatrix 2.0). - -1
The first Debian packaging revision for this upstream version.
If someone changes the packaging, they’d bump this to -2, -3, etc. - ~ppa1
ppa1 = “first PPA build”.
The leading ~ is special: it makes this version sort older than 2.0-1.
That means: 2.0-1~ppa1 < 2.0-1
So if Ubuntu later publishes 2.0-1 in the official archives, apt will upgrade users from your PPA package to the official one, which is what you usually want. - ~rexbytes
A label (still prefixed by ~) indicating which PPA/repo this build is from. It keeps the overall version “below” 2.0-1, but lets you distinguish it from other possible PPA builds.
In short:
2.0-1~ppa1~rexbytes= cmatrix 2.0, first Debian-style packaging revision, first PPA build, from “rexbytes”, always considered older than the official 2.0-1 package.
13. Bonus: Using dch to manage the changelog
In this tutorial, we wrote debian/changelog by hand to understand the format.
In real packaging work, you’ll usually use the dch tool (from devscripts) to edit it safely.
dch can:
- Create a new
debian/changelog - Bump the Debian revision (
-1→-2, etc.) - Set the version explicitly
- Add new changelog entries with your name, email, and the current date
13.1 Tell dch who you are
dch gets your name and email from environment variables (preferred) or, if those aren’t set, from git config / other fallbacks.
For packaging, it’s nice to set explicit Debian identity variables:
export DEBFULLNAME="Good Boy"
export DEBEMAIL="[email protected]"
You can put these in ~/.bashrc (or ~/.zshrc, etc.) so they’re always set:
echo 'export DEBFULLNAME="Good Boy"' >> ~/.bashrc
echo 'export DEBEMAIL="[email protected]"' >> ~/.bashrc
source ~/.bashrc
From now on, dch will create changelog trailer lines like:
-- Good Boy <[email protected]> Fri, 05 Dec 2025 12:34:56 +0000
13.2 Creating a changelog with dch
If debian/changelog doesn’t exist yet, you can create it with:
dch --create -v 2.0-1~ppa1~rexbytes --package cmatrix
dch will:
- Open an editor with a template entry
- Use your DEBFULLNAME/DEBEMAIL
- Fill in the version and date
Edit the bullet points, save, and quit.
dch will write a proper changelog stanza for you.
13.3 Bumping the version for a new PPA build
Suppose you’ve already uploaded 2.0-1~ppa1~rexbytes and now want a second PPA build, e.g. 2.0-1~ppa2~rexbytes:
dch -v 2.0-1~ppa2~rexbytes "Second PPA build: tweak packaging."
This will:
- Add a new changelog entry at the top
- Set the new version to 2.0-1~ppa2~rexbytes
- Use your configured name and email
- Update the date automatically
13.4 Auto-incrementing Debian revisions
If you’re doing classic Debian-style revisions (2.0-1, 2.0-2, 2.0-3, …), you can let dch increment the revision for you:
dch -i "Bump Debian revision after packaging changes."
-i tells dch to:
- Look at the current version (e.g. 2.0-1)
- Bump the Debian revision (
-1→-2) - Add a new changelog entry with that incremented version