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 quilt to add a small patch
  • Build a .deb package 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.gz is 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_configure runs autoreconf and ./configure with /usr as the prefix.
  • override_dh_auto_install installs into a temporary tree under debian/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

Leave a Reply