712 lines
34 KiB
ReStructuredText
712 lines
34 KiB
ReStructuredText
==============================
|
|
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.
|
|
|
|
KVM preparation and VM installation
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The most common way to use KVM is through virt-manager, a GUI app that is
|
|
somewhat similar to VirtualBox. Under the hood, it uses libvirt, QEMU, and KVM
|
|
to run VMs.
|
|
|
|
.. NOTE::
|
|
KVM virtualization, much like the rest of Linux, has a lot of different
|
|
pieces that work together. QEMU emulates hardware and CPU instructions that
|
|
can't be run at full speed, KVM runs CPU instructions that can be run at
|
|
full speed, and libvirt makes it easier for applications to work with
|
|
QEMU/KVM virtual machines. virt-manager then provides a graphical user
|
|
interface for libvirt.
|
|
|
|
Installation is fairly simple; open QTerminal and run::
|
|
|
|
sudo apt install virt-manager libvirt-clients libvirt-daemon virtiofsd
|
|
sudo systemctl enable libvirtd.service
|
|
sudo systemctl start libvirtd.service
|
|
|
|
You should now be able to create virtual machines using virt-manager.
|
|
|
|
.. NOTE::
|
|
When talking about virtual and physical systems, the physical machine that
|
|
runs the VMs is typically called the "host", while the VMs themselves are
|
|
typically called "guests".
|
|
|
|
The next thing to do is to download the latest pre-release image of Lubuntu.
|
|
Like mentioned above, it is important to use the latest possible version of
|
|
Ubuntu to prevent issues with package builds later. The latest ISO can be
|
|
found
|
|
`<on cdimage.ubuntu.com https://cdimage.ubuntu.com/lubuntu/daily-live/pending/>`__.
|
|
It is generally a good idea to verify your ISO download using GnuPG and
|
|
sha256sum. To do this:
|
|
|
|
1. Create a directory to store the ISO at. ``$HOME/ISO/Lubuntu`` is a good
|
|
location.
|
|
2. Download the ``CODENAME-desktop-amd64.iso``, ``SHA256SUMS``, and
|
|
``SHA256SUMS.gpg`` files for Lubuntu, and move them to the newly created
|
|
directory.
|
|
3. Open QTerminal in the new directory, and import the PGP key used to sign
|
|
Ubuntu ISO images:
|
|
``gpg --keyserver keyserver.ubuntu.com --recv-keys 843938DF228D22F7B3742BC0D94AA3F0EFE21092``
|
|
4. Verify the SHA256SUMS file is unmodified using GnuPG:
|
|
``gpg --keyid-format=long --verify SHA256SUMS.gpg SHA256SUMS``. This
|
|
command should show output that looks similar to this::
|
|
|
|
gpg: Signature made Tue 26 Aug 2025 12:14:14 PM CDT
|
|
gpg: using RSA key 843938DF228D22F7B3742BC0D94AA3F0EFE21092
|
|
gpg: Good signature from "Ubuntu CD Image Automatic Signing Key (2012) <cdimage@ubuntu.com>" [unknown]
|
|
gpg: WARNING: This key is not certified with a trusted signature!
|
|
gpg: There is no indication that the signature belongs to the owner.
|
|
Primary key fingerprint: 8439 38DF 228D 22F7 B374 2BC0 D94A A3F0 EFE2 1092
|
|
|
|
5. Ensure you see the words "Good signature" in the output of GnuPG. If you
|
|
see "No public key" or "BAD signature", your download is corrupt. If you
|
|
see "Good signature", the SHA256SUMS file is authentic and intact.
|
|
6. Verify the ISO file is unmodified using sha256sum:
|
|
``sha256sum -c SHA256SUMS``. This command should show output that looks
|
|
like ``resolute-desktop-amd64.iso: OK``. If you see this, your ISO download
|
|
is authentic and intact.
|
|
|
|
Once you have a verified Lubuntu download, it's finally time we can create the
|
|
VM! To do this:
|
|
|
|
1. Open the application menu, and launch "Virtual Machine Manager".
|
|
2. Wait until the "Connecting" notice near the top of the window disappears.
|
|
3. Click the "Create a new virtual machine" button (it's in the very top-left
|
|
corner of the window).
|
|
4. In the "Create a new virtual machine" window, under "Choose how you would
|
|
like to install the operating system", click "Local install media (ISO
|
|
image or CDROM), then click "Forward".
|
|
5. At the top-right corner of the window, under "Choose ISO or CDROM install
|
|
media", click "Browse...".
|
|
6. In the "Locate ISO media volume" window, click "Browse Local".
|
|
7. In the file selector, navigate to the directory containing the Lubuntu ISO,
|
|
then click the ISO file and click "Open".
|
|
8. Uncheck the "Automatically detect from the installation media / source"
|
|
checkbox.
|
|
9. In the "Choose the operating system you are installing" text box, type
|
|
"Ubuntu".
|
|
10. In the popup that papears, click "ubuntu 25.10 (ubuntu25.10)", then click
|
|
"Forward".
|
|
11. Set a reasonable amount of RAM and number of CPUs for your hardware.
|
|
Package builds usually don't require that much memory or CPU power, but
|
|
sometimes they can benefit from lots of memory and CPU power, so it's a
|
|
good idea to allocate at least 8192 MB RAM and 4 CPUs if possible.
|
|
12. Set a reasonable amount of disk space for the VM. Package builds can take
|
|
a lot of disk space, so allocating at least 64 GB is highly recommended
|
|
here.
|
|
13. Set the VM name to something descriptive (i.e. ``lubuntu-dev``), then
|
|
click "Finish". We'll refer to this VM as ``lubuntu-dev`` in the rest of
|
|
this document.
|
|
|
|
The Lubuntu ISO should boot, and you can install it like you normally would.
|
|
For best performance, the ``ext4`` filesystem should be used. We won't cover
|
|
the Lubuntu installation process here, it's fairly straightforward. Once the
|
|
installed system boots up, you should check for updates and install them using
|
|
Lubuntu Update (or by running ``sudo apt update && sudo apt full-upgrade`` in
|
|
a terminal).
|
|
|
|
Once all updates are installed, click the application menu inside
|
|
``lubuntu-dev``, then hover over "Leave" and click "Shutdown". When LXQt asks
|
|
if you want to switch off your computer, click "Yes". (It is important that
|
|
you shut down the VM using LXQt's GUI buttons, do NOT run ``shutdown now`` in
|
|
a terminal! Doing the first shutdown in this manner prevents an LXQt bug that
|
|
breaks several features of Lubuntu.)
|
|
|
|
Shared folder setup
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
When doing Debian packaging, you will frequently have to modify packages on
|
|
both the host and guest systems. Rather than moving files between the guest
|
|
and the host all the time, it's easier to use a shared folder. This allows
|
|
both the guest and host to see and work on a set of files in the shared
|
|
directory.
|
|
|
|
.. NOTE::
|
|
KVM shared folders understand UNIX file permissions, so if a file is owned
|
|
by a particular UID on the host, it will appear as being owned by that same
|
|
UID in the guest. The default UID for the first user in Lubuntu is 1000. If
|
|
your user on the host system has UID 1000, things should work normally, but
|
|
if your UID on the host is something other than 1000, you will almost
|
|
certainly run into file ownership issues when trying to modify files in the
|
|
shared folder within the guest. If this happens, you should create a new
|
|
user in the guest with the same UID as your user account on the host, then
|
|
do your packaging work using that user account.
|
|
|
|
.. WARNING::
|
|
Do not share your entire home directory with the guest. This can expose
|
|
your PGP key to the guest, which is a security hazard.
|
|
|
|
To add a shared folder to the VM:
|
|
|
|
1. In the host OS, create a new directory to share between the host and the
|
|
guest. We'll assume the shared folder is at ``$HOME/vmshare``.
|
|
2. Create a file named ``test-marker.txt`` in ``$HOME/vmshare``. Well use this
|
|
to ensure that the shared folder actually works later.
|
|
3. Ensure the ``lubuntu-dev`` window is open but the VM itself is powered off.
|
|
(You should see the words "Guest is not running." in the middle of the
|
|
window.)
|
|
4. Click the "Show virtual hardware details" button (it's in the top toolbar,
|
|
and is the second button from the left).
|
|
5. In the left-hand sidebar, click "Memory", then check the "Enable shared
|
|
memory" checkbox and click "Apply"."
|
|
6. Underneath the left-hand sidebar, click "Add Hardware".
|
|
7. In the "Add New Virtual Hardware" window, in the left-hand sidebar, click
|
|
"Filesystem".
|
|
8. Ensure that the "Driver" is set to "virtiofs", then set the "Source path"
|
|
to ``/home/USERNAME/vmshare`` and the "Target path" to ``vmshare``.
|
|
(Replace ``USERNAME`` with your username on the host system.)
|
|
9. Click "Finish" to add the shared folder to the VM.
|
|
|
|
Next, to set up the VM to automatically mount this shared folder on startup:
|
|
|
|
1. Ensure the ``lubuntu-dev`` window is open, then click the "Power on the
|
|
virtual machine" button (it's in the top toolbar, looks like a play button,
|
|
and is the third button from the left).
|
|
2. Log in if necessary.
|
|
3. In the guest, open QTerminal, and run the following commands, replacing
|
|
``USERNAME`` with the guest's account's username. This will create a
|
|
systemd unit for mounting the shared folder, enable it so it starts on
|
|
bootup, and then start it so that the shared folder immediately starts
|
|
working::
|
|
|
|
mkdir $HOME/vmshare
|
|
cat <<'EOF' | sudo tee /etc/systemd/system/mount-vmshare.service
|
|
[Unit]
|
|
Description=Mount shared folder on startup
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
RemainAfterExit=true
|
|
ExecStart=mount -t virtiofs vmshare /home/USERNAME/vmshare
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
sudo systemctl enable mount-vmshare.service
|
|
sudo systemctl start mount-vmshare.service
|
|
|
|
4. The shared folder should be immediately mounted. In the guest, run
|
|
``ls $HOME/vmshare``, and verify that you can see the file
|
|
``test-marker.txt`` in the directory.
|
|
5. In the guest, run ``touch $HOME/vmshare/test-marker-guest.txt``.
|
|
6. On the host, run ``ls $HOME/vmshare``, and verify that you can see the
|
|
``test-marker-guest.txt`` file.
|
|
|
|
If both test files can be seen on both the guest and the host, the shared
|
|
folder is working. With that out of the way, we can get to the fun part;
|
|
installing tools for Debian packaging!
|
|
|
|
Installing and configuring packaging utilities
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Like mentioned earlier, we're going to be using ``sbuild`` as our primary
|
|
packaging tool. We'll go into a bit of detail about what all ``sbuild`` does
|
|
and how later. For now, we're just going to get it and the rest of the Debian
|
|
packaging tools installed and ready to work.
|
|
|
|
1. Ensure the ``lubuntu-dev`` window is open and the VM is running.
|
|
2. In the guest, open QTerminal, and run the following commands to install
|
|
``sbuild`` and several other packaging utilities::
|
|
|
|
sudo apt install ubuntu-dev-tools debhelper devscripts mmdebstrap git sbuild
|
|
|
|
3. In the guest, configure ``sbuild``. The following configuration is
|
|
relatively basic, works for almost everything, and integrates automatic
|
|
package caching. Replace ``Your Name`` and ``name@example.com`` as
|
|
appropriate. Do NOT remove the ``1;`` at the end of this config, or it will
|
|
break ``sbuild``. To create the config file::
|
|
|
|
mkdir -p $HOME/.config/sbuild
|
|
cat <<'EOF' > $HOME/.config/sbuild/config.pl
|
|
$maintainer_name = 'Your Name <name@example.com>';
|
|
$distribution = "resolute";
|
|
$build_arch_all = 1;
|
|
$purge_build_directory = "successful";
|
|
$purge_session = "successful";
|
|
$purge_build_deps = "successful";
|
|
$log_dir = $ENV{HOME}."/ubuntu/logs";
|
|
$chroot_mode = "unshare";
|
|
$unshare_mmdebstrap_keep_tarball = 1;
|
|
$unshare_mmdebstrap_extra_args = [
|
|
"*" => [ "--include=debhelper,auto-apt-proxy,ca-certificates" ],
|
|
"resolute" => [ "--include=debhelper,auto-apt-proxy,ca-certificates", "--components=main,universe,restricted,multiverse" ],
|
|
"questing" => [ "--include=debhelper,auto-apt-proxy,ca-certificates", "--components=main,universe,restricted,multiverse" ],
|
|
"plucky" => [ "--include=debhelper,auto-apt-proxy,ca-certificates", "--components=main,universe,restricted,multiverse" ],
|
|
"noble" => [ "--include=debhelper,auto-apt-proxy,ca-certificates", "--components=main,universe,restricted,multiverse" ],
|
|
];
|
|
$lintian_opts = [ '-E', '-v', '-I', '-L', '+pedantic' ];
|
|
$clean_source = 0;
|
|
1;
|
|
EOF
|
|
|
|
4. In the guest, configure ``quilt``. We'll explain more about what this tool
|
|
is and what it does later::
|
|
|
|
cat <<'EOF' > $HOME/.quiltrc
|
|
for where in ./ ../ ../../ ../../../ ../../../../ ../../../../../; do
|
|
if [ -e ${where}debian/rules -a -d ${where}debian/patches ]; then
|
|
export QUILT_PATCHES=debian/patches
|
|
break
|
|
fi
|
|
done
|
|
QUILT_PUSH_ARGS="--color=auto"
|
|
QUILT_DIFF_ARGS="--no-timestamps --no-index -p ab --color=auto"
|
|
QUILT_REFRESH_ARGS="--no-timestamps --no-index -p ab"
|
|
QUILT_DIFF_OPTS='-p'
|
|
EOF
|
|
|
|
5. In the guest, configure ``git``. You may already know what this tool does,
|
|
but we'll explain more about it later. Replace ``Your Name`` and
|
|
``name@example.com`` as appropriate::
|
|
|
|
git config --global user.name 'Your Name'
|
|
git config --global user.email 'name@example.com'
|
|
|
|
6. In the guest, configure ``dch``. We'll explain more about what this tool is
|
|
and what it does later. Replace ``Your Name`` and ``name@example.com`` as
|
|
appropriate::
|
|
|
|
cat <<'EOF' >> $HOME/.bashrc
|
|
export EMAIL='name@example.com'
|
|
export DEBEMAIL='name@example.com'
|
|
export DEBFULLNAME='Your Name'
|
|
EOF
|
|
|
|
7. In the guest, run ``source $HOME/.bashrc`` so the new settings you've
|
|
created for ``dch`` take effect in the currently running shell.
|
|
8. On the host, run the following commands to install some necessary packaging
|
|
tools there as well::
|
|
|
|
sudo apt install debhelper devscripts
|
|
|
|
There's a lot going on here, most of which won't make sense right now. We'll
|
|
go into detail about what all these options do later on in this guide.
|
|
|
|
At this point, your packaging environment is configured and ready to use. It's
|
|
time for the last step of setup; building a test package!
|
|
|
|
Testing the packaging environment
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
To make sure everything's working smoothly, we're going to use ``sbuild`` to
|
|
build binary packages for ``lxqt-about``, the same package we showed an
|
|
overview of at the beginning of this document. ``lxqt-about``'s packaging is
|
|
stored in the Lubuntu Git instance, so we're going to download the packaging
|
|
from there and build it.
|
|
|
|
1. Ensure the ``lubuntu-dev`` window is open and the VM is running.
|
|
2. In the guest, open QTerminal, and create a directory at
|
|
``$HOME/vmshare/pkg`` to do packaging in. Then change to the directory::
|
|
|
|
mkdir $HOME/vmshare/pkg
|
|
cd $HOME/vmshare/pkg
|
|
|
|
3. In the guest, download the Debian packaging for the ``lxqt-about`` package
|
|
from Lubuntu Git::
|
|
|
|
git clone https://git.lubuntu.me/Lubuntu/lxqt-about-packaging.git
|
|
|
|
4. In the guest, change to the new ``lxqt-about-packaging`` directory with
|
|
``cd lxqt-about-packaging``.
|
|
5. In the guest, run ``ls``, and ensure you see a single directory named
|
|
``debian``.
|
|
|
|
.. NOTE::
|
|
If you remember the overview of ``lxqt-about`` from the start of this
|
|
document, you might be confused here, since you only see a ``debian``
|
|
directory, not a full package. This is normal; Lubuntu does not duplicate
|
|
upstream source code in our packaging, since it's a waste of space and
|
|
isn't needed for package builds to still work.
|
|
|
|
6. In the guest, download the source code for ``lxqt-about`` by running
|
|
``uscan --download-current-version``. ``uscan`` is a packaging tool used
|
|
to download source code for packaged applications.
|
|
|
|
.. NOTE::
|
|
Due to a
|
|
`bug <https://bugs.launchpad.net/ubuntu/+source/devscripts/+bug/2122486>`__,
|
|
this might not work for all packages yet.
|
|
|
|
7. In the guest, build the package with the following command::
|
|
|
|
sbuild -d resolute
|
|
|
|
8. In the guest, run ``ls ..``. If all went well, you should see an
|
|
``lxqt-about`` deb file, alongside several other files.
|
|
|
|
That's it! If the above worked, you now have a working packaging environment!
|
|
We're now ready to move past system setup, and start learning how packaging
|
|
works.
|