From abeb933b7f2f7712305c176c13f153b905d13d24 Mon Sep 17 00:00:00 2001 From: Esteban Puyana Date: Sun, 29 Mar 2026 16:14:53 -0400 Subject: [PATCH 1/5] docs: Add example for installing AUR packages in ArchLinux images Co-Authored By: Claude Sonnet 4.6 --- docs/building-aur-packages.md | 264 ++++++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 docs/building-aur-packages.md diff --git a/docs/building-aur-packages.md b/docs/building-aur-packages.md new file mode 100644 index 0000000000..8782d6c4ad --- /dev/null +++ b/docs/building-aur-packages.md @@ -0,0 +1,264 @@ +--- +title: Installing AUR Packages in Arch Linux Images +category: Tutorials +layout: default +SPDX-License-Identifier: LGPL-2.1-or-later +--- + +# Installing AUR Packages in Arch Linux Images: + +`mkosi` does not natively support installing packages from the [Arch User Repository +(AUR)](https://aur.archlinux.org/) since AUR packages must be built from source using `mkpkg` rather than +installed through `pacman`. This section describes how to install AUR packages at image build time using +[`aurutils`](https://aur.archlinux.org/packages/aurutils) and a local pacman repository. + +## Overview: + +The approach involes using three `mkosi` hook scripts that run in sequence: + +1. `mkosi.prepare.chroot`: Initialises the pacman keyring, uses `reflector` to fetch and rank mirrors, bootstraps `aurutils` from the AUR (since it is an AUR package itself and therefore cannot be listed in + the `BuildPackages=` section of an `mkosi.conf` file), and then sets up a local pacman repository backed by + `$PACKAGEDIR`. + +2. `mkosi.build.chroot`: Resolves the full AUR dependency graph, installs official-repo makedepends, fetches `PKGBUILD`s, builds packages as the unprivileged [nobody](https://wiki.ubuntu.com/nobody) user, and registers the results in the local repository inside `$PACKAGEDIR`. + +3. `mkosi.postinst.chroot`: Configures pacman in the final image to read from `$PACKAGEDIR` and installs all built AUR packages. + +`BuildSourcesEphemeral=yes` ensures that build tools (`base-devel`, `git`, etc.) installed via +`BuildPackages=` are present during the build phase but [are not included in the final image](/mkosi/resources/man/mkosi.1.md#build-section). `$PACKAGEDIR` is a mkosi-managed directory that persists between the build phase and the postinst phase. + +### Why `nobody`? + +Given that `makepkg` refuses to run as root as a safety measure, inside mkosi's build sandbox there is no persistent user database, so the existing `nobody` system user (`uid 65534`) is a convenient unprivileged identity that is always available. + +### Why `aur depends` and `tsort`? + +AUR packages can depend on other AUR packages. With `aur depends -r` emits the full +transitive dependency graph. `tsort` linearises the dependencies into a build order that guarantees each package is built after the packages it depends on. For neovim-git, the AUR package used in this example, this means any AUR dependencies are built and registered before neovim-git itself attempts to build against them. + +# Example installing `neovim-git`: + +## `mkosi.conf`: + +```sh +[Distribution] +Distribution=arch + +[Build] +BuildSourcesEphemeral=yes + +# Enables network connectivity while mkosi.build build scripts are invoked. +# Required to fetch AUR sources and dependencies. +WithNetwork=yes + +[Content] +# Build-time only tools. +BuildPackages= + base-devel + git + jq + reflector + +# AUR packages are installed via mkosi.postinst.chroot. +Packages= + base + linux + linux-firmware + systemd + bash + reflector +``` + +## `mkosi.prepare.chroot`: + +```sh +#!/usr/bin/env bash + +set -eux + +if [[ "${1}" != "build" ]]; then + exit 0 +fi + +# Pacman initialization operations: +pacman-key --init +pacman-key --populate archlinux + +reflector --latest 10 --sort rate --save /etc/pacman.d/mirrorlist + +pacman -Sy + +# Bootstrap aurutils from AUR, with user nobody into /tmp, then install with pacman. +install -d /tmp/aurutils-build -o nobody + +cd /tmp/aurutils-build +sudo -u nobody git clone https://aur.archlinux.org/aurutils.git +cd aurutils + +( source ./PKGBUILD + pacman -S --needed --noconfirm \ + "${makedepends[@]}" "${depends[@]}" +) + +sudo -u nobody PKGDEST="/tmp" PKGEXT=".pkg.tar" makepkg --clean --cleanbuild --noconfirm +pacman -U --noconfirm /tmp/aurutils-*.pkg.tar + +cd / + +# Create the local repo directory owned by nobody. +install -d /aur -o nobody + +# Initialise an empty pacman database for the [aur] repo. +sudo -u nobody tar -ca -f /aur/aur.db.tar.xz -T /dev/null +sudo -u nobody ln -sf /aur/aur.db.tar.xz /aur/aur.db + +mkdir -p /etc/pacman.d + +# Sentinel file so /etc/pacman.d is never empty (pacman requires Include targets exist). +cat > /etc/pacman.d/dummy.conf << 'EOF' +# This file exists so /etc/pacman.d is never an empty directory. +EOF + +# Drop the [aur] repo fragment. +cat > /etc/pacman.d/aur.conf << 'EOF' +[aur] +SigLevel = Optional TrustAll +Server = file:///aur +EOF + +# Add the Include directive to pacman.conf if not already present. +if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then + echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf +fi + +# Sync so pacman knows about [aur] before mkosi.build.chroot runs. +pacman -Sy +``` + +## `mkosi.build.chroot`: + +```sh +# mkosi.build.chroot +# +# This runs after mkosi.prepare.chroot "build" phase. +# Still inside the BUILD overlay, so base-devel, aurutils, git, are all available here. + +set -eux + +PACKAGES=( + neovim-git + # foo + # bar + # and any other AUR packages you want to build here +) + +# Set up the local pacman repo inside $PACKAGEDIR (not /aur) to pass +# built packages from the build script to postinst. + +install -d "$PACKAGEDIR" -o nobody + +sudo -u nobody tar -ca -f "$PACKAGEDIR/aur.db.tar.xz" -T /dev/null +sudo -u nobody ln -sf "$PACKAGEDIR/aur.db.tar.xz" "$PACKAGEDIR/aur.db" + +# Point pacman at $PACKAGEDIR as the [aur] repo. +mkdir -p /etc/pacman.d +cat > /etc/pacman.d/aur.conf << EOF +[aur] +SigLevel = Optional TrustAll +Server = file://$PACKAGEDIR +EOF + +if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then + echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf +fi + +pacman -Sy + +install -d /tmp/aurbuild -o nobody +install -d /var/tmp/aurutils-65534 -o nobody +cd /tmp/aurbuild + +# Resolve full AUR dependency graph and linearise into build order. +aur_deps=$(aur depends "${PACKAGES[@]}" -r | tsort) +echo "AUR build order: ${aur_deps}" + +# Install official repo dependencies upfront. +pacman_deps=$(aur depends "${PACKAGES[@]}" --json --all \ + | jq -r '.[] | select(.ID == null) | .Name') + +if [[ -n "${pacman_deps}" ]]; then + # shellcheck disable=SC2086 + pacman -S --needed --noconfirm ${pacman_deps} +fi + +# shellcheck disable=SC2086 +aur fetch ${aur_deps[@]} +chown -R nobody:nobody /tmp/aurbuild + +for pkg in ${aur_deps[@]}; do + pushd "${pkg}" + + sudo -u nobody \ + BUILDDIR="/tmp/aurbuild" \ + SRCDEST="/tmp/aurbuild" \ + PKGDEST="$PACKAGEDIR" \ + aur build --no-sync + + sudo -u nobody repo-add "$PACKAGEDIR/aur.db.tar.xz" "$PACKAGEDIR/${pkg}"-*.pkg.tar* + + popd +done + +pacman -Sy +``` + +## `mkosi.postinst.chroot`: + +```sh +#!/usr/bin/env bash + +# Installs built AUR packages into the final image. + +set -eux + +mkdir -p /etc/pacman.d + +cat > /etc/pacman.d/aur.conf << EOF +[aur] +SigLevel = Optional TrustAll +Server = file://$PACKAGEDIR +EOF + +# The final image context has no mirrors configured by default. +# Fetch and rank the 10 fastest mirrors. +reflector --latest 10 --sort rate --save /etc/pacman.d/mirrorlist + +if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then + echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf +fi + +pacman-key --init +pacman-key --populate archlinux +pacman -Sy + +# Install every package registered in the [aur] repo. +pacman -S --noconfirm $(pacman -Sql aur) +``` + +# Building and Executing the Scripts: + +Once you have confiuged the scripts to contain the desired AUR packages, the image can be built: + +```sh +chmod +x mkosi.prepare.chroot mkosi.build.chroot mkosi.postinst.chroot +mkosi +``` + +Then boot the resulting image and verify that the package was correctly installed: + +```sh +mkosi vm + +pacman -Q neovim-git +nvim --version +``` From d5941f2b6572690c55e22f5f32de795be5a5feef Mon Sep 17 00:00:00 2001 From: Esteban Puyana Date: Sun, 29 Mar 2026 16:39:16 -0400 Subject: [PATCH 2/5] chore: fixed typo in documentation file --- docs/building-aur-packages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/building-aur-packages.md b/docs/building-aur-packages.md index 8782d6c4ad..9bab999a9c 100644 --- a/docs/building-aur-packages.md +++ b/docs/building-aur-packages.md @@ -14,7 +14,7 @@ installed through `pacman`. This section describes how to install AUR packages a ## Overview: -The approach involes using three `mkosi` hook scripts that run in sequence: +The approach involves using three `mkosi` hook scripts that run in sequence: 1. `mkosi.prepare.chroot`: Initialises the pacman keyring, uses `reflector` to fetch and rank mirrors, bootstraps `aurutils` from the AUR (since it is an AUR package itself and therefore cannot be listed in the `BuildPackages=` section of an `mkosi.conf` file), and then sets up a local pacman repository backed by From 34716cc8a655f12ea5e9f9899202afd360d37105 Mon Sep 17 00:00:00 2001 From: Esteban Puyana Date: Mon, 30 Mar 2026 10:28:04 -0400 Subject: [PATCH 3/5] docs: starting changes to AUR package guide as requested in PR --- docs/building-aur-packages.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/building-aur-packages.md b/docs/building-aur-packages.md index 9bab999a9c..d1683ea1e7 100644 --- a/docs/building-aur-packages.md +++ b/docs/building-aur-packages.md @@ -8,7 +8,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later # Installing AUR Packages in Arch Linux Images: `mkosi` does not natively support installing packages from the [Arch User Repository -(AUR)](https://aur.archlinux.org/) since AUR packages must be built from source using `mkpkg` rather than +(AUR)](https://aur.archlinux.org/) since AUR packages must be built from source using `makepkg` rather than installed through `pacman`. This section describes how to install AUR packages at image build time using [`aurutils`](https://aur.archlinux.org/packages/aurutils) and a local pacman repository. @@ -29,7 +29,7 @@ The approach involves using three `mkosi` hook scripts that run in sequence: ### Why `nobody`? -Given that `makepkg` refuses to run as root as a safety measure, inside mkosi's build sandbox there is no persistent user database, so the existing `nobody` system user (`uid 65534`) is a convenient unprivileged identity that is always available. +Since `makepkg` checks `EUID` (Effective User ID) rather than strictly requiring non-root, the `nobody` user (`uid` 65534) works as a convenient unprivileged identity, as it is always available in the build sandbox without requiring a persistent user database. ### Why `aur depends` and `tsort`? @@ -64,8 +64,6 @@ Packages= base linux linux-firmware - systemd - bash reflector ``` From 1578352370c3cae60138d6c65cc8040696ec3ac2 Mon Sep 17 00:00:00 2001 From: Esteban Puyana Date: Mon, 30 Mar 2026 22:18:49 -0400 Subject: [PATCH 4/5] Updated documentation file on adding AUR packages for ArchLinux images Minor syntax changes; removed reflector and opted for default mkosi mirror image; expanded section on nobody user to include explenation of EUID; removed systemd and bash as BuildPackage dependecies as they are included in base. --- docs/building-aur-packages.md | 94 ++++++++++++++--------------------- 1 file changed, 38 insertions(+), 56 deletions(-) diff --git a/docs/building-aur-packages.md b/docs/building-aur-packages.md index d1683ea1e7..9d22b7edc5 100644 --- a/docs/building-aur-packages.md +++ b/docs/building-aur-packages.md @@ -8,7 +8,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later # Installing AUR Packages in Arch Linux Images: `mkosi` does not natively support installing packages from the [Arch User Repository -(AUR)](https://aur.archlinux.org/) since AUR packages must be built from source using `makepkg` rather than +(AUR)](https://aur.archlinux.org/), since AUR packages must be built from source using `makepkg` rather than installed through `pacman`. This section describes how to install AUR packages at image build time using [`aurutils`](https://aur.archlinux.org/packages/aurutils) and a local pacman repository. @@ -16,7 +16,7 @@ installed through `pacman`. This section describes how to install AUR packages a The approach involves using three `mkosi` hook scripts that run in sequence: -1. `mkosi.prepare.chroot`: Initialises the pacman keyring, uses `reflector` to fetch and rank mirrors, bootstraps `aurutils` from the AUR (since it is an AUR package itself and therefore cannot be listed in +1. `mkosi.prepare.chroot`: Initialises the pacman keyring, bootstraps `aurutils` from the AUR (since it is an AUR package itself and therefore cannot be listed in the `BuildPackages=` section of an `mkosi.conf` file), and then sets up a local pacman repository backed by `$PACKAGEDIR`. @@ -33,7 +33,7 @@ Since `makepkg` checks `EUID` (Effective User ID) rather than strictly requiring ### Why `aur depends` and `tsort`? -AUR packages can depend on other AUR packages. With `aur depends -r` emits the full +AUR packages can depend on other AUR packages. Using `aur depends -r` emits the full transitive dependency graph. `tsort` linearises the dependencies into a build order that guarantees each package is built after the packages it depends on. For neovim-git, the AUR package used in this example, this means any AUR dependencies are built and registered before neovim-git itself attempts to build against them. # Example installing `neovim-git`: @@ -57,14 +57,12 @@ BuildPackages= base-devel git jq - reflector # AUR packages are installed via mkosi.postinst.chroot. Packages= base linux linux-firmware - reflector ``` ## `mkosi.prepare.chroot`: @@ -82,7 +80,9 @@ fi pacman-key --init pacman-key --populate archlinux -reflector --latest 10 --sort rate --save /etc/pacman.d/mirrorlist +cat > /etc/pacman.d/mirrorlist << 'EOF' +Server = https://fastly.mirror.pkgbuild.com/$repo/os/$arch +EOF pacman -Sy @@ -93,51 +93,43 @@ cd /tmp/aurutils-build sudo -u nobody git clone https://aur.archlinux.org/aurutils.git cd aurutils -( source ./PKGBUILD - pacman -S --needed --noconfirm \ - "${makedepends[@]}" "${depends[@]}" -) +pacman -S --needed --noconfirm \ + git pacutils curl perl perl-json-xs bash + +sudo -u nobody \ + PKGDEST="/tmp" \ + PKGEXT=".pkg.tar" \ + makepkg --clean --cleanbuild --noconfirm -sudo -u nobody PKGDEST="/tmp" PKGEXT=".pkg.tar" makepkg --clean --cleanbuild --noconfirm pacman -U --noconfirm /tmp/aurutils-*.pkg.tar cd / -# Create the local repo directory owned by nobody. -install -d /aur -o nobody - -# Initialise an empty pacman database for the [aur] repo. -sudo -u nobody tar -ca -f /aur/aur.db.tar.xz -T /dev/null -sudo -u nobody ln -sf /aur/aur.db.tar.xz /aur/aur.db +# Initialize the local pacman repo inside $PACKAGEDIR. +install -d "$PACKAGEDIR" -o nobody +sudo -u nobody tar -ca -f "$PACKAGEDIR/aur.db.tar.xz" -T /dev/null +sudo -u nobody ln -sf "$PACKAGEDIR/aur.db.tar.xz" "$PACKAGEDIR/aur.db" mkdir -p /etc/pacman.d -# Sentinel file so /etc/pacman.d is never empty (pacman requires Include targets exist). -cat > /etc/pacman.d/dummy.conf << 'EOF' -# This file exists so /etc/pacman.d is never an empty directory. -EOF - -# Drop the [aur] repo fragment. -cat > /etc/pacman.d/aur.conf << 'EOF' +cat > /etc/pacman.d/aur.conf << EOF [aur] SigLevel = Optional TrustAll -Server = file:///aur +Server = file://$PACKAGEDIR EOF -# Add the Include directive to pacman.conf if not already present. if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf fi -# Sync so pacman knows about [aur] before mkosi.build.chroot runs. pacman -Sy ``` ## `mkosi.build.chroot`: ```sh -# mkosi.build.chroot -# +#!/usr/bin/env bash + # This runs after mkosi.prepare.chroot "build" phase. # Still inside the BUILD overlay, so base-devel, aurutils, git, are all available here. @@ -150,28 +142,7 @@ PACKAGES=( # and any other AUR packages you want to build here ) -# Set up the local pacman repo inside $PACKAGEDIR (not /aur) to pass -# built packages from the build script to postinst. - -install -d "$PACKAGEDIR" -o nobody - -sudo -u nobody tar -ca -f "$PACKAGEDIR/aur.db.tar.xz" -T /dev/null -sudo -u nobody ln -sf "$PACKAGEDIR/aur.db.tar.xz" "$PACKAGEDIR/aur.db" - -# Point pacman at $PACKAGEDIR as the [aur] repo. -mkdir -p /etc/pacman.d -cat > /etc/pacman.d/aur.conf << EOF -[aur] -SigLevel = Optional TrustAll -Server = file://$PACKAGEDIR -EOF - -if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then - echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf -fi - -pacman -Sy - +# /var/tmp/aurutils-65534 is aurutils' own working directory (65534 = nobody uid). install -d /tmp/aurbuild -o nobody install -d /var/tmp/aurutils-65534 -o nobody cd /tmp/aurbuild @@ -180,7 +151,7 @@ cd /tmp/aurbuild aur_deps=$(aur depends "${PACKAGES[@]}" -r | tsort) echo "AUR build order: ${aur_deps}" -# Install official repo dependencies upfront. +# Install official-repo dependencies upfront so makepkg does not need sudo. pacman_deps=$(aur depends "${PACKAGES[@]}" --json --all \ | jq -r '.[] | select(.ID == null) | .Name') @@ -202,7 +173,8 @@ for pkg in ${aur_deps[@]}; do PKGDEST="$PACKAGEDIR" \ aur build --no-sync - sudo -u nobody repo-add "$PACKAGEDIR/aur.db.tar.xz" "$PACKAGEDIR/${pkg}"-*.pkg.tar* + sudo -u nobody repo-add "$PACKAGEDIR/aur.db.tar.xz" \ + "$PACKAGEDIR/${pkg}"-*.pkg.tar* popd done @@ -227,9 +199,9 @@ SigLevel = Optional TrustAll Server = file://$PACKAGEDIR EOF -# The final image context has no mirrors configured by default. -# Fetch and rank the 10 fastest mirrors. -reflector --latest 10 --sort rate --save /etc/pacman.d/mirrorlist +cat > /etc/pacman.d/mirrorlist << 'EOF' +Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch +EOF if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf @@ -237,6 +209,11 @@ fi pacman-key --init pacman-key --populate archlinux + +cat > /etc/pacman.d/mirrorlist << 'EOF' +Server = https://fastly.mirror.pkgbuild.com/$repo/os/$arch +EOF + pacman -Sy # Install every package registered in the [aur] repo. @@ -260,3 +237,8 @@ mkosi vm pacman -Q neovim-git nvim --version ``` + +# Miscellaneous Notes: + +This example assumes the host is running Arch Linux or an Arch-based distribution. Building Arch images from +non-Arch hosts is possible using [`ToolsTree=arch`](/mkosi/resources/man/mkosi.1.md#build-section) From 423b147bec13fe4cd61e2ecea56ea590f0a4c020 Mon Sep 17 00:00:00 2001 From: Esteban Puyana Date: Sun, 12 Apr 2026 12:55:13 -0400 Subject: [PATCH 5/5] chore: updating building-aur-packages.md to relfect changes requested in PR review --- docs/building-aur-packages.md | 101 +++++++++++----------------------- 1 file changed, 31 insertions(+), 70 deletions(-) diff --git a/docs/building-aur-packages.md b/docs/building-aur-packages.md index 9d22b7edc5..fa9953855a 100644 --- a/docs/building-aur-packages.md +++ b/docs/building-aur-packages.md @@ -10,19 +10,18 @@ SPDX-License-Identifier: LGPL-2.1-or-later `mkosi` does not natively support installing packages from the [Arch User Repository (AUR)](https://aur.archlinux.org/), since AUR packages must be built from source using `makepkg` rather than installed through `pacman`. This section describes how to install AUR packages at image build time using -[`aurutils`](https://aur.archlinux.org/packages/aurutils) and a local pacman repository. +[`aurutils`](https://aur.archlinux.org/packages/aurutils). ## Overview: -The approach involves using three `mkosi` hook scripts that run in sequence: +The approach involves using two `mkosi` hook scripts and a stub `build` script: -1. `mkosi.prepare.chroot`: Initialises the pacman keyring, bootstraps `aurutils` from the AUR (since it is an AUR package itself and therefore cannot be listed in - the `BuildPackages=` section of an `mkosi.conf` file), and then sets up a local pacman repository backed by - `$PACKAGEDIR`. +1. `mkosi.prepare.chroot`: Bootstraps `aurutils` from AUR, resolves its dependency graph, builds all + requested packages as the unprivileged [`nobody`](https://wiki.ubuntu.com/nobody) user, and places the resulting packages in `$PACKAGEDIR`. -2. `mkosi.build.chroot`: Resolves the full AUR dependency graph, installs official-repo makedepends, fetches `PKGBUILD`s, builds packages as the unprivileged [nobody](https://wiki.ubuntu.com/nobody) user, and registers the results in the local repository inside `$PACKAGEDIR`. +2. `mkosi.build.chroot`: A stub script that exists solely to trigger mkosi's build phase, which causes mkosi.prepare.chroot to be called with the build argument. -3. `mkosi.postinst.chroot`: Configures pacman in the final image to read from `$PACKAGEDIR` and installs all built AUR packages. +3. `mkosi.postinst.chroot`: Installs the built packages from `$PACKAGEDIR` into the final image using `pacman -U`. `BuildSourcesEphemeral=yes` ensures that build tools (`base-devel`, `git`, etc.) installed via `BuildPackages=` are present during the build phase but [are not included in the final image](/mkosi/resources/man/mkosi.1.md#build-section). `$PACKAGEDIR` is a mkosi-managed directory that persists between the build phase and the postinst phase. @@ -36,6 +35,11 @@ Since `makepkg` checks `EUID` (Effective User ID) rather than strictly requiring AUR packages can depend on other AUR packages. Using `aur depends -r` emits the full transitive dependency graph. `tsort` linearises the dependencies into a build order that guarantees each package is built after the packages it depends on. For neovim-git, the AUR package used in this example, this means any AUR dependencies are built and registered before neovim-git itself attempts to build against them. +### Why `aurutils` is bootstrapped manually? +`aurutils` cannot be listed in `BuildPackages=` because it is itself an AUR package. Its dependencies are +installed explicitly as root before `makepkg` runs, since `makepkg --syncdeps` calls `pacman` via `sudo` +internally, which `nobody` does not have access to in the build sandbox. + # Example installing `neovim-git`: ## `mkosi.conf`: @@ -72,11 +76,14 @@ Packages= set -eux -if [[ "${1}" != "build" ]]; then +if [[ "$1" != "build" ]]; then exit 0 fi -# Pacman initialization operations: +# The prepare script runs in a fresh build overlay where the keyring has +# not been initialised and no package databases exist. Both steps are +# required, omitting them causes "keyring is not writable" and +# "database file does not exist" errors respectively. pacman-key --init pacman-key --populate archlinux @@ -86,9 +93,7 @@ EOF pacman -Sy -# Bootstrap aurutils from AUR, with user nobody into /tmp, then install with pacman. install -d /tmp/aurutils-build -o nobody - cd /tmp/aurutils-build sudo -u nobody git clone https://aur.archlinux.org/aurutils.git cd aurutils @@ -105,46 +110,14 @@ pacman -U --noconfirm /tmp/aurutils-*.pkg.tar cd / -# Initialize the local pacman repo inside $PACKAGEDIR. -install -d "$PACKAGEDIR" -o nobody -sudo -u nobody tar -ca -f "$PACKAGEDIR/aur.db.tar.xz" -T /dev/null -sudo -u nobody ln -sf "$PACKAGEDIR/aur.db.tar.xz" "$PACKAGEDIR/aur.db" - -mkdir -p /etc/pacman.d - -cat > /etc/pacman.d/aur.conf << EOF -[aur] -SigLevel = Optional TrustAll -Server = file://$PACKAGEDIR -EOF - -if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then - echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf -fi - -pacman -Sy -``` - -## `mkosi.build.chroot`: - -```sh -#!/usr/bin/env bash - -# This runs after mkosi.prepare.chroot "build" phase. -# Still inside the BUILD overlay, so base-devel, aurutils, git, are all available here. - -set -eux - +# Add any AUR packages you want to build here, PACKAGES=( neovim-git - # foo - # bar - # and any other AUR packages you want to build here ) -# /var/tmp/aurutils-65534 is aurutils' own working directory (65534 = nobody uid). install -d /tmp/aurbuild -o nobody install -d /var/tmp/aurutils-65534 -o nobody +install -d "$PACKAGEDIR" -o nobody cd /tmp/aurbuild # Resolve full AUR dependency graph and linearise into build order. @@ -171,15 +144,19 @@ for pkg in ${aur_deps[@]}; do BUILDDIR="/tmp/aurbuild" \ SRCDEST="/tmp/aurbuild" \ PKGDEST="$PACKAGEDIR" \ - aur build --no-sync - - sudo -u nobody repo-add "$PACKAGEDIR/aur.db.tar.xz" \ - "$PACKAGEDIR/${pkg}"-*.pkg.tar* + makepkg --noconfirm --noprogressbar popd done +``` -pacman -Sy +## `mkosi.build.chroot`: + +```sh +#!/usr/bin/env bash +# This script exists solely to trigger mkosi's build phase, which causes +# mkosi.prepare.chroot to be called with the "build" argument. All actual +# AUR package building happens in mkosi.prepare.chroot. ``` ## `mkosi.postinst.chroot`: @@ -187,26 +164,11 @@ pacman -Sy ```sh #!/usr/bin/env bash -# Installs built AUR packages into the final image. - set -eux -mkdir -p /etc/pacman.d - -cat > /etc/pacman.d/aur.conf << EOF -[aur] -SigLevel = Optional TrustAll -Server = file://$PACKAGEDIR -EOF - -cat > /etc/pacman.d/mirrorlist << 'EOF' -Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch -EOF - -if ! grep -q 'Include = /etc/pacman.d/\*.conf' /etc/pacman.conf; then - echo -e '\nInclude = /etc/pacman.d/*.conf' >> /etc/pacman.conf -fi - +# The final image context also starts with no keyring, mirrorlist, or +# synced databases. pacman -U needs all three to verify package signatures +# and resolve official-repo dependencies of the AUR packages. pacman-key --init pacman-key --populate archlinux @@ -216,8 +178,7 @@ EOF pacman -Sy -# Install every package registered in the [aur] repo. -pacman -S --noconfirm $(pacman -Sql aur) +pacman -U --noconfirm $PACKAGEDIR/*.pkg.tar.zst ``` # Building and Executing the Scripts: