From 04b87447500a6890006c9904fbc64f6fffe18739 Mon Sep 17 00:00:00 2001 From: Aaron Rainbolt Date: Tue, 4 Nov 2025 17:56:43 -0600 Subject: [PATCH] Initial commit (high-level packaging overview and GPG setup) --- lubuntu-packaging-guide.rst | 376 ++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 lubuntu-packaging-guide.rst diff --git a/lubuntu-packaging-guide.rst b/lubuntu-packaging-guide.rst new file mode 100644 index 0000000..438962b --- /dev/null +++ b/lubuntu-packaging-guide.rst @@ -0,0 +1,376 @@ +============================== +Packaging Software for Lubuntu +============================== + +This document provides information about how to to create and maintain the +Debian packages that comprise the core of Lubuntu. We'll go over how to set up +your system for packaging, basic packaging concepts, best practices for +Lubuntu's packages, and advice for what to do and not do in order to make your +life as a packager easier. + +Copyright and Licensing +----------------------- + +The text of this document may be used under the terms of the CC-BY-SA 4.0 +license. The copyright info for this document is as follows: + +* Copyright (c) 2025 Aaron Rainbolt . + +.. NOTE:: + If you make a substantial contribution to this document, you should add + your own copyright info to the above list. + +High-level overview of a Debian "package" +----------------------------------------- + +There are two distinct kinds of packages in Debian, *binary packages* and +*source packages*. Binary packages are the packages you actually install on +your system. For the most part, you won't need to worry about the details of +how they work internally. Source packages are bundles of source code with +Debian packaging metadata. This metadata describes (among other things) how to +build the package, and where the files it installs should go. *Building* a +source package will create one or more binary packages, along with some other +files that we'll describe as we go. + +To get an idea of how source packages are structured, we'll start with a +fairly simple package, ``lxqt-about``:: + + aaron@pkg-builder:~/lubuntu-dev/lxqt-about$ tree + . + ├── aboutdialog + │   ... + ├── AUTHORS + ├── CHANGELOG + ├── CMakeLists.txt + ├── COPYING + ├── debian + │   ├── changelog + │   ├── control + │   ├── copyright + │   ├── docs + │   ├── ... + │   ├── ... + │   ├── lxqt-about.install + │   ├── lxqt-about-l10n.install + │   ├── lxqt-about.lintian-overrides + │   ├── rules + │   ├── ... + │   ├── source + │   │   ├── format + │   │   └── options + │   ├── upstream + │   │   ├── metadata + │   │   └── signing-key.asc + │   └── watch + ├── languages + ├── main.cpp + ├── README.md + ├── resources + │   ... + ├── translations + │   ... + └── translatorsinfo + ... + +(The contents of the ``aboutdialog``, ``translations``, and +``translatorsinfo`` dirs are omitted for brevity, and a few irrelevant files +from the ``debian`` directory have been hidden for clarity.) + +If you look at `the lxqt-about Git repo +`__, you'll see that this looks very +similar to the lxqt-about source code repository. The primary difference is +there is a ``debian`` directory here, with a number of files in it. This +``debian`` directory contains all the instructions necessary to take code, and +turn it into Debian binary packages. + +We won't go into the details about what these files contain quite yet, but we +will briefly cover what each one does. + +* ``changelog``: As one would expect, this contains a record of all changes + made to the package over time. It also specifies the version number of the + package, the version of Ubuntu (or Debian) the package is intended for, and + the identity of the person or people who made changes to the package. +* ``control``: This file defines critical information about the package, + including the names of the source package and each binary package, build and + runtime dependencies, what CPU each binary package is designed to run on, + and a description of each binary package. +* ``copyright``: This file contains copyright notices and authorship + information for (almost) every file in a source package. This is necessary + because many license agreements require or encourage a software distributor + (like Ubuntu) to include copyright notices, license text, and authorship + information for software they distribute. Thanks to the somewhat complex + nature of software licensing, this can be tricky and tedious to maintain, + but it is necessary. +* ``docs``: This file isn't present in all packages. When it is present, it + specifies files that should be installed in a subdirectory of + ``/usr/share/doc`` for the user to reference later if they care to. +* ``lxqt-about.install``: This file contains information about what files + should be placed in the ``lxqt-about`` binary package. There are some simple + source packages that don't need a ``.install`` file for a binary package, + but those are rare. +* ``lxqt-about-l10n.install``: This file serves the same purpose as + ``lxqt-about.install``, but for the ``lxqt-about-l10n`` binary package. (As + you can probably guess, the ``lxqt-about`` source package builds two binary + packages, named ``lxqt-about`` and ``lxqt-about-l10n``.) +* ``lxqt-about.lintian-overrides``: This file is used to silence + false-positive warnings from Lintian, a package checking tool that we'll + discuss later. +* ``rules``: This is a Makefile that provides the instructions for building + the source code of the source package into binaries. Previously this file + was rather large and complicated (and with some more advanced packages it's + still large and complicated), but thanks to some of Debian's more modern + tooling it is a lot easier to work with than it was in the past. +* ``source/format``: This file contains a string indicating what "format" the + package is in. We'll cover formats later. +* ``source/options``: You can usually ignore this file. It contains some + configuration for the ``dpkg-source`` tool, which you will very rarely have + to work with. +* ``upstream/metadata``: This file contains some basic information about the + source package's *upstream*, i.e. the entity that actually wrote the + software you are now packaging for Debian. It's good to know how to work + with these files, but you won't have to touch them very often. +* ``watch``: This file is used to locate, download, and sometimes repack + source code from upstream. It's rare that you'll have to change this file, + and it is usually very painful to work with it, but nonetheless it's good to + understand how to work with it. + +Most of the simpler packages you'll work with (including the entire LXQt +stack) will have a ``debian`` directory that more-or-less follows this +structure. More complicated packages may feature a substantially different +package structure, but for now we won't worry about those. + +The above is mainly meant to be a teaser of what you'll be working with as a +packager. Before we get into the details of packaging and how it works though, +you should have a good environment for packaging set up. That's what we'll +cover in the next few sections, starting with setting up PGP keys. + +PGP keys in Ubuntu development +------------------------------ + +One critical tool you'll use as an Ubuntu packager is PGP. Put simply, PGP is +a powerful tool used to prove that you take responsibility for some data (i.e. +a Debian package), and to ensure confidential data you send to someone can +only be read by them. This is useful, because as a packager, you will +frequently be uploading packages to Launchpad, and you need to prove that you +are the one doing the uploads for them to be accepted. Rarely, you will also +run into instances where someone has to send you confidential data. + +Using PGP effectively requires some understanding of how it works, so we'll +start with an overview of how PGP does what it does. + +Overview of PGP concepts +^^^^^^^^^^^^^^^^^^^^^^^^ + +PGP is a system for encrypting and signing arbitrary data using public key +cryptography. The basic idea behind PGP is that: + +* Each PGP user has two keys, a public key and a private key. The public key + is uploaded to a *keyserver* where others can download it, while the private + key is kept secret and is only accessible by the key's owner. +* Any PGP user can use the public key to *encrypt* data. Only the key owner's + secret key can *decrypt* and read the data. +* The key owner can use their secret key to *sign* data, proving that they + claim responsibility for that data. Anyone can use the key owner's public + key to *verify* the signature. +* It is (in practice) impossible to decrypt data encrypted by the public key + without the corresponding private key. It is similarly impossible to create + a signature that can be verified with a public key, without the + corresponding private key. The reason things work this way is beyond the + scope of this guide, but basically PGP uses some clever math tricks to do + what it does. It's been proven to work over years of production use, so it's + very widely used. + +Ubuntu uses PGP for several operations, including signing packages. Launchpad +requires that all packages are signed by the packager who claims +responsibility for them, before those packages can be uploaded. The signature +ensures that only authorized users can upload packages, and makes it so that +each package upload can be reliably traced back to the uploader. + +Because of PGP's reliance on public keys for verification and encryption, it +is necessary to distribute the public key as widely as possible, so that +individuals can find it and use it to send you encrypted data or verify things +that you send. To facilitate this, there are several *keyservers*, which PGP +software can upload keys to and fetch keys from. PGP keyservers share public +keys with each other, so uploading a key to one keyserver is enough for users +of virtually any other server to fetch that key. + +Preparing your PGP keys +^^^^^^^^^^^^^^^^^^^^^^^ + +.. NOTE:: + Ubuntu has `PGP key recommendations + `__ + for secure key storage. This overview is *not* fully compliant with these + recommendations, as the recommendations are non-mandatory, require special + hardware (in the form of a PGP-compatible USB hardware security key), and + are not easy to follow for first-time users. Once you have experience + generating PGP keys in general, you may choose to purchase a hardware + security key and configure it the way the Ubuntu PGP key recommendations + document. + +Before you create a PGP key, there are a few recommendations you should +consider: + +* If the laptop you intend to do development work on does not already use full + disk encryption, consider backing up your data and reinstalling the machine + with full disk encryption enabled. (This can be accomplished by using the + "Encrypt system" checkbox on the "Partitions" screen of Lubuntu's + installer.) This adds an extra layer of protection to the key. +* You **MUST** back up your key somewhere. If the key should become stolen or + compromised in the future, you will need a copy of it in order to revoke the + key and prevent it from being misused. +* If you are familiar with PGP key generation already, consider ignoring the + rest of this section and following the Ubuntu PGP key recommendations linked + above. These recommendations will have you generate a key in a known-good + environment and upload it to a hardware security key such as a Yubikey. This + provides much greater protection against key theft than the instructions + here. + +The standard tool for PGP key management under Ubuntu is GNU Privacy Guard +(GnuPG, usually accessed using the ``gpg`` command). This tool should already +installed on your system. You can use it to generate keys, sign and encrypt +data, verify signatures, and decrypt data sent to you. + +To generate a new PGP key using GPG, complete the following steps on your +physical system (do NOT do this in a packaging VM): + +1. Open a terminal window (i.e. QTerminal). +2. Run ``gpg --full-generate-key``. +3. When prompted to select the kind of key you want, press ``Return`` to + accept the default of ``ECC (sign and encrypt)``. +4. When prompted to select which elliptic curve you want, press ``Return`` to + accept the default of ``Curve 25519``. +5. When prompted to specify how long the key should be valid, enter a + reasonable amount of time and press ``Return``. (The default, ``0``, will + result in the key never expiring. This is acceptable, however setting a key + expiration data will make you review your key storage practices every so + often, which you may find useful for staying secure.) +6. When asked if the provided expiration data is correct, press ``y``, then + press ``Return``. +7. When prompted for your real name, enter it and press ``Return``. (If you + have a pseudonym that is recognizable in the Ubuntu community, you may use + that instead. What's important is that the key and things you sign with + that key can be clearly traced back to you as an individual.) +8. When prompted for your email address, enter the same email address you use + for your Ubuntu One account and press ``Return``. +9. When prompted for a comment, press ``Return`` to accept the default (empty) + value. (If you intend on using this PGP key only for Ubuntu packaging, you + might consider adding a comment like "Ubuntu packaging key".) +10. When asked for confirmation of your choices, press ``o``, then press + ``Return`` to accept your settings. +11. When prompted for a passphrase to protect your key, choose a strong + passphrase and enter it. Note that anyone who gains access to both your + key and its passphrase will be able to forge signatures in your name and + decrypt data sent to you, so it is of vital importance that this + passphrase be very secure. The easiest way to create a strong passphrase + is to pick six to eight random words and use those as your passphrase. + See `XKCD 936 `__ (but note that four-word + passphrases like suggested in the comic are not very secure). After + entering the passphrase, click "OK" in the popup window. +12. After clicking "OK", wait for the key to be generated. You will see + something like this once the key has been generated:: + + pub ed25519 2025-11-04 [SC] + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + uid Your Name + sub cv25519 2025-11-04 [E] + +Congratulations, you have now generated a PGP key! You should immediately back +this key up to some "offline" storage (i.e. a storage device that won't be +actively connected to your computer most of the time; flash drives are good +for this). GnuPG saves all of its persistent data, including generated public +and private keys, in the directory ``~/.gnupg``. You can therefore copy this +entire directory to a backup drive to back up the key. This will also back up +any other PGP-related data that GnuPG is storing, such as imported public +keys. + +Now that your key is generated and backed up, it's time to upload your public +key to a keyserver. This will of course allow users to verify things you sign +and encrypt data to you. More importantly for packaging though, uploading your +public key to a keyserver will let Launchpad discover it. This will allow you +to bind your key to your account in Launchpad, which will let you use that key +for package uploads later. Uploading a key is pretty simple:: + + gpg --keyserver keyserver.ubuntu.com --send-key name@example.com + +(Replace ``name@example.com`` with the email address you specified when +generating the key.) + +Your key is now on the Ubuntu keyserver. Now that you're done with that, it's +time to add the key to Launchpad. This is a bit tricky but not too difficult: + +1. In a web browser, go to your user account page on Launchpad (for instance, + ``https://launchpad.net/~example``). +2. Under the "User information" section, there is a subsection called "OpenPGP + keys". Click the pen icon next to this section. +3. Launchpad will require you to reauthenticate via Ubuntu One. Provide your + Launchpad account's username and password, click "Log in", then click "Yes, + log me in". +4. Open a terminal window (i.e., QTerminal), and type the command + ``gpg --fingerprint | grep -C5 name@example.com``, replacing + ``name@example.com`` with your email address. This will show some info + about your PGP key, including the fingerprint. The fingerprint will look + like ``xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx``, with + hexadecimal numbers in place of the "x" characters. Copy the fingerprint + to your clipboard (select it, then press Ctrl+Shift+C). +5. Back in your browser, you should be at the "Change your OpenPGP keys" + screen. Under the "Import an OpenPGP key" section, paste your fingerprint + into the "Fingerprint" field, then click "Import Key". This will cause + Launchpad to send you an email encrypted with your PGP public key, which + will contain an activation link you can use to confirm ownership of the + key. +6. You will receive an email with some instructions, and a block of text + starting with the string ``-----BEGIN PGP MESSAGE-----`` and ending with + the string ``-----END PGP MESSAGE-----``. Copy that block of text with + Ctrl+C. +7. Open a text editor (i.e. Featherpad), and paste the text in with Ctrl+V. + Then save the file to ``~/Documents/pgp-activate.txt``. +8. In a terminal window, run ``gpg --decrypt ~/Documents/pgp-activate.txt``. + Enter your key's passphrase when prompted. This will show you the link + needed to register your key with Launchpad. Copy the link (select it, then + press Ctrl+Shift+C). +9. Open a new tab in your browser, and paste the link into the address bar. +10. Click "Confirm" in the web page that appears. + +Congratulations, your PGP key is now registered with Launchpad and is ready +for development use! With that out of the way, we can get to the fun part; +setting up your packaging environment. + +Preparing a Debian packaging environment +---------------------------------------- + +There are a lot of different ways to set up a packaging environment, using +various different tools. The way documented here is a simplified version of my +packaging setup, which essentially uses a KVM-based VM running the latest +development release of Ubuntu, with ``sbuild`` as my primary build tool. This +method works well for me because: + +* It uses a full installation of Ubuntu in a VM, rather than a container, + avoiding some of the numerous pitfalls of containers when it comes to + privileges, resource sharing, etc. +* KVM is more robust than much of the other virtualization software available + for Linux (in particular I've found VirtualBox to be problematic in some + instances). +* It avoids issues that often arise when trying to package for a newer version + of Ubuntu using an older version, while not requiring one to run that newer + version as their primary OS. +* It's fairly simple to get working and fairly easy to use. +* ``sbuild`` closely mimics how packages are actually built on Launchpad, + minimizing the chances of odd things happening because of your build + environment. +* It integrates several other packaging tools you should be using, such as + Lintian. + +This method is not without disadvantages however: + +* If you want to keep your PGP keys out of your VM (which is recommended), it + requires signing packages manually on the host prior to upload. +* Virtualization incurs some overhead, so it can be slower than other + solutions. + +The steps are, roughly: + +* Install your desired flavor of Ubuntu into a virtual machine. +* Create a shared folder for working on packages on both the VM and host. +* Install and configure packaging utilities. +* Test the system by building sample source and binary packages.