Initial commit (high-level packaging overview and GPG setup)
This commit is contained in:
commit
04b8744750
376
lubuntu-packaging-guide.rst
Normal file
376
lubuntu-packaging-guide.rst
Normal file
@ -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 <arraybolt3@ubuntu.com>.
|
||||
|
||||
.. 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
|
||||
<https://github.com/lxqt/lxqt-about>`__, 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
|
||||
<https://documentation.ubuntu.com/project/contributors/setup/pgp-key-storage/>`__
|
||||
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 <https://xkcd.com/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 <name@example.com>
|
||||
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.
|
||||
Loading…
x
Reference in New Issue
Block a user