Signing and Distributing Debian Packages
Every package built earlier in this section installed cleanly on the machine that built it — but nothing about it could be trusted, verified, or fetched by anyone else. This closing chapter takes hello-tool the rest of the way: signed, served from a real repository, and installed on a client exactly the way any official package would be, closing the loop from source code to something genuinely distributable.
Step 1: Generating A GPG Key
Everything here rests on a real cryptographic key pair — the private half signs, the public half lets anyone verify.
gpg --full-generate-keyChoose RSA, at least 4096 bits, and provide a name and email when prompted. This produces a key pair stored in your GPG keyring. List it to confirm:
gpg --list-secret-keys --keyid-format longsec rsa4096/A1B2C3D4E5F6A7B8 2026-01-15
uid You <[email protected]>That A1B2C3D4E5F6A7B8 is your key ID — you’ll reference it directly in the steps ahead. Export the public half, since this is what you’ll eventually hand to anyone who wants to verify packages signed with it:
gpg --armor --export A1B2C3D4E5F6A7B8 > hello-tool-signing-key.ascThis is exactly the reverse role of the trust discussion earlier in this section — there, you were the one trusting a repository’s signature; here, you’re the one whose signature needs to be trustworthy.
Step 2: Signing The Package Itself
sudo apt install dpkg-sig
dpkg-sig --sign builder hello-tool_1.0.0_amd64.debVerify it directly:
dpkg-sig --verify hello-tool_1.0.0_amd64.debGOODSIG _gpgbuilder A1B2C3D4E5F6A7B8This confirms the .deb file itself carries a valid signature — one layer of trust. The next step adds a second, separate layer: signing the repository metadata that describes it.
Step 3: Building A Real Repository With reprepro
An apt repository isn’t just a folder of .deb files — apt update expects structured metadata (Packages, Release files) describing what’s in it. reprepro builds and maintains exactly that structure.
sudo apt install reprepro
mkdir -p ~/my-repo/confnano ~/my-repo/conf/distributionsOrigin: MyRepo
Label: MyRepo
Codename: stable
Architectures: amd64
Components: main
Description: A minimal example repository
SignWith: A1B2C3D4E5F6A7B8That SignWith line is where repository-level signing happens — every time reprepro regenerates its metadata, it signs it with this key automatically.
reprepro -b ~/my-repo includedeb stable hello-tool_1.0.0_amd64.debls ~/my-repo/dists/stable/main/binary-amd64/Packages Packages.gz ReleaseThese are the actual files apt will fetch — a real, structured, signed repository, built from a single package.
Step 4: Serving It
For demonstration purposes, Python’s built-in web server is more than enough — real production distribution wants HTTPS and a properly configured web server, but the underlying protocol apt speaks is just plain HTTP requests for these exact files:
cd ~/my-repo
python3 -m http.server 8000Step 5: Consuming It — The Client Side
On the installing machine (or the same machine, treating it as both), import the public key first:
sudo cp hello-tool-signing-key.asc /usr/share/keyrings/hello-tool-archive-keyring.ascAdd the repository, referencing that key exactly as covered in the apt chapter’s discussion of signed-by:
echo "deb [signed-by=/usr/share/keyrings/hello-tool-archive-keyring.asc] http://localhost:8000 stable main" | sudo tee /etc/apt/sources.list.d/hello-tool.listThen, the exact same commands used for any official package throughout this entire section:
sudo apt update
sudo apt install hello-toolThis is the full loop, closed: a C program, written from nothing, compiled, packaged, signed, published through a real repository structure, and installed via the ordinary apt install path — with apt verifying the signature automatically along the way, exactly as it would for anything from an official Debian mirror.
Real-World Notes: Key Management
The private half of this key pair is the entire foundation of trust in everything signed with it — anyone who obtains it can sign malicious packages that verify as genuinely yours. Store it somewhere genuinely secure (a hardware security key, or at minimum an encrypted, access-controlled location), never commit it to a repository, and treat its exposure as a full security incident requiring immediate key rotation if it ever happens.
Key rotation — periodically generating a new key and formally transitioning trust to it — matters for the same reason password rotation does, plus one Debian-specific nuance: a rotation needs to be communicated to everyone currently trusting the old key, since an abrupt, unannounced switch looks identical to what a compromise would look like from the outside.
How This Actually Works On A Real Debian Or Ubuntu System
Everything above is a genuine, correct demonstration of the underlying mechanics — but it’s worth being honest about the gap between “a self-hosted repository on your own machine” and “a package that ships in the actual Debian or Ubuntu archive that millions of machines pull from.” The real path has more structure to it.
The realistic path most individuals and companies actually take is a Launchpad PPA (Personal Package Archive), Ubuntu’s own hosted repository service — not the official Debian archive itself. You build your source package properly with debuild (a more complete, standards-compliant build tool than the manual dpkg-deb --build used earlier in this section for learning purposes), sign it with debsign, and upload it with dput:
debuild -S -sa
dput ppa:yourusername/your-ppa-name hello-tool_1.0.0_source.changesLaunchpad then builds your package on its own infrastructure for every supported architecture and hosts the resulting repository for you — genuinely the same underlying reprepro-style mechanics from this chapter, just operated at scale by Canonical’s infrastructure instead of your own laptop. This is how the overwhelming majority of third-party Ubuntu software you’ve ever installed via a PPA actually got there.
Getting into the official Debian archive itself is a considerably more involved process, worth knowing about even without expecting to go through it: it requires either becoming a registered Debian Developer or Debian Maintainer yourself (a genuine vetting process involving identity verification and a demonstrated track record), or finding an existing Debian Developer willing to sponsor your package — reviewing it and uploading it into the archive on your behalf under their own trust. A brand-new package additionally passes through Debian’s NEW queue, where the ftp-master team manually reviews it — checking licensing, packaging quality, and appropriateness — before it’s accepted into the archive at all. Uploads themselves go through dput/dupload to Debian’s incoming system, processed by the Debian Archive Kit (dak), the official infrastructure equivalent of the reprepro setup built by hand in this chapter.
The honest summary: the mechanics you just built — signing, structured metadata, a served repository, a trusting client — are genuinely the same mechanics underlying both paths. What differs is scale, infrastructure, and, for the official Debian archive specifically, a real human review and trust process layered on top, precisely because that archive is trusted directly by an enormous number of systems worldwide.
Closing Out Package Management
That’s the complete section — from understanding how package management works conceptually, through both major low-level and high-level tools on Debian and Fedora/RHEL, building real packages from a C program and a Python script, the full maintainer-script lifecycle, every location a package touches, genuinely complete removal, permissions and security, common pitfalls, and now signing and distribution. You’ve taken software from source code to a trusted, installable package the same way real Debian and Ubuntu packages actually get built and shipped.