-
Notifications
You must be signed in to change notification settings - Fork 432
docs: Add example for installing AUR packages in ArchLinux images #4250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
abeb933
d5941f2
952f259
34716cc
1578352
cd8bb30
1ec1276
423b147
208d5b9
26488b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,205 @@ | ||
| --- | ||
| 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 `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). | ||
|
|
||
| ## Overview: | ||
|
|
||
| The approach involves using two `mkosi` hook scripts and a stub `build` script: | ||
|
|
||
| 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`: 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`: 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. | ||
|
|
||
| ### Why `nobody`? | ||
|
|
||
| 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`? | ||
|
|
||
| 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`: | ||
|
|
||
| ```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 | ||
|
|
||
| # AUR packages are installed via mkosi.postinst.chroot. | ||
| Packages= | ||
| base | ||
| linux | ||
| linux-firmware | ||
| ``` | ||
|
|
||
| ## `mkosi.prepare.chroot`: | ||
|
|
||
| ```sh | ||
| #!/usr/bin/env bash | ||
|
|
||
| set -eux | ||
|
|
||
| if [[ "$1" != "build" ]]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| # 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 | ||
|
|
||
| cat > /etc/pacman.d/mirrorlist << 'EOF' | ||
| Server = https://fastly.mirror.pkgbuild.com/$repo/os/$arch | ||
| EOF | ||
|
|
||
| pacman -Sy | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should also not be necessary, since packages have just been installed.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without these lines, I am also attaching logs of a failed build after removing these lines where the server failed to sync databases. |
||
|
|
||
| install -d /tmp/aurutils-build -o nobody | ||
| cd /tmp/aurutils-build | ||
| sudo -u nobody git clone https://aur.archlinux.org/aurutils.git | ||
| cd aurutils | ||
|
|
||
| pacman -S --needed --noconfirm \ | ||
| git pacutils curl perl perl-json-xs bash | ||
|
|
||
| sudo -u nobody \ | ||
| PKGDEST="/tmp" \ | ||
| PKGEXT=".pkg.tar" \ | ||
| makepkg --clean --cleanbuild --noconfirm | ||
|
|
||
| pacman -U --noconfirm /tmp/aurutils-*.pkg.tar | ||
|
|
||
| cd / | ||
|
|
||
| # Add any AUR packages you want to build here, | ||
| PACKAGES=( | ||
| neovim-git | ||
| ) | ||
|
|
||
| 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. | ||
| aur_deps=$(aur depends "${PACKAGES[@]}" -r | tsort) | ||
| echo "AUR build order: ${aur_deps}" | ||
|
|
||
| # Install official-repo dependencies upfront so makepkg does not need sudo. | ||
| 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" \ | ||
| makepkg --noconfirm --noprogressbar | ||
|
|
||
| popd | ||
| done | ||
| ``` | ||
|
|
||
| ## `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`: | ||
|
|
||
| ```sh | ||
| #!/usr/bin/env bash | ||
|
|
||
| set -eux | ||
|
|
||
| # 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 | ||
|
|
||
| cat > /etc/pacman.d/mirrorlist << 'EOF' | ||
| Server = https://fastly.mirror.pkgbuild.com/$repo/os/$arch | ||
| EOF | ||
|
|
||
| pacman -Sy | ||
|
|
||
| pacman -U --noconfirm $PACKAGEDIR/*.pkg.tar.zst | ||
| ``` | ||
|
|
||
| # 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 | ||
| ``` | ||
|
|
||
| # 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) | ||
Uh oh!
There was an error while loading. Please reload this page.