aboutsummaryrefslogtreecommitdiffstats
path: root/posts/2022
diff options
context:
space:
mode:
Diffstat (limited to 'posts/2022')
-rw-r--r--posts/2022/arch-a-recap.rst294
-rw-r--r--posts/2022/managing-binary-package-repositories.rst193
-rw-r--r--posts/2022/new-pgp-key-id-1793dad5d803a8ffd7451697bb992f9864fad168.rst182
-rw-r--r--posts/2022/packaging-for-arch-linux.rst1152
4 files changed, 1821 insertions, 0 deletions
diff --git a/posts/2022/arch-a-recap.rst b/posts/2022/arch-a-recap.rst
new file mode 100644
index 0000000..9ac0b19
--- /dev/null
+++ b/posts/2022/arch-a-recap.rst
@@ -0,0 +1,294 @@
+.. title: Arch, a recap
+.. slug: arch-a-recap
+.. date: 2022-01-30 18:0:00 UTC+02:00
+.. tags: arch linux, pro-audio, packaging
+.. category: archlinux
+.. link:
+.. description:
+.. type: text
+
+One of the things, that has kept me (increasingly) busy over the past few years
+is my involvement with the |linux distribution| |arch linux|.
+While I have been using |linux| for probably about 14 years it is frankly hard to
+pinpoint when exactly I went down the rabbit hole that this operating system/
+ecosystem/ community is (relevant |xkcd|). However, I can elaborate on my
+motivation and where that got me.
+
+.. TEASER_END
+
+As a musician of a varying background (from band-based rock music to solo
+performances on guitar or with a modular synthesizer) I have found myself
+evaluating the available pieces of software that are commonly used in music
+production (e.g. |daws| and |audio plug-ins|). Most of them are |proprietary|
+and only available for Windows or macOS (both proprietary as well). During my
+studies a lot of the software in use has also not been |free|, but was provided
+by the university with a *student discount* (e.g. Operating Systems (OSes),
+|ides| or certain types of |vpls|).
+I got increasingly annoyed by dealing with intransparent proprietary OSes,
+|vendor lock-in| schemes, paying for software updates and being driven into
+software piracy for working with so-called *industry standards*.
+
+Some time during the studies for my B.Sc. I decided to "try out Linux", not
+knowing what that would mean actually. So there I was, booting an |ubuntu| Live
+CD and clicking around in an interface, that would install the OS alongside a
+still existing Windows 7. At that point I did not yet know about the joys of
+missing or failing |device drivers|. Many hard fights with the |x window
+system| later I settled on |ubuntu studio| for a while, as it had many nice
+audio related pieces of software available out-of-the-box.
+
+I have always been a person that is interested in *"how things work"*. Soon I
+realized, that the Linux ecosystem consisted of people that thought quite
+similarly. Through various (often distribution specific) online documentation,
+forums, mailing lists and the documentation of software projects for the first
+time I felt as if I could actually learn something that mattered, because it
+was not sold in a box and instead had a community of like-minded people
+gathering around it.
+I found quite appealing that a lot of things were *not polished* and that some
+things were *not easy*, because it provided the sense of achieving something or
+*getting good at something*. Where in Windows land I would have reinstalled the
+OS upon getting intermittent |bluescreens|, in Linux land I just kept reading
+about a certain topic until I was able to fix it myself.
+
+Probably a year after dipping my toes into Linux I bought a new laptop (my
+previous one decided to commit suicide by desoldering its GPU). At that time it
+seemed like a good idea to not dual-boot anymore, as apart from an occasional
+game session I was not using Windows anymore.
+Due to a friend of one of my fellow students I got introduced to Arch Linux,
+which that person used in a (to me) bizarrely minimal fashion by booting from a
+USB stick, as the hard drive in his laptop was broken.
+
+After installing Arch Linux for the first time (probably around 2008) I
+realized quite early on that I would rather continue using it instead of Ubuntu
+Studio, which by that time had given me many issues due to unclear
+configuration management, documentation and graphics driver handling.
+The |arch wiki| already back then was an excellent source of knowledge (and
+still is to this day). Although some articles lack structure or are sometimes
+outdated, it is this trove of knowledge that I had been missing with less
+hands-on distributions up to then.
+The |aur| offered an entrypoint for me to understand how distribution |package
+management| works and how to build my own packages, that I could install using
+the |pacman| package manager. This new found knowledge made me realize how
+inefficient my work on Windows had been in the past (a realization that had not
+fully dawned upon me on Ubuntu Studio as their update model follows a certain
+cadence in which new versions of softwares are updated and otherwise only gain
+bugfix releases). I was suddenly enabled to build packages myself of software
+that I liked and used and I was able to alter existing packages to e.g. fix
+problems or to extend their functionality. I was enabled to upgrade my entire
+system with a single command, while on Windows I had to scavenge websites to
+download installers and run those without knowing whether they were compatible.
+
+As my main focus shifted even further towards pro-audio applications, |dsp|
+languages and recording practices with my M.Sc., I of course do have to mention
+the accumulation of knowledge that |linux audio| represents (e.g. with the
+|linux audio wiki|). It is an invaluable, although by now partially outdated
+and not actively maintained point of - often distribution agnostic -
+information on all things audio on Linux. This ecosystem is what drove and/ or
+documented the development and use of many of the projects at the center of
+what it means to achieve low-latency audio on Linux such as |jack|.
+
+After 2011 I started to conceptualize the Arch Linux distribution also as a
+social construct, that relies on individuals to develop and change it (by
+|getting involved|). While Arch is a distribution that can be used for many
+purposes, the lack of structure or features in e.g. the pro-audio section was
+apparent (although partially covered by packages in the AUR). I was able to do
+most of the projects I was working on at that time using |supercollider| but
+sometimes ran into issues that e.g. Ubuntu Studio had solved in a distribution
+specific way (e.g. by providing packages for the |realtime kernel| to achieve
+very low latencies while recording).
+
+Around 2017 it became apparent that many of the packages that I was using on a
+day-to-day basis were starting to fall behind on updates or had not been
+updated in a long time. It turned out that two packagers that had been active
+packaging audio related software were missing in action or were extremely
+unresponsive. I realized, that unlike a company supported endeavor, Arch Linux
+was a community driven effort and as such required help.
+
+At the time of writing, Arch Linux consists of |arch linux developers|, |arch
+linux trusted users| and |arch linux support staff|. While the first group
+somewhat defines the direction of the distribution itself and takes care of the
+most centric package repositories (``[core]`` and ``[extra]``), the second
+group historically has been an additional group of packagers that takes care of
+the ``[community]`` repository and the AUR and the last group is keeping a lot
+of the infrastructure (e.g. wiki, forums, mailing lists, IRC channels, servers,
+hosted applications) alive.
+
+For outsiders it is possible to join the Support Staff by starting to help
+maintain infrastructure together with the existing staff.
+When looking at the Trusted Users group the barrier of entry is a bit higher,
+as the person gains access to package repositories that are used by thousands
+of users. As such newcomers have to follow a vetting process and be sponsored
+by existing group members (this is similar, but much less clearly defined, for
+Developers).
+
+At the end of 2017 I was able to apply as Trusted User with the help of Ray
+Rashif, who had been maintaining the packages I wanted to help improve and
+update.
+
+Admittedly, the application process has been a bit daunting at the time, but it
+also made me realize, how much I could still improve my package scripts and the
+amount of work that is sometimes required to get things right.
+
+Since becoming a Trusted User in 2017 I have added many new packages in the
+context of a pro-audio package group and spent time on various other packaging
+areas as well.
+In 2019 I have been promoted to Developer and spent some more time on
+non-packaging topics on the side, such as infrastructure improvements
+(|releng|, |arch-release-promotion| and |arch-repo-management|), installation
+medium (|archiso|) and various community related topics (setting up an |rfc
+process| and help holding |arch linux conferences|).
+
+I will follow up on packaging and best practices in an upcoming article
+(hopefully in the not so distant future) and shed some light on the
+non-packaging topics in further articles as well.
+
+That's it for now! I hope you enjoyed reading a user story, that eventually led
+to getting more involved with an international community of (very talented)
+developers working on a challenging project with many facets. As you can
+imagine there are always many more stories to tell, but I tried to give a
+general overview. Maybe I could even get someone interested in reaching out and
+lending a hand in further developing this amazing beast that is Arch Linux :-)
+
+.. |linux distribution| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Linux_distribution">Linux distribution</a>
+
+.. |arch linux| raw:: html
+
+ <a target="blank" href="https://www.archlinux.org">Arch Linux</a>
+
+.. |linux| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Linux">Linux</a>
+
+.. |xkcd| raw:: html
+
+ <a target="blank" href="https://xkcd.com/456/">XKCD</a>
+
+.. |proprietary| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Proprietary_software">proprietary</a>
+
+.. |daws| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Digital_audio_workstation">Digital Audio Workstations (DAWs)</a>
+
+.. |audio plug-ins| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Audio_plug-in">audio plugin-ins</a>
+
+.. |free| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Free-software_license">free</a>
+
+.. |ides| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Integrated_development_environment">Integrated Development Environments (IDEs)</a>
+
+.. |vpls| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Visual_programming_language">Visual Programming Languages (VPLs)</a>
+
+.. |vendor lock-in| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Vendor_lock-in">vendor lock-in</a>
+
+.. |ubuntu| raw:: html
+
+ <a target="blank" href="https://ubuntu.com/">Ubuntu</a>
+
+.. |device drivers| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Device_driver">device drivers</a>
+
+.. |x window system| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/X_Window_System">X Window System</a>
+
+.. |ubuntu studio| raw:: html
+
+ <a target="blank" href="https://ubuntustudio.org/">Ubuntu Studio</a>
+
+.. |bluescreens| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Blue_Screen_of_Death">bluescreens</a>
+
+.. |arch wiki| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/">Arch Wiki</a>
+
+.. |aur| raw:: html
+
+ <a target="blank" href="https://aur.archlinux.org">AUR</a>
+
+.. |package management| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Package_manager">package management</a>
+
+.. |pacman| raw:: html
+
+ <a target="blank" href="https://archlinux.org/pacman/">pacman</a>
+
+.. |dsp| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Digital_signal_processing">DSP</a>
+
+.. |linux audio| raw:: html
+
+ <a target="blank" href="https://linuxaudio.org/">Linux Audio</a>
+
+.. |linux audio wiki| raw:: html
+
+ <a target="blank" href="https://wiki.linuxaudio.org/">Linux Audio Wiki</a>
+
+.. |jack| raw:: html
+
+ <a target="blank" href="https://jackaudio.org/">JACK</a>
+
+.. |getting involved| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Getting_involved">getting involved</a>
+
+.. |supercollider| raw:: html
+
+ <a target="blank" href="https://supercollider.github.io/">SuperCollider</a>
+
+.. |realtime kernel| raw:: html
+
+ <a target="blank" href="https://wiki.linuxfoundation.org/realtime/start">realtime kernel</a>
+
+.. |arch linux developers| raw:: html
+
+ <a target="blank" href="https://archlinux.org/people/developers/">Developers</a>
+
+.. |arch linux trusted users| raw:: html
+
+ <a target="blank" href="https://archlinux.org/people/trusted-users/">Trusted Users</a>
+
+.. |arch linux support staff| raw:: html
+
+ <a target="blank" href="https://archlinux.org/people/support-staff/">Support Staff</a>
+
+.. |releng| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/releng/">releng</a>
+
+.. |arch-release-promotion| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/arch-release-promotion/">arch-release-promotion</a>
+
+.. |arch-repo-management| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/arch-repo-management/">arch-repo-management</a>
+
+.. |archiso| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/archiso/">archiso</a>
+
+.. |rfc process| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/rfcs/">RFC process</a>
+
+.. |arch linux conferences| raw:: html
+
+ <a target="blank" href="https://conf.archlinux.org/">Arch Linux Conferences</a>
+
diff --git a/posts/2022/managing-binary-package-repositories.rst b/posts/2022/managing-binary-package-repositories.rst
new file mode 100644
index 0000000..89f203f
--- /dev/null
+++ b/posts/2022/managing-binary-package-repositories.rst
@@ -0,0 +1,193 @@
+.. title: Managing binary package repositories
+.. slug: managing-binary-package-repositories
+.. date: 2022-07-02 13:19:59 UTC+02:00
+.. tags: arch linux, packaging, repod, dbscripts
+.. category: archlinux
+.. link:
+.. description:
+.. type: text
+
+In `Packaging for Arch Linux
+<https://sleepmap.de/2022/packaging-for-arch-linux>`_ I described the ins and
+outs of binary repository management and some of the issues that come with the
+tooling currently used by |arch linux|.
+
+In this article I will highlight the work on new tooling and its features.
+
+Since my last write-up on this topic, the project formerly known as
+``arch-repo-management`` has been renamed to ``repod`` (as in *repo-d*) and has
+just seen its first minor release. 🎉
+
+You can find its documentation at https://repod.archlinux.page.
+
+.. TEASER_END
+
+.. note::
+
+ The https://archlinux.page domain has recently been acquired by Arch Linux to
+ serve as the common platform for documentation of projects driven by the
+ distribution.
+
+Please note, that |repod| 0.1.0 is still alpha grade software and **should
+not** be used to actually manage binary package repositories at this point in
+time!
+
+However, it is already possible to do a few things with the software and if you
+are able to test it or are interested in helping develop it, that is very much
+welcomed!
+
+On Arch Linux you can install it using |pacman|:
+
+.. code:: sh
+
+ pacman -S repod
+
+On other distributions (even on macOS!) you may install it using |pip| (|repod|
+is |available on pypi|) until your respective package management system makes
+the software available to you on a system level:
+
+.. code:: sh
+
+ pip install --user repod
+
+Working on repod
+----------------
+
+Since 2021 I have been on and off working on what is now |repod|. The project
+is written in typed |python| and is extensively tested using |pytest|.
+
+Work first began after |arch conf| 2019, at which a working group had looked
+into improving the workflows currently employed by the distribution and pushing
+for tooling that would allow moving away from an |svn| monorepo based approach
+to a deconstructed |git| setup.
+
+A proof of concept (PoC) to mimic the behavior of |dbscripts| had been created,
+but after 2019 this work laid dormant.
+
+Over 2021 I have spent time to transform parts of the PoC into a Python project
+following best practices for development (e.g. type hints following |pep0484|,
+100% test coverage, data validation using |pydantic| models), exposing first
+features in scripts.
+
+In 2022 more work has been done to extend validation and transform the project
+into a package based setup for easier handling and extension in the future.
+
+Concepts of repod
+-----------------
+
+Contrary to |dbscripts|, |repod| follows a paradigm in which it is largely
+decoupled from the |source repository| of the binary packages it maintains and
+aims at becoming a self-contained service.
+
+Package files and their signatures are consumed, relevant metadata is extracted
+and transferred to a |management repository|, which is where the state of
+each |binary repository| is kept.
+
+Available packages in a given |binary repository| are exposed to |pacman| via
+|sync database| files. The |management repository| contents can be
+(transparently and reproducibly) transformed into |sync database| files and
+vice versa.
+
+The above functionality is exposed on the command line via |repod-file|.
+
+Upcoming work
+-------------
+
+As mentioned above, |repod| is not yet stable and still misses quite a few
+features.
+The following topics (and more) will be worked on in the next milestones (not
+necessarily in this order):
+
+* file handling (moving package files from staging areas to actual repositories)
+* signature validation (PGP signature validation of package files)
+* handling of debug packages
+* consolidate schema of |management repository|
+* improve logging throughout the project
+* git backend to transparently expose changes to the |management repository|
+* caching for |management repository| state (e.g. to allow fast searches)
+* API to interact with a |repod| instance over the wire in an authenticated fashion
+* client-side tooling to interact with |repod|'s API
+
+There is still a lot of work to be done, so if you have a background in
+|Python| development and are interested in working on a project that is very
+close to the distribution and will likely improve the workflow of many people
+while making binary repository management more transparent to the user, have a
+look at the project's |contribution guidelines| and do not hesitate to reach
+out!
+
+.. |arch linux| raw:: html
+
+ <a target="blank" href="https://archlinux.org">Arch Linux</a>
+
+.. |repod| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/repod">repod</a>
+
+.. |pacman| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/pacman.8">pacman</a>
+
+.. |pip| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/pip.1">pip</a>
+
+.. |available on pypi| raw:: html
+
+ <a target="blank" href="https://pypi.org/project/repod/">available on pypi</a>
+
+.. |python| raw:: html
+
+ <a target="blank" href="https://www.python.org/">Python</a>
+
+.. |pytest| raw:: html
+
+ <a target="blank" href="https://docs.pytest.org/en/latest/">pytest</a>
+
+.. |arch conf| raw:: html
+
+ <a target="blank" href="https://conf.archlinux.org/">Arch Conf</a>
+
+.. |svn| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/svn.1">svn</a>
+
+.. |git| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/git.1">git</a>
+
+.. |dbscripts| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/dbscripts">dbscripts</a>
+
+.. |pep0484| raw:: html
+
+ <a target="blank" href="https://peps.python.org/pep-0484/">PEP 0484</a>
+
+.. |pydantic| raw:: html
+
+ <a target="blank" href="https://pydantic-docs.helpmanual.io/">pydantic</a>
+
+.. |source repository| raw:: html
+
+ <a target="blank" href="https://repod.archlinux.page/repositories/source_repository.html">source repository</a>
+
+.. |management repository| raw:: html
+
+ <a target="blank" href="https://repod.archlinux.page/repositories/management_repository.html">management repository</a>
+
+.. |binary repository| raw:: html
+
+ <a target="blank" href="https://repod.archlinux.page/repositories/binary_repository.html">binary repository</a>
+
+.. |sync database| raw:: html
+
+ <a target="blank" href="https://repod.archlinux.page/repositories/sync_database.html">sync database</a>
+
+.. |repod-file| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/repod-file.1">repod-file</a>
+
+.. |contribution guidelines| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/repod/-/blob/79a0fa9aa4a4d9def6dad24805f9bbff0388f734/CONTRIBUTING.md">contribution guidelines</a>
+
diff --git a/posts/2022/new-pgp-key-id-1793dad5d803a8ffd7451697bb992f9864fad168.rst b/posts/2022/new-pgp-key-id-1793dad5d803a8ffd7451697bb992f9864fad168.rst
new file mode 100644
index 0000000..15ce8fb
--- /dev/null
+++ b/posts/2022/new-pgp-key-id-1793dad5d803a8ffd7451697bb992f9864fad168.rst
@@ -0,0 +1,182 @@
+.. title: New PGP key ID 1793DAD5D803A8FFD7451697BB992F9864FAD168
+.. slug: new-pgp-key-id-1793dad5d803a8ffd7451697bb992f9864fad168
+.. date: 2022-04-30 10:35:57 UTC+02:00
+.. tags: chain of trust, gnupg, gpg, infrastructure, openpgp, sequoia, sq, web key directory, web of trust
+.. category: admin
+.. link:
+.. description:
+.. type: text
+
+As my current |PGP| key ``91BD8815FE0040FA7FF5D68754C28F4FF5A1A949`` will be
+expired soon, I have created a new one to replace it.
+
+You can get my new key ``1793DAD5D803A8FFD7451697BB992F9864FAD168`` as well as
+the old one and the cross-signatures required to establish the |chain of trust|
+between the two via Web Key Directory (|WKD|) (which should be used
+automatically by ``gpg >= 2.1.23``).
+
+To not deal with the rather convoluted |gnupg| tooling I have created a
+deployment method for this using |sequoia-pgp|'s |sq|, about which you can read
+in the rest of this article.
+
+.. TEASER_END
+
+Key servers
+===========
+
+Historically, there has been a set of |key servers|, which have been used to
+distribute the public keys of users centrally and/ or in a synchronized
+fashion. These key servers have been widely relied upon, but they suffer(ed)
+from a lot of issues in regards to privacy, stability and speed. Most notably
+the Synchronized Key Server (|SKS|) system collapsed under its technical debt
+and had to be shut down.
+
+To this day there are still other large, non-synchronized keyserver systems
+around (e.g. |hockeypuck|, which drives https://keyserver.ubuntu.com), but they
+all suffer from the fact, that a large centralized setup, in which keys are
+only ever appended, does not scale.
+
+Additionally, not all keyserver systems support all key types or signatures on
+keys, which is problematic, as they can not reflect upon |chain of trust|
+between two or more keys. This is very problematic for the |web of trust| of
+|PGP|.
+
+Web Key Directory
+=================
+
+At the time of writing the |WKD| system is formalized in
+|draft-koch-openpgp-webkey-service-11|. It describes a decentralized way of
+providing public key material via a given domain's webserver, by exposing
+specially crafted files.
+
+WKD Deployment
+==============
+
+Personally, I believe that the |gpg| commandline interface is incredibly
+convoluted and very complex. I therefore used |sequoia-pgp|'s |sq| instead to
+combine PGP public key material and prepare the required directory structure.
+
+In my personal |wkd| project I assembled a simple system consisting of easy to
+prepare directories in which to place PGP public keys, which are converted to a
+keyring using |sq keyring join|, converted into a |WKD| structure using |sq wkd
+generate| and synchronized using |rsync|.
+
+As I do not provide an ``openpgpkey`` subdomain, I am using a direct domain
+directory structure (see |WKDHosting| for further details).
+
+Using keys from WKD
+===================
+
+In theory all that is required for |gpg| to make use of |WKD| is a version
+``>=2.1.23``. However, its use can be somewhat confusing:
+
+.. code:: sh
+
+ gpg --locate-keys dave@sleepmap.de
+
+The above only returns the new key
+``1793DAD5D803A8FFD7451697BB992F9864FAD168``, but not the old
+``91BD8815FE0040FA7FF5D68754C28F4FF5A1A949``. It is entirely opaque to the user
+as to why.
+
+Meanwhile with |sq wkd get| it is possible to return the public key material of
+both keys:
+
+.. code:: sh
+
+ sq wkd get dave@sleepmap.de
+
+The certificates can be inspected directly using |sq inspect|:
+
+.. code:: sh
+
+ sq inspect --certifications <(sq wkd get dave@sleepmap.de)
+
+Additionally, the certificates can be imported into an existing |gnupg| based
+keyring:
+
+.. code:: sh
+
+ gpg --import <(sq wkd get dave@sleepmap.de)
+
+
+Using |WKD|, the need for providing a separate PGP public key file in the
+context of this website has been made obsolete and I have therefore instead
+replaced it with plain mentions of the PGP key IDs on the `about page
+<https://sleepmap.de/about/>`_.
+
+.. |PGP| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy">PGP</a>
+
+.. |chain of trust| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Chain_of_trust">chain of trust</a>
+
+.. |web of trust| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Web_of_trust">web of trust</a>
+
+.. |WKD| raw:: html
+
+ <a target="blank" href="https://wiki.gnupg.org/WKD">WKD</a>
+
+.. |gnupg| raw:: html
+
+ <a target="blank" href="https://gnupg.org/">gnupg</a>
+
+.. |sequoia-pgp| raw:: html
+
+ <a target="blank" href="https://sequoia-pgp.org/">sequoia-pgp</a>
+
+.. |sq| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/sq.1">sq</a>
+
+.. |key servers| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Key_server_(cryptographic)">key servers</a>
+
+.. |SKS| raw:: html
+
+ <a target="blank" href="https://github.com/SKS-Keyserver/sks-keyserver">SKS</a>
+
+.. |hockeypuck| raw:: html
+
+ <a target="blank" href="https://github.com/hockeypuck/hockeypuck">hockeypuck</a>
+
+.. |draft-koch-openpgp-webkey-service-11| raw:: html
+
+ <a target="blank" href="https://tools.ietf.org/id/draft-koch-openpgp-webkey-service-11.html">draft-koch-openpgp-webkey-service-11</a>
+
+.. |gpg| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/gpg.1">gpg</a>
+
+.. |wkd| raw:: html
+
+ <a target="blank" href="https://git.sleepmap.de/dave/wkd.git/">wkd</a>
+
+.. |sq keyring join| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/sq-keyring-join.1">sq keyring join</a>
+
+.. |sq wkd generate| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/sq-wkd-generate.1">sq wkd generate</a>
+
+.. |rsync| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/rsync.1">rsync</a>
+
+.. |WKDHosting| raw:: html
+
+ <a target="blank" href="https://wiki.gnupg.org/WKDHosting">WKDHosting</a>
+
+.. |sq wkd get| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/sq-wkd-get.1">sq wkd get</a>
+
+.. |sq inspect| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/sq-inspect.1">sq inspect</a>
diff --git a/posts/2022/packaging-for-arch-linux.rst b/posts/2022/packaging-for-arch-linux.rst
new file mode 100644
index 0000000..0b27eeb
--- /dev/null
+++ b/posts/2022/packaging-for-arch-linux.rst
@@ -0,0 +1,1152 @@
+.. title: Packaging for Arch Linux
+.. slug: packaging-for-arch-linux
+.. date: 2022-04-06 13:22:53 UTC+02:00
+.. tags: arch linux, packaging, reproducible builds, arch-repo-management, dbscripts
+.. category: archlinux
+.. link:
+.. description:
+.. type: text
+
+In `Arch, a recap <https://sleepmap.de/2022/arch-a-recap>`_ I elaborated a bit
+on my reasons for getting involved with Arch Linux. In this post I would like
+to highlight a few technical details and give a "behind the scenes" when it
+comes to packaging on and for Arch Linux.
+This post is written from the viewpoint of a distribution packager, but it
+is likely to contain information also useful to people packaging on different
+distributions or for private purposes.
+
+.. TEASER_END
+
+|arch linux| is a |linux distribution|, that offers binary packages in
+|software repositories| (aka. repos). To achieve this, packages are built from
+source files using tooling that is developed by the distribution and various
+volunteers. The resulting binary packages are then provided to users on mirrors
+of the distribution (i.e. package files and their cryptographic signatures are
+provided by |web servers|) and are downloaded, verified, validated and
+installed using a |package manager|.
+
+.. note::
+
+ Other distributions may use different concepts. E.g. |gentoo linux| offers
+ installation media that is used to install a base system. From then on users
+ rebuild the software on their systems themselves based on distribution
+ provided source files. There are no binary packages for users to install.
+
+The upsides of a central software package system facilitating binary repos are
+
+- users do not have to build the software on their systems themselves, which
+ e.g. for web browsers can take a very long time and eat a lot of energy
+- software for the entire system can be updated with one command and only takes
+ as long as download and extraction of a given set of packages
+
+Packages
+========
+
+When looking at the concept of binary software packages it probably helps to
+consider the point of view from e.g. Windows and macOS, which both provide
+software to users in different ways and give a good case for comparison. In
+case you already know how binary packages function and compare, skip this
+section.
+
+For brevity I will skip the proprietary app stores in the below examples as
+they abstract the concept of software installation to the point where this is
+opaque to the user and delivers no direct comparison in the context of packages
+(while under the hood most app stores use the below mentioned technologies).
+
+Windows
+-------
+
+On Windows software is usually provided by the means of an installer (e.g.
+shipped as a ``.exe`` or ``.msi`` file). An installer usually needs to be
+downloaded from thirdparty websites (often without verification) and then
+executed one-by-one. The installer often already contains the (prebuilt) files
+to be installed (sometimes files are also downloaded by the installer
+application on-the-fly), offers some form of modification (e.g. the
+installation location), installs the bundled or downloaded files and modifies
+the system's registry (e.g. for auto-start or other features). Although
+Microsoft has attempted to consolidate its installation backends, the user
+experience is usually still a mixed bag.
+System updates (those modifying the operating system) are handled by the OS
+itself and the user usually has not much of a say when/ how that happens (this
+can be modified to some extent). Additionally, some hardware may not use the
+latest version of Windows due to software-based |planned obsolescence|.
+
+MacOS
+-----
+
+On macOS software can be installed using images or installers (shipped as e.g.
+``.dmg`` and ``.pkg`` respectively). The download of the files in question
+usually functions in the same way as it does on Windows (unverified downloads
+from thirdparty websites). Where with images the user experience is usually
+*"drag and drop"* from a mounted image to the list of applications, installers
+on the other hand offer similar functionality to how installers work on Windows
+(e.g. setup auto-starting).
+System updates, similar to those on Windows are handled by macOS itself and
+also here software enforced |planned obsolescence| is a thing.
+
+Looking at the above examples it becomes clear, that automation on both
+platforms is quite terrible: The distinction between OS updates and *"other
+software"* leads to a mix and match approach towards updates, that is (if at
+all) only partly remedied by externally developed and provided package managers
+for some of the *"other software"* (e.g. |homebrew| or |chocolatey|), but at
+best remains a fragmented experience for the user.
+
+Linux
+-----
+
+On distributions that offer binary package repositories, users use a package
+manager to install packages and to upgrade **all software** [1]_ on their
+system.
+Packages are essentially |archive files|, that are downloaded, verified and
+extracted by the package manager. As the files contained in (distribution)
+packages follow a well-defined location schema (e.g. |filesystem hierarchy
+standard| or |file-hierarchy|), the system can check for file conflicts and
+users can usually have reasonable assumptions about where files of a package
+are located (package managers usually also track the files of all packages).
+Additional functionality, such as post install scripts (e.g. to create users or
+to change ownership on files) are usually
+contained in package files and executed after installation. However, on systemd
+based distributions, much of the post installation tasks have been streamlined
+with the help of |sysusers.d| and |tmpfiles.d| (more on that later). Some
+distributions also make use of non-standardized hooks (see |alpm-hooks| for how
+this is implemented for |pacman|), that are used by the package manager for
+certain tasks on files that are not owned by one specific package (e.g. update
+font cache).
+
+Build tooling
+=============
+
+The most basic build tooling for Arch Linux - |makepkg| - is bundled with
+|pacman_website| (the package manager used to install all software packages on the
+distribution). It is used in conjunction with a |PKGBUILD|, which as a package
+source file describes where/ how to get a package's source files (and in which
+version), how to build and test it (if applicable) and how/ where to install
+it.
+
+In case you have experience with |bash|: Both ``makepkg`` and ``PKGBUILDs`` are
+written in it.
+
+When building packages with plain ``makepkg``, the built package will be
+created in the context of the user's system and as such will make use of the
+software available on the user's system. While this works (given all
+dependencies are met) it is not recommended to do so, as the user's
+system may use custom packages or settings to ``makepkg`` (see |makepkg.conf|),
+that can alter the outcome of the build, which may make the package unusable on
+another system.
+
+Clean chroots
+=============
+
+To enable builds, that are done in a clean environment (i.e. one that only has
+official distribution packages installed and does not depend on configuration
+or custom packages on a local system), Arch Linux and various contributors have
+created special build tooling, which is contained in the |devtools| project.
+
+With the help of |makechrootpkg| one can run ``makepkg`` in a |systemd-nspawn|
+based |chroot|, which will only have the packages installed, that are required
+for building, testing and running a given package.
+
+Using |makechrootpkg| and its various repository-specific symlinks is how Arch
+Linux packagers build all packages in the official repositories.
+
+.. note::
+
+ It is generally advisable to build **all packages** in a clean environment.
+
+An implict upside of using ``makechrootpkg`` to build packages is, that
+|checkpkg| and |namcap| are being run on the resulting package, which can give
+valuable hints at possible improvements of the package.
+
+Building packages
+=================
+
+First off: There are sometimes a lot of subtleties involved with packaging and
+especially producing packages that are of good quality. In the following
+sections I will discuss a few tools and packaging specifics, that may seem
+quite overwhelming or complicated at first. Luckily, a lot of the tooling is
+fairly well documented and it is probably always good to remember, that
+everyone is a learner and that as the tooling and the best practices evolve,
+this is an open-ended topic.
+
+A good starting point is always to use ``makechrootpkg`` and to adhere to the
+|arch package guidelines|.
+
+.. note::
+
+ There is the |arch package guidelines category| of more specific guidelines
+ for various programming languages and special use-cases.
+
+Getting package build sources
+-----------------------------
+
+The act of getting the sources for a binary package is described in the context
+of the |arch build system| (ABS). While users without write access to the Arch
+Linux source repositories can rely upon |asp| to get to the package build
+sources, the official packagers rely on a rather organically grown packaging
+workflow, that is described in |howto be a packager|.
+
+At the time of writing, Arch Linux still relies on two monolithic |svn|
+repositories for the package build sources (one for the ``[core]`` and
+``[extra]`` repositories and one for the ``[community]`` and ``[multilib]``
+repositories) which are exported to |git| via |git-svn| on the official Arch
+Linux Github organization (|svntogit-packages| and |svntogit-community|,
+respectively).
+
+.. note::
+
+ Work is underway to switch to |git| for the package build sources. However,
+ this has implications for maintaining state of resulting binary repositories
+ (this is currently done in the svn repositories). While |dbscripts| has been
+ used for managing the state for many years, it is likely to be replaced by
+ |arch-repo-management| in the future.
+ Additionally, it should be mentioned, that such a switch is not trivial after
+ 20 years, if one is also concerned with the technical feasibility and
+ maintainability of the tooling in use.
+
+PKGBUILDs
+---------
+
+As mentioned earlier, |PKGBUILD| files are really just |bash| scripts, that are
+being evaluated by |makepkg|. As such they define a few variables and functions
+(some of which are required, others only being optional).
+
+The below example shows a bare minimum example, derived from the prototype
+files, that can be found in ``/usr/share/pacman/``:
+
+.. code:: sh
+
+ # Maintainer: Your Name <youremail@domain.com>
+ pkgname=dummy-package
+ pkgver=0.1.0
+ pkgrel=1
+ pkgdesc="A dummy package"
+ arch=(any)
+ url="https://my-upstream.link/to/dummy-package"
+ license=(GPL3)
+ depends=(another-package)
+ optdepends=('some-additional: for additional feature X')
+ source=(https://my-upstream.link/to/$pkgname-$pkgver.tar.gz)
+ b2sums=('THISISADUMMYCHECKSUM')
+
+ package() {
+ make DESTDIR="$pkgdir" install -C $pkgname-$pkgver
+ }
+
+To go through the essentials of this very minimalistic example, which assumes
+that we have a project using |make| to install a few files:
+
+- While the ``Maintainer`` comment is technically not required, it is always
+ helpful for others trying to contact the author of a given package build
+ source
+- ``pkgname``: The name of the package. Refer to the wiki section
+ |pkgbuild#pkgname| for further info (e.g. restrictions)
+- ``pkgver``: The (upstream) version of the package. Refer to the wiki section
+ |pkgbuild#pkgver| for further info (e.g. restrictions)
+- ``pkgrel``: The release version of the package, which identifies the build of
+ the particular package in version ``pkgver``. This is a string specific to
+ Arch Linux (see |pkgbuild#pkgrel|) and *is not related to the upstream
+ version* of the software.
+- ``pkgdesc``: A short description of what this package provides
+- ``arch``: The architecture of the resulting package. As this is an array, it
+ can contain several entries (``makepkg`` will envoke a build for each
+ architecture). At the time of writing Arch Linux only supports the ``x86_64``
+ and ``any`` architectures.
+- ``url``: The URL of the upstream project (e.g. a website or a link to the
+ |version control| sources)
+- ``license``: The licenses that apply to the project. This again is an array
+ and may contain several licenses. In case licenses that are not covered by
+ the |licenses package| are encountered, their license files must be installed
+ in the ``package()`` function (refer to the wiki section |pkgbuild#license|
+ for further information).
+- ``depends``: An array of runtime dependencies for the package. They will be
+ installed automatically during build when building with ``makechrootpkg`` or
+ ``makepkg -s``.
+- ``optdepends``: An array of optional dependencies and a short description
+ about their purpose. These packages will not be installed during build time
+ (for this ``makedepends`` needs to be used).
+- ``source``: An array of resources for ``makepkg`` to retrieve. As |makepkg|
+ is able to handle various |version control| systems, local and remote files,
+ as well as to rename files, it is advisable to read the relevant man page
+ section for ``makepkg``.
+- ``b2sums``: An array of checksums for all resources in the ``source`` array.
+ It is advisable to use either (or all of) ``sh256sums``, ``sha512sums`` or
+ ``b2sums`` as older hashing mechanisms are by now unsafe (see
+ |pkgbuild#integrity|). The checksums are used to guard against changing (and
+ potentially malicious) upstream resources. The resources and checksums for a
+ new version of a given package may be retrieved and updated using
+ |updpkgsums| (contained in the |pacman-contrib| package).
+- ``package()``: This function defines all steps necessary to install the files
+ of the upstream project to an empty location (represented by the *magic
+ variable* ``"$pkgdir"``), that will contain all installable files of the
+ package. This function is called using |fakeroot|, which means that to the
+ installing processes it looks like they are being executed by ``root``.
+
+PGP validation
+--------------
+
+Upstream project resources (e.g. signed source tarballs or git tags/ commits)
+can be validated using |pgp|.
+
+.. note::
+
+ While other mechanisms are theoretically possible (e.g. |signify| or
+ |cosign|), they are currently not implemented in the context of |makepkg|.
+
+Technically all that is required for this is,
+that the ``validpgpkeys`` array in the PKGBUILD contains at least one
+retrievable PGP key ID and that the ``source`` array contains either a ``.sig``
+or ``.asc`` file valid for one of the resources, or that a git object to be
+checked is targetted using the ``?signed`` identifier (see
+|makepkg#signature_checking| and |pkgbuild#using_vcs_sources|).
+
+Although it is advisable to have cryptographic signature validation (e.g.
+using |pgp|) for releases, this should only be considered under the following
+circumstances in regards to an upstream project:
+
+* there is a track record of signing releases with the same key ID and the
+ project specifically provides the expectable key ID publicly (e.g. on the
+ website)
+* keeps a |chain of trust| between multiple and/or successive key IDs
+* no key easily used by multiple users is used (e.g. Github's PGP key, which
+ can be used by multiple users of a given Github project and is not handled by
+ the users themselves)
+
+The first point is usually easy to check up on, while the 2nd might require
+getting in touch with the project developers if it happens (or happened in the
+past) - this is the case more often than you would think and does block package
+updates, as a new key ID must not be trusted without investigating the cause
+for a missing |chain of trust| to prevent a potential |supply chain attack|!
+
+.. note::
+
+ I am contemplating to prepare an |arch linux rfc| for this, as the handling
+ of PGP signed sources is not well defined for the distribution and often
+ leads to mishandling (e.g. using new PGP key IDs without having a |chain of
+ trust|).
+
+The 3rd point practically provides a false sense of security: A PGP key signed
+a release of a project, but in actuality multiple members of a project may have
+access to this functionality. From the outside it is impossible to tell who
+triggered a release and signed off on it (it could easily be malicious because
+someone's Github account has been hacked).
+
+Reproducibility
+---------------
+
+Arch Linux as a distribution is committed to packages becoming bit-for-bit
+reproducible (have a look at the overarching |reproducible builds| project for
+more background information on the general topic). The status of the current
+packages in the official repositories is tracked on
+https://reproducible.archlinux.org, which is backed by |rebuilderd|.
+
+After building a package it can be rebuilt using |makerepropkg|, which may use
+|diffoscope| on the resulting package in case it is not reproducible.
+
+As the use of ``makerepropkg`` requires the ``PKGBUILD`` used to build the
+initial package, it can not be used when only a package file is available.
+However, for that use-case |repro| may be used.
+
+.. note::
+
+ Both tools make use of the |buildinfo| files contained in each binary
+ package.
+
+Dealing with the strange
+========================
+
+In `building packages <#building-packages>`_ we have looked at some of the more
+basic use-cases. The following sub-sections will deal with more uncommon or
+very specific ones as well as problems at the intersection of build tooling and
+binary repository management.
+
+Split packages
+--------------
+
+There are situations, in which one wants to build several packages from a
+single ``PKGBUILD``. Those are usually:
+
+- the documentation of the project is very large
+- certain features (e.g. language bindings) are not required by the main
+ application or use-case of the project
+- specific functionality would require a large tree of dependencies but is not
+ required for the main application or use-case
+
+In all three cases this can be handled using a split package setup in which the
+extra functionality (as a package) is declared an optional dependency of the
+main package.
+
+To create a split package, the ``pkgname`` variable of the ``PKGBUILD`` is
+turned into an array, containing multiple package names, while the ``pkgbase``
+variable (see |pkgbuild#pkgbase|) should be set. Additionally, the generic
+``package()`` function needs to be split up into specific functions for each
+package (``prepare()``, ``build()`` and ``check()`` are shared).
+
+Using the example from `PKGBUILDs <#pkgbuilds>`_, this is how it would look
+like when e.g. splitting out documentation (assuming that the upstream project
+provides separate install targets for the components).
+
+.. code:: sh
+
+ # Maintainer: Your Name <youremail@domain.com>
+ pkgbase=dummy-package
+ pkgname=(dummy-package dummy-package-docs)
+ pkgver=0.1.0
+ pkgrel=1
+ pkgdesc="A dummy package"
+ arch=(any)
+ url="https://my-upstream.link/to/dummy-package"
+ license=(GPL3)
+ makedepends=(another-package)
+ source=(https://my-upstream.link/to/$pkgname-$pkgver.tar.gz)
+ b2sums=('THISISADUMMYCHECKSUM')
+
+ package_dummy-package() {
+ depends=(another-package)
+ optdepends=(
+ 'dummy-package-docs: for documentation'
+ 'some-additional: for additional feature X'
+ )
+
+ make DESTDIR="$pkgdir" install-scripts -C $pkgname-$pkgver
+ }
+
+ package_dummy-package-docs() {
+ make DESTDIR="$pkgdir" install-docs -C $pkgname-$pkgver
+ }
+
+Binary repository management
+----------------------------
+
+The resulting packages of a build process can be installed on a local machine,
+but are often of course more useful, if more systems can install them as well.
+For this purpose the repository sync databases exist, which |pacman| uses (see
+|libalpm_databases|) to retrieve the difference between a remote package
+repository and a local machine's state and to figure out which packages to
+upgrade.
+
+The most rudimentary actions (adding and removing packages, optionally signing
+a database) on a binary repository can be done using |repo-add| and
+|repo-remove|, which are shipped with |pacman|. As the tooling is very basic,
+it does not offer any form of state tracking (i.e. a log of actions, such as
+additions or removals done to a sync database by a specific user).
+
+At the time of writing Arch Linux packagers make use of |dbscripts| for the
+binary repository management, which also does (a form of) state tracking by
+interacting with and using the the two |svn|-based monorepos for package build
+sources for this purpose.
+The tooling consists of a set of shell scripts (making use of |repo-add| and
+|repo-remove| internally), that are being called by authorized users on a
+specific host over |ssh|. The user authentification is therefore done using
+|ssh| while the user authorization is implemented using plain unix groups
+(different sets of packagers have access to ``[core]`` and ``[extra]`` vs.
+``[community]`` and ``[multilib]`` - often only for historical reasons).
+However, this setup is showing its age and comes with its own set of pitfalls:
+
+- changes to repositories are not externally auditable
+- package data is only checked rudimentarily
+- integrity of repository sync databases can not be guaranteed
+- repository sync databases can not be rebuilt to a specific state
+- setting the target binary repository for a package is a manual operation
+- due to the blocking nature of dbscripts, it is possible to brick the state of
+ a repository if e.g. connection to the host running dbscripts is lost during
+ the move of packages between two
+ repositories
+- it is not possible to setup rebuild-specific staging repositories on the fly
+- many users need |ssh| access to a machine
+
+This all being said, work is underway with |arch-repo-management| to provide a
+more manageable and easy to configure solution that runs as a service and does
+not rely on multiple users to have direct access on a target system.
+One of the project's main focusses is to be able to verify incoming package
+data and to fully decouple the state from the repository sync databases (to be
+able to rebuild them whenever needed).
+Going forward it should become more easy to setup ephemeral staging
+repositories to build against and safer to move data due to more atomic
+repository operations, while allowing externals to audit each repository's
+history. Currently the project is still far from being usable though and there
+are quite a few things left to be implemented. Switching from the current setup
+in which both package build sources and binary repository state are handled by
+one |version control| system, to one where these concerns are separated is a
+hard problem, especially when one wants to get this right.
+I hope that going forward we will end up with a solution that can be easily
+contributed to and reused also outside of Arch Linux. I will write another post
+in the coming months, that highlights work and concepts of
+|arch-repo-management|.
+
+Distributing trust
+------------------
+
+Packagers use the |makepkg.conf| variables ``PACKAGER`` and ``GPGKEY`` to set
+the packager user ID (i.e. name and e-mail address) and the PGP key ID used for
+signing created packages.
+
+Other users that wish to use packages signed by someone else need to import
+that other user's PGP public key using |pacman-key|.
+
+Arch Linux maintains a |web of trust| between a set of main signing keys and
+all packagers and between all packagers amongst themselves (see the |main keys|
+page for an extensive overview). This setup allows for user systems to evaluate
+whether a given package signature done by a packager is considered trusted (see
+|pacman.conf#package_and_database_signature_checking| for further info).
+These constructs are system-wide PGP keyrings for the use with |pacman| and can
+be handled with |pacman-key|.
+
+.. note::
+
+ The main signing keys are considered **fully trusted** on a user system. They
+ define the root trust for the distribution which is handed down to the
+ packagers.
+
+In the |archlinux-keyring| project the distribution trust of Arch Linux is
+maintained as a set of decomposed PGP public keys and the signatures on them.
+The custom tooling ``keyringctl`` (which uses |sequoia|'s ``sq`` under the
+hood) is used to maintain (e.g. import public keys and signatures) a PGP
+keyring that is packaged in the |archlinux-keyring package| and which is
+automatically added and updated upon install.
+
+More than or equal to three main signing key holders are required to uphold
+the web of trust. More than or equal to three valid main key signatures are
+required for a packager key (if it is itself still valid) to be allowed for
+distributing packages in the official Arch Linux repositories.
+
+.. note::
+
+ Writing the new tooling ``keyringctl`` to manage the distribution trust has
+ been a huge topic of the past year, that |Levente Polyak| and I have been
+ working on, as the previous setup was very brittle. I will elaborate a bit
+ more on that topic in an upcoming post.
+
+
+Sonames
+-------
+
+Linux distributions mostly build C and C++ libraries and executables using
+|dynamic linking|. This implies, that shared libraries usually provide a
+|soname| (e.g. ``libexample.so.1``), which is in turn used (i.e. linked
+against) by one or more other libraries or executables.
+If the |application binary interface| (ABI) of the library in question changes,
+its |soname| should be increased as well (e.g. ``libexample.so.2``). If a
+package with an updated soname is released and installed, without rebuilding
+any of the packages depending on it, those will fail to load (the now
+non-existent) ``libexample.so.1`` shared object.
+
+A common task as a packager is therefore to do rebuilds for libraries and
+executables when a soname change is introduced. Depending on the library
+introducing the soname change or the library/executable being affected by it,
+this is sometimes a bit of a painful and time consuming experience.
+While it is not unheard of that projects either forget to introduce a soname
+change (silently breaking consumers) or accidentally downgrade their soname,
+consumers are more likely to run into trouble because of not yet implementing
+changes introduced by the ABI change (requiring patches not yet included in a
+stable release).
+
+To safeguard against cases in which soname changes went unnoticed and packages
+are pushed to the repositories, it is possible to make use of |makepkg|'s
+builtin dependency resolution. Extending upon the example in `PKGBUILDs
+<#pkgbuilds>`_ and assuming that ``libexample`` is the package providing
+``libexample.so``:
+
+.. code:: sh
+
+ # Maintainer: Your Name <youremail@domain.com>
+ pkgname=libexample
+ pkgver=1.0.0
+ pkgrel=1
+ pkgdesc="A dummy library"
+ arch=(any)
+ url="https://my-upstream.link/to/libexample"
+ license=(GPL3)
+ depends=(glibc)
+ provides=(libexample.so)
+ source=(https://my-upstream.link/to/$pkgname-$pkgver.tar.gz)
+ b2sums=('THISISADUMMYCHECKSUM')
+
+ build() {
+ make -C $pkgname-$pkgver
+ }
+
+ package() {
+ make DESTDIR="$pkgdir" install -C $pkgname-$pkgver
+ }
+
+.. code:: sh
+
+ # Maintainer: Your Name <youremail@domain.com>
+ pkgname=dummy-package
+ pkgver=0.1.0
+ pkgrel=1
+ pkgdesc="A dummy package"
+ arch=(any)
+ url="https://my-upstream.link/to/dummy-package"
+ license=(GPL3)
+ depends=(another-package libexample libexample.so)
+ optdepends=('some-additional: for additional feature X')
+ source=(https://my-upstream.link/to/$pkgname-$pkgver.tar.gz)
+ b2sums=('THISISADUMMYCHECKSUM')
+
+ build() {
+ make -C $pkgname-$pkgver
+ }
+
+ package() {
+ make DESTDIR="$pkgdir" install -C $pkgname-$pkgver
+ }
+
+If during build time ``libexample`` provided ``libexample.so.1``, the resulting
+``dummy-package`` will now depend on ``libexample`` and ``libexample.so=1-64``,
+which ``libexample`` provides.
+
+If the ``libexample`` package is then updated while accidentally including a
+soname bump to ``libexample.so.2``, |pacman| will prevent this package from
+being upgraded on a user's system, because it can no longer provide
+``libexample.so.1``, which is required by its consumers (i.e.
+``dummy-package``).
+This only helps against immediate breakage on already installed systems. On
+systems that are about to be installed it would lead to pacman not being able
+to resolve the dependencies and bailing out. It is therefore to be considered a
+stop-gap solution which allows for fixing the package(s) in question, while not
+immediately breaking consumers of ``libexample``.
+
+In the future this feature will be directly built into |makepkg|, removing the
+manual process of identifying shared libraries (and their sonames) which are
+provided by packages.
+
+.. note::
+
+ To identify the sonames provided by a package, |find-libprovides| can be
+ used. Reversely, to identify the sonames required by a specific package
+ |find-libdeps| can be used.
+
+Debug packages
+--------------
+
+The ability to debug software using e.g. |gdb| is very powerful, as it allows
+users to provide vital information about failing software to the packagers and
+upstream projects. For this to work, a package's debug symbols need to be
+provided to the debugger.
+In February 2022 Arch Linux has started using |debug packages and debuginfod|,
+which allows just that.
+
+Creating a package and additionally also building its debug symbols has now
+become as easy as adding ``debug`` to the ``options`` array in a |pkgbuild|
+(until this option eventually is added to the default for packagers of the
+distribution).
+
+.. note::
+
+ At the time of writing not all issues with non-|file-hierarchy| compliant
+ files and directories have been solved yet, but a large set of debug packages
+ have already been built across all official repositories.
+
+Creating users
+--------------
+
+Historically, system users and groups for packages have been created
+using ``.install`` scripts (see |pkgbuild#install|). This had the downside of
+requiring a specific |user identifier| (UID) and/or |group identifier| (GID)
+(see |UID/ GID database| for specific assignments) if file ownerships also
+needed to be handled in the context of a package.
+Additionally, the user and group creation was not standardized and required a
+script (run as ``root``), which was only run *after* creating and installing
+the package and therefore not easily testable.
+
+With the adoption of |systemd| and specifically |sysusers.d| the workflow has
+changed to installing a single file in the context of a package to the vendor
+location ``/usr/lib/sysusers.d/``. Based on the |systemd| |alpm-hooks| setup
+the configuration is applied using |systemd-sysusers|.
+
+Changing files after package installation
+-----------------------------------------
+
+Similar to how system users and groups have been created in the past, file
+modifications (e.g. ownership, |extended file attributes| or |setuid|) have
+been done using ``.install`` scripts or directly in PKGBUILDs. The problem with
+this approach was, that it required the specific assignment and pinning of UIDs
+and GIDs when creating the required users and groups, *before* doing the file
+modifications (e.g. using |chown|).
+
+This task has been made less complex with |tmpfiles.d|, which allows for
+packaging a single file in a package to the vendor location
+``/usr/lib/tmpfiles.d/``. Due to the ordering of |alpm-hooks| first users
+and groups are created and only afterwards the file configuration is applied
+using |systemd-tmpfiles|, allowing for diverse scenarios.
+
+Packaging
+=========
+
+Working on packages for software written in different languages (e.g. |php|,
+|python|, |ruby|, |c|, |c++| or |rust|) using various build systems surely
+makes for a very interesting Github profile eventually (due to providing issue
+reports and fixes to many projects).
+
+You can find the |list of my packages| amongst the official repositories.
+Moreover I currently maintain two |unofficial user repositories|: |[realtime]|
+and |[pro-audio-legacy]|
+
+Packaging can be a fun but also a very time consuming and frustrating pastime.
+As such there are many many more examples and specifics I could list (but this
+article is already quite dense I am afraid).
+
+.. note::
+
+ None of the Arch Linux package maintainers are payed for their work, which
+ they do solely in their free time and the project is not a commercial
+ endeavor. Some dependency chains are fairly complex and require time and
+ care. The reasons as to why a package is not updated is not always obvious to
+ the outside and it could be due to various technical problems or the packager
+ just lacking the time. Please be mindful about this and instead of getting
+ upset try to lend a helping hand packaging (it is usually much appreciated)
+ or consider |getting involved|.
+
+At any rate, I hope I could spark your curiosity! If you are interested in
+finding out more about packaging for specific languages or best practices,
+the following are some good starting points:
+
+* |arch package guidelines| and |arch package guidelines category|
+* |#archlinux| and |#archlinux-aur| on |libera.chat|
+
+.. note::
+
+ Update: I have fixed some typos. Thanks to Andreas Schleifer (Segaja) for
+ noticing them!
+
+ Update: I have fixed more typos. Thanks to `doesntthinkmuch
+ <https://www.reddit.com/user/doesntthinkmuch/>`_ for noticing them.
+
+.. [1] I am excluding `flatpak <https://flatpak.org/>`_ and `snap
+ <https://snapcraft.io/>`_ in this article as they follow an app-store/
+ per-user installation paradigm. However, they relate to system's packaging
+ in that they provide precompiled binaries in a predefined format.
+
+.. |arch linux| raw:: html
+
+ <a target="blank" href="https://archlinux.org">Arch Linux</a>
+
+.. |linux distribution| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Linux_distribution">Linux distribution</a>
+
+.. |software repositories| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Software_repository">software repositories</a>
+
+.. |web servers| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Web_server">web servers</a>
+
+.. |package manager| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Package_manager">package manager</a>
+
+.. |gentoo linux| raw:: html
+
+ <a target="blank" href="https://www.gentoo.org/">Gentoo Linux</a>
+
+.. |planned obsolescence| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Planned_obsolescence">planned obsolescence</a>
+
+.. |homebrew| raw:: html
+
+ <a target="blank" href="https://brew.sh/">Homebrew</a>
+
+.. |chocolatey| raw:: html
+
+ <a target="blank" href="https://chocolatey.org/">Chocolatey</a>
+
+.. |archive files| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Archive_file">archive files</a>
+
+.. |filesystem hierarchy standard| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard">filesystem hierarchy standard</a>
+
+.. |file-hierarchy| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/core/systemd/file-hierarchy.7.en">file-hierarchy</a>
+
+.. |tmpfiles.d| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/tmpfiles.d.5.en">tmpfiles.d</a>
+
+.. |sysusers.d| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/sysusers.d.5.en">sysusers.d</a>
+
+.. |alpm-hooks| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/alpm-hooks.5">alpm-hooks</a>
+
+.. |makepkg| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/makepkg.8">makepkg</a>
+
+.. |pacman| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/pacman.8">pacman</a>
+
+.. |pacman_website| raw:: html
+
+ <a target="blank" href="https://archlinux.org/pacman/">Pacman</a>
+
+.. |PKGBUILD| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/core/pacman/PKGBUILD.5.en">PKGBUILD</a>
+
+.. |bash| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Bash_(Unix_shell)">Bash</a>
+
+.. |makepkg.conf| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/makepkg.conf.5">makepkg.conf</a>
+
+.. |devtools| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/devtools">devtools</a>
+
+.. |makechrootpkg| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/makechrootpkg.1">makechrootpkg</a>
+
+.. |systemd-nspawn| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/systemd-nspawn.1">systemd-nspawn</a>
+
+.. |chroot| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/chroot.1.en">chroot</a>
+
+.. |checkpkg| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/checkpkg.1">checkpkg</a>
+
+.. |namcap| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/namcap.1">namcap</a>
+
+.. |arch package guidelines| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Arch_package_guidelines">Arch package guidelines</a>
+
+.. |arch package guidelines category| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Category:Arch_package_guidelines">Arch package guidelines category</a>
+
+.. |arch build system| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Arch_Build_System">Arch Build System</a>
+
+.. |asp| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/asp.1">asp</a>
+
+.. |howto be a packager| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/DeveloperWiki:HOWTO_Be_A_Packager">HOWTO be a packager</a>
+
+.. |svn| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/svn.1">svn</a>
+
+.. |git| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/git.1">git</a>
+
+.. |git-svn| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/extra/git/git-svn.1.en">git-svn</a>
+
+.. |svntogit-packages| raw:: html
+
+ <a target="blank" href="https://github.com/archlinux/svntogit-packages">svntogit-packages</a>
+
+.. |svntogit-community| raw:: html
+
+ <a target="blank" href="https://github.com/archlinux/svntogit-community">svntogit-community</a>
+
+.. |dbscripts| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/dbscripts">dbscripts</a>
+
+.. |arch-repo-management| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/arch-repo-management">arch-repo-management</a>
+
+.. |make| raw:: html
+
+ <a target="blank" href="https://www.gnu.org/software/make/">make</a>
+
+.. |pkgbuild#pkgname| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/PKGBUILD#pkgname">PKGBUILD#pkgname</a>
+
+.. |pkgbuild#pkgver| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/PKGBUILD#pkgver">PKGBUILD#pkgver</a>
+
+.. |pkgbuild#pkgrel| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/PKGBUILD#pkgrel">PKGBUILD#pkgrel</a>
+
+.. |version control| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Version_control">version control</a>
+
+.. |licenses package| raw:: html
+
+ <a target="blank" href="https://archlinux.org/packages/core/any/licenses/">licenses package</a>
+
+.. |pkgbuild#license| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/PKGBUILD#license">PKGBUILD#licenses</a>
+
+.. |pkgbuild#integrity| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/PKGBUILD#Integrity">PKGBUILD#Integrity</a>
+
+.. |updpkgsums| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/updpkgsums.8">updpkgsums</a>
+
+.. |pacman-contrib| raw:: html
+
+ <a target="blank" href="https://archlinux.org/packages/?q=pacman-contrib">pacman-contrib</a>
+
+.. |fakeroot| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/fakeroot.1">fakeroot</a>
+
+.. |pgp| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy">PGP</a>
+
+.. |signify| raw:: html
+
+ <a target="blank" href="https://github.com/aperezdc/signify">signify</a>
+
+.. |cosign| raw:: html
+
+ <a target="blank" href="https://github.com/sigstore/cosign">cosign</a>
+
+.. |makepkg#signature_checking| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Makepkg#Signature_checking">makepkg#signature_checking</a>
+
+.. |pkgbuild#using_vcs_sources| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/PKGBUILD.5.en#USING_VCS_SOURCES">PKGBUILD#USING_VCS_SOURCES</a>
+
+.. |chain of trust| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Chain_of_trust">chain of trust</a>
+
+.. |supply chain attack| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Supply_chain_attack">supply chain attack</a>
+
+.. |arch linux rfc| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/rfcs">Arch Linux RFC</a>
+
+.. |reproducible builds| raw:: html
+
+ <a target="blank" href="https://reproducible-builds.org/">Reproducible Builds</a>
+
+.. |rebuilderd| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/rebuilderd.1">rebuilderd</a>
+
+.. |makerepropkg| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/makerepropkg.1">makerepropkg</a>
+
+.. |diffoscope| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/diffoscope.1">diffoscope</a>
+
+.. |repro| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/repro.8">repro</a>
+
+.. |buildinfo| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/core/pacman/BUILDINFO.5.en">.BUILDINFO</a>
+
+.. |pkgbuild#pkgbase| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/PKGBUILD#pkgbase">PKGBUILD#pkgbase</a>
+
+.. |libalpm_databases| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/libalpm_databases.3">libalpm_databases</a>
+
+.. |repo-add| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/repo-add.8">repo-add</a>
+
+.. |repo-remove| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/repo-add.8">repo-remove</a>
+
+.. |ssh| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/ssh.1">ssh</a>
+
+.. |web of trust| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Web_of_trust">web of trust</a>
+
+.. |main keys| raw:: html
+
+ <a target="blank" href="https://archlinux.org/master-keys/">main keys</a>
+
+.. |pacman.conf#package_and_database_signature_checking| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/pacman.conf.5#PACKAGE_AND_DATABASE_SIGNATURE_CHECKING">pacman.conf#PACKAGE_AND_DATABASE_SIGNATURE_CHECKING</a>
+
+.. |pacman-key| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/pacman-key.8">pacman-key</a>
+
+.. |archlinux-keyring| raw:: html
+
+ <a target="blank" href="https://gitlab.archlinux.org/archlinux/archlinux-keyring/">archlinux-keyring</a>
+
+.. |sequoia| raw:: html
+
+ <a target="blank" href="https://sequoia-pgp.org/">sequoia</a>
+
+.. |archlinux-keyring package| raw:: html
+
+ <a target="blank" href="https://archlinux.org/packages/core/any/archlinux-keyring/">archlinux-keyring package</a>
+
+.. |Levente Polyak| raw:: html
+
+ <a target="blank" href="https://leventepolyak.net/">Levente Polyak</a>
+
+.. |dynamic linking| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Dynamic_linker">dynamic linking</a>
+
+.. |soname| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Soname">soname</a>
+
+.. |application binary interface| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Application_binary_interface">application binary interface</a>
+
+.. |find-libprovides| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/find-libprovides.1">find-libprovides</a>
+
+.. |find-libdeps| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/find-libdeps.1">find-libdeps</a>
+
+.. |gdb| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/gdb.1">gdb</a>
+
+.. |debug packages and debuginfod| raw:: html
+
+ <a target="blank" href="https://archlinux.org/news/debug-packages-and-debuginfod/">debug packages and debuginfod</a>
+
+.. |pkgbuild#install| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/PKGBUILD#install">PKGBUILD#install</a>
+
+.. |user identifier| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/User_identifier">user identifier</a>
+
+.. |group identifier| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Group_identifier">group identifier</a>
+
+.. |UID/ GID database| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/DeveloperWiki:UID_/_GID_Database">UID/ GID database</a>
+
+.. |systemd| raw:: html
+
+ <a target="blank" href="https://systemd.io/">systemd</a>
+
+.. |systemd-sysusers| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/systemd-sysusers.8">systemd-sysusers</a>
+
+.. |extended file attributes| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Extended_file_attributes#Linux">extended file attributes</a>
+
+.. |setuid| raw:: html
+
+ <a target="blank" href="https://en.wikipedia.org/wiki/Setuid">setuid</a>
+
+.. |chown| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/chown.1">chown</a>
+
+.. |systemd-tmpfiles| raw:: html
+
+ <a target="blank" href="https://man.archlinux.org/man/systemd-tmpfiles.8">systemd-tmpfiles</a>
+
+.. |php| raw:: html
+
+ <a target="blank" href="https://www.php.net/">PHP</a>
+
+.. |python| raw:: html
+
+ <a target="blank" href="https://www.python.org/">Python</a>
+
+.. |ruby| raw:: html
+
+ <a target="blank" href="https://www.ruby-lang.org/en/">Ruby</a>
+
+.. |c| raw:: html
+
+ <a target="blank" href="https://www.iso.org/standard/74528.html">C</a>
+
+.. |c++| raw:: html
+
+ <a target="blank" href="https://isocpp.org/">C++</a>
+
+.. |rust| raw:: html
+
+ <a target="blank" href="https://www.rust-lang.org/">Rust</a>
+
+.. |#archlinux| raw:: html
+
+ <a target="blank" href="ircs://irc.libera.chat/archlinux">#archlinux</a>
+
+.. |#archlinux-aur| raw:: html
+
+ <a target="blank" href="ircs://irc.libera.chat/archlinux-aur">#archlinux-aur</a>
+
+.. |libera.chat| raw:: html
+
+ <a target="blank" href="https://libera.chat/">libera.chat</a>
+
+.. |list of my packages| raw:: html
+
+ <a target="blank" href="https://archlinux.org/packages/?sort=&q=&maintainer=dvzrv&flagged=">list of my packages</a>
+
+.. |unofficial user repositories| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Unofficial_user_repositories">unofficial user repositories</a>
+
+.. |[realtime]| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Unofficial_user_repositories#realtime">[realtime]</a>
+
+.. |[pro-audio-legacy]| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Unofficial_user_repositories#pro-audio-legacy">[pro-audio-legacy]</a>
+
+.. |getting involved| raw:: html
+
+ <a target="blank" href="https://wiki.archlinux.org/title/Getting_involved">getting involved</a>
+