Uploading cmatrix to a PPA (PPA Upload Tutorial)
Example Values Used in This Tutorial
This tutorial uses the following fake example values throughout. Replace them with your own real details when following along.
| Field | Example Value |
|---|---|
| Full Name | Rex Bytes |
[email protected] | |
| Launchpad Username | rexbytes |
| GPG Key ID | AABB1122CCDD3344 |
| GPG Fingerprint | 1A2B3C4D5E6F7890AABB1122CCDD3344EEFF5566 |
| PPA | ppa:rexbytes/example-ppa |
| Package | cmatrix 2.0 |
| PPA Version | 2.0-1~ppa1~rexbytes |
| Target Distribution | noble |
| Working Directory | ~/packaging/cmatrix-ppa |
Prerequisites: You should complete 02-local-packaging.md and be familiar with 01-key-management.md before continuing.
In tutorial 02, you built and installed a .deb package locally. This tutorial takes the next step: signing, uploading, and publishing that package to a Launchpad PPA so anyone can install it with apt.
You’ll learn how to:
- Set up your GPG key and Launchpad PPA
- Use
dchto create a PPA-versioned changelog - Build a signed source package for Launchpad
- Upload it to your PPA with
dput - Install and test the package from your PPA
This tutorial assumes you already have:
- A working
~/packaging/cmatrix-ppa/cmatrix-2.0source tree withdebian/packaging - A successful local build from
dpkg-buildpackage -us -uc - The upstream tarball
cmatrix_2.0.orig.tar.gzin~/packaging/cmatrix-ppa/
If not, go back and complete 02-local-packaging.md first.
0. Install additional tools for PPA uploads
Tutorial 02 installed the core packaging tools. Confirm you also have gnupg (for GPG signing):
sudo apt install gnupg
Note:
gnupgis usually pre-installed on Ubuntu. If you followed tutorial 02 exactly, it’s already installed.
1. Set your packaging identity for dch
Tell dch (and other Debian tools) who you are. This controls the name/email in debian/changelog:
export DEBFULLNAME="Rex Bytes"
export DEBEMAIL="[email protected]"
Code language: JavaScript (javascript)
To make this permanent, add it to your shell config:
echo 'export DEBFULLNAME="Rex Bytes"' >> ~/.bashrc
echo 'export DEBEMAIL="[email protected]"' >> ~/.bashrc
source ~/.bashrc
Code language: PHP (php)
dch will now generate changelog trailer lines like:
-- Rex Bytes <[email protected]> Fri, 05 Dec 2025 12:34:56 +0000
Code language: HTML, XML (xml)
2. One-time PPA prep: GPG key + Launchpad PPA
See 01-key-management.md for full details on key management, backup, and rotation.
You only need to do this once per account.
2.1 Generate a GPG key
Create a new GPG key for signing packages:
gpg --full-generate-key
Choose:
- Kind: RSA and RSA (default is fine)
- Key size: 4096 (recommended)
- Expiry: e.g. 1–2 years, or “does not expire”
- Name and email: must match your Launchpad account
Confirm the secret key was created and note the fingerprint:
gpg --list-secret-keys --keyid-format LONG
Code language: PHP (php)
Why
--list-secret-keys? For package signing, what matters is that the secret (private) key exists on your machine.--list-keysonly shows public keys, which isn’t enough to confirm you can sign. This is especially important after restoring keys from a backup — you might have the public key but not the private one.
2.2 Upload your GPG key to the Ubuntu keyserver
Launchpad doesn’t accept key uploads directly — it fetches your public key from a keyserver. You must publish your key there first:
gpg --keyserver keyserver.ubuntu.com --send-keys AABB1122CCDD3344
Code language: CSS (css)
Verify the upload worked:
gpg --keyserver keyserver.ubuntu.com --recv-keys AABB1122CCDD3344
Code language: CSS (css)
Note: Keyserver propagation can take a few minutes. If Launchpad can’t find your key immediately, wait and try again.
2.3 Add your GPG key to Launchpad and create a PPA
- Go to https://launchpad.net/, log in (or create an account).
- Navigate to your profile → OpenPGP keys → paste your full key fingerprint (e.g.
1A2B 3C4D 5E6F 7890 AABB 1122 CCDD 3344 EEFF 5566). - Launchpad will send an encrypted email to the address in your key’s uid. Decrypt it, click the confirmation link inside, and your key is registered.
- Create a PPA: go to your profile → Create a new PPA → name it (e.g.
example-ppa), giving youppa:rexbytes/example-ppa.
Important: The email address in your GPG key uid must match a verified email on your Launchpad account, and the fingerprint must match what Launchpad fetched from the keyserver. If either doesn’t match, uploads will be rejected.
3. Update debian/changelog for a PPA build (using dch)
In tutorial 02 you wrote debian/changelog by hand. For PPA builds, we’ll use dch to regenerate it with a PPA-style version.
From inside the source tree:
cd ~/packaging/cmatrix-ppa/cmatrix-2.0
Code language: JavaScript (javascript)
Create a new changelog (this overwrites the hand-written one from tutorial 02):
dch --create -v 2.0-1~ppa1~rexbytes --package cmatrix -D noble
Code language: CSS (css)
Important: Without
-D noble,dchdefaults the distribution toUNRELEASED. Launchpad rejects uploads withUNRELEASED— you must set it to an active Ubuntu series likenoble.
dch will open an editor. Write a description:
cmatrix (2.0-1~ppa1~rexbytes) noble; urgency=medium
* Initial PPA build with custom Debian packaging.
-- Rex Bytes <[email protected]> Wed, 26 Nov 2025 12:00:00 +0000
Code language: HTML, XML (xml)
2.0-1~ppa1~rexbytesis the package version (see tutorial 02, section 13 for the full version breakdown).nobleis the target distribution.- The last line is automatically filled by
dch, using yourDEBFULLNAME/DEBEMAIL.
Save and exit.
For later uploads (e.g. 2.0-1~ppa2~rexbytes), you can bump the version with:
dch -v 2.0-1~ppa2~rexbytes -D noble "Second PPA build: tweak packaging."
Code language: JavaScript (javascript)
4. Build a signed source package for your PPA
For PPAs, you upload a signed source package, not a .deb. Launchpad builds the binary packages for you.
Make sure your packaging identity matches your GPG key and Launchpad account:
export DEBFULLNAME="Rex Bytes"
export DEBEMAIL="[email protected]"
Code language: JavaScript (javascript)
Your GPG key should use the same name and email. Verify with:
gpg --list-secret-keys --keyid-format LONG
Code language: PHP (php)
Example output:
sec rsa4096/AABB1122CCDD3344 2024-01-15 [SC]
1A2B3C4D5E6F7890AABB1122CCDD3344EEFF5566
uid [ultimate] Rex Bytes <[email protected]>
ssb rsa4096/9988776655443322 2024-01-15 [E]
Code language: HTML, XML (xml)
- Long key ID:
AABB1122CCDD3344 - Fingerprint (recommended for -k):
1A2B3C4D5E6F7890AABB1122CCDD3344EEFF5566
Replace the fingerprint in the commands below with your own.
First, unapply any quilt patches (if still applied from tutorial 02). With 3.0 (quilt) format, dpkg-source will re-apply patches during the build:
quilt pop -a
Note: If you get
No patch removedthat’s fine — it means patches are already unapplied.
4.1 First upload of this upstream version
Include the full orig tarball and sign the source package:
debuild -S -sa -k<YOUR-FINGERPRINT>
Code language: HTML, XML (xml)
For example:
debuild -S -sa -k1A2B3C4D5E6F7890AABB1122CCDD3344EEFF5566
Explanation:
-S→ build source only (no binary.deb).-sa→ include the upstreamorig.tar.gzin this upload.-k…→ tell debuild which GPG key to sign with (by fingerprint or long key ID).
On a correctly configured system, this:
- Builds the source package
- Runs lintian (a Debian package checker)
- Signs the
.dsc,.buildinfo, and_source.changesfiles with your key
Note:
debuildrunslintianautomatically. You may see warnings about missing man pages or other minor policy issues — these don’t block the build and are normal for tutorial packages. To see detailed explanations, runlintian --info <package>_source.changes.
If you accidentally ran debuild without -k… and got unsigned files, you can sign them afterwards with:
cd ~/packaging/cmatrix-ppa
debsign -k<YOUR-FINGERPRINT> cmatrix_2.0-1~ppa1~rexbytes_source.changes
Code language: HTML, XML (xml)
After a successful debuild, go up one directory:
cd ..
ls
You should see files like:
cmatrix_2.0-1~ppa1~rexbytes.dsc
cmatrix_2.0.orig.tar.gz
cmatrix_2.0-1~ppa1~rexbytes.debian.tar.xz
cmatrix_2.0-1~ppa1~rexbytes_source.buildinfo
cmatrix_2.0-1~ppa1~rexbytes_source.changes
Code language: CSS (css)
4.2 Subsequent uploads of the same upstream version
If you later tweak the packaging (e.g. 2.0-1~ppa2~rexbytes) but the upstream version (2.0) is unchanged, you don’t need to re-upload the orig.tar.gz. Use:
debuild -S -sd -k<YOUR-FINGERPRINT>
Code language: HTML, XML (xml)
-sd→ do not re-upload the orig tarball (saves time and bandwidth).
Troubleshooting signing and build failures
| Symptom | Likely cause | Fix |
|---|---|---|
gpg: skipped "...": No secret key | The fingerprint in -k doesn’t match any secret key on your system | Run gpg --list-secret-keys --keyid-format LONG and use the correct fingerprint |
gpg: signing failed: No pinentry | GPG can’t prompt for your passphrase (common in SSH sessions) | Install pinentry-tty and set pinentry-program in ~/.gnupg/gpg-agent.conf, then gpgconf --kill gpg-agent |
debsign: gpg error occurred! Aborting. | GPG passphrase wrong or agent timed out | Re-run debuild or debsign and enter the correct passphrase |
orig.tar.gz not found | Missing or misnamed upstream tarball | Ensure cmatrix_2.0.orig.tar.gz is in the parent directory (~/packaging/cmatrix-ppa/) |
distribution UNRELEASED is not allowed | Changelog still says UNRELEASED | Re-run dch -D noble or edit debian/changelog to set the distribution to noble |
5. Upload to your PPA with dput
Now use dput to send the signed source package to your PPA.
From ~/packaging/cmatrix-ppa:
dput ppa:rexbytes/example-ppa cmatrix_2.0-1~ppa1~rexbytes_source.changes
Adjust ppa:rexbytes/example-ppa to match the PPA you created on Launchpad.
Troubleshooting: Network unreachable errors
Very rarely you might get a “Network is unreachable” or “Cannot assign requested address” error:
[Errno 101] Network is unreachable
[Errno 99] Cannot assign requested address
Code language: CSS (css)
This can happen due to IPv6, NAT, router, or firewall quirks.
If this happens, the most reliable workaround is to use SFTP instead of the default FTP method. SFTP requires an SSH key registered on your Launchpad account (see 01-key-management.md).
Create a custom dput config in ~/.dput.cf:
[my-ppa]
fqdn = ppa.launchpad.net
method = sftp
incoming = ~rexbytes/ubuntu/example-ppa/
login = rexbytes
Note: The
incomingpath follows the pattern~<launchpad-user>/ubuntu/<ppa-name>/. Replacerexbyteswith your Launchpad username andexample-ppawith your PPA name.
Then upload using the [my-ppa] config section name instead of ppa:...:
dput my-ppa cmatrix_2.0-1~ppa1~rexbytes_source.changes
Code language: CSS (css)
Note: The system-wide
/etc/dput.cfcontains a[ppa]section that uses FTP with anonymous login — theppa:user/ppa-nameshorthand uses this system config. Your~/.dput.cfoverrides let you use SFTP as an alternative.
dput will:
- Check the signatures on
_source.changesand.dsc - Upload the referenced files (
.dsc,.orig.tar.gz,.debian.tar.xz,.buildinfo, etc.) to Launchpad
On Launchpad:
- Open your PPA page.
- You should see
cmatrix 2.0-1~ppa1~rexbytesin the build queue. - When the build completes for your target series (e.g. noble amd64) and the status changes to Published, the binary packages become available in your PPA.
6. Install from your PPA and test
Once Launchpad has built and published your package, you can install it like any other PPA package.
On an Ubuntu (or Mint Noble-based) system:
sudo add-apt-repository ppa:rexbytes/example-ppa
sudo apt update
Before installing, check which versions APT sees. Because the PPA version uses ~ (tilde) in its version string, it will sort lower than the archive version — this is expected and intentional, not a sign that something went wrong:
apt-cache policy cmatrix
Expected output (example):
cmatrix:
Installed: (none)
Candidate: 2.0-6
Version table:
2.0-6 500
500 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages
2.0-1~ppa1~rexbytes 500
500 https://ppa.launchpadcontent.net/rexbytes/example-ppa/ubuntu noble/main amd64 Packages
Code language: JavaScript (javascript)
Note on version sorting: Because of the
~in2.0-1~ppa1~rexbytes, this version sorts lower than the archive’s2.0-6. This is by design — if Ubuntu publishes an official update,apt upgradewill replace your PPA version automatically. It also meanssudo apt install cmatrixwill install the archive version, not your PPA version. To install the PPA version explicitly:
sudo apt install cmatrix=2.0-1~ppa1~rexbytes
Verify it installed:
apt-cache policy cmatrix
cmatrix:
Installed: 2.0-1~ppa1~rexbytes
Candidate: 2.0-6
Version table:
*** 2.0-1~ppa1~rexbytes 100
100 /var/lib/dpkg/status
2.0-6 500
500 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages
2.0-1~ppa1~rexbytes 500
500 https://ppa.launchpadcontent.net/rexbytes/example-ppa/ubuntu noble/main amd64 Packages
Code language: JavaScript (javascript)
Now test the version output:
cmatrix -V
Expected output (similar to):
CMatrix version 2.0 (compiled 16:47:43, Dec 07 2025)
Email: abishekvashok@gmail.com
Web: https://github.com/abishekvashok/cmatrix
Packaged By: Rex Bytes - As part of a packaging tutorial.
Code language: CSS (css)
That confirms you’re running the cmatrix build from your PPA, with your quilt patch applied and your PPA-style version string.
7. Understanding the version: 2.0-1~ppa1~rexbytes
This was covered in detail in tutorial 02, section 13. Here’s a quick recap:
[epoch:]upstream-version[-debian-revision]
Code language: CSS (css)
| Part | Meaning |
|---|---|
2.0 | The upstream project version (cmatrix 2.0). |
-1 | The first Debian packaging revision for this upstream version. |
~ppa1 | First PPA build. The ~ makes this sort older than 2.0-1, so an official 2.0-1 package will automatically replace it. |
~rexbytes | Labels which PPA this build is from. |
2.0-1~ppa1~rexbytes= cmatrix 2.0, first Debian packaging revision, first PPA build, from “rexbytes”, always considered older than an official2.0-1package.
Linux PPA Packaging — All Parts
- 1 Key Management for Launchpad (GPG + SSH)
- 2 Packaging cmatrix with quilt (Local Build Tutorial)
- 3 Uploading cmatrix to a PPA (PPA Upload Tutorial) You are here
- 4 Packaging Your Own Software for a PPA (From Scratch)
