Setting up AnotherAURHelper with LXC

It is recommended to use AnotherAURHelper with a container as a safety net due to the fact that makechrootpkg directly sources/parses PKGBUILDs.

The following assumes you already have LXC installed. If not, follow the ArchWiki until you can get an arbitrary container up and running.

Note

The following code blocks will have different prefixes. > is used to specify commands run on an ArchLinux installation, and $ is used to specify commands run inside of the LXC container.

Privileged Containers

AnotherAURHelper requires to be run in a privileged container because it uses a chroot. If your LXC is already configured for unprivileged containers, you can create a privileged container by commenting out the config for an unprivileged container and creating a container, and uncommenting after the container has been created to allow future containers to be created as unprivileged.

# /etc/lxc/default.conf
#lxc.idmap = u 0 100000 65536
#lxc.idmap = g 0 100000 65536

LXC Container Setup

Create the container like the following on your host system.

> sudo lxc-create -n aur_helper -t download
Downloading the image index

---
DIST             RELEASE     ARCH   VARIANT  BUILD
---
...
archlinux        current     amd64  default  20250303_05:33
archlinux        current     arm64  default  20250303_05:49
...
---

Distribution:
> archlinux
Release:
> current
Architecture:
> amd64

The cached copy has expired, re-downloading...
Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
You just created an Archlinux  x86_64 (20250303_05:33) container.

Start the container.

> sudo lxc-start -n aur_helper -s lxc.apparmor.allow_nesting=1 -s lxc.apparmor.profile=generated

Attach to a shell inside the container.

> sudo lxc-attach -n aur_helper

Getting Required Packages

Update your mirror-list in the container and update.

$ pacman -Syu

base-devel, devtools, python-toml, ccache, and sqlite is required.

$ pacman -S base-devel devtools python-toml ccache sqlite

You may need to grab an editor like vim, emacs, or nano.

$ pacman -S vim emacs nano

If your filesystem is using btrfs, you will need to install btrfs-progs.

$ pacman -S btrfs-progs

Setting up SSH for the Container

This is pretty straightforward, but for those unfamiliar with ssh, here's a quick setup guide.

First, install openssh.

$ pacman -S openssh

Enable and start sshd.

$ systemctl enable --now sshd

After setting up the user in the following section, you can use ssh to log in to the user.

You can fetch the local ip address of the running container with the following.

> sudo lxc-ls -f
NAME       STATE   AUTOSTART GROUPS IPV4    IPV6    UNPRIVILEGED
aur_helper RUNNING 0         -      omitted omitted false

Just use the local ip address in the IPV4 column and you can ssh into your user like so.

> ssh build@10.0.3.1

Creating the build user

A build user is to be created with sudo privileges that will be used to run the builds.

First, create the user.

$ useradd -m -s /usr/bin/bash build

Then add sudo privileges for the build user.

$ EDITOR=nano visudo

Add the following line for sudo privileges for build.

build ALL=(ALL:ALL) NOPASSWD: ALL

If you prefer to have build use a password for sudo privielges, then use the following instead.

build ALL=(ALL:ALL) ALL

And set build's password.

$ passwd build

Open a shell as build to check if it works.

$ su - build
$ sudo ls -a

At this point you should be able to ssh into build.

Creating the CHROOT

Note

Continue the following steps as the build user, not as root.

Use /usr/bin/mkarchroot to create a CHROOT at /home/build/chroot/root.

$ mkdir /home/build/chroot
$ mkarchroot /home/build/chroot/root base base-devel cmake ninja

Warning

Do NOT preinstall ccache or sccache in the CHROOT as it will be handled by AnotherAURHelper.

Note

From now on, you must refer to the CHROOT as /home/build/chroot when handling it in AnotherAURHelper, even if the actual chroot is inside of /home/build/chroot/root.

Note

The default LXC ArchLinux container has /etc/locale.conf set to C.UTF-8. You may have to change locale settings as in the installation guide on the ArchWiki.

Note

You are able to run commands in the CHROOT:

$ arch-nspawn /home/build/chroot/root pacman -S cmake

You may do this to also set proper locale information in the CHROOT.

You may want to uncomment some lines in /home/build/chroot/root/etc/pacman.conf to allow fetching multilib packages.

# pacman.conf
...
[multilib]
Include = /etc/pacman.d/mirrorlist
...

When the CHROOT is used to build packages by AnotherAURHelper, it should automatically use the same mirrorlist as the one used by the LXC container.

Set up GnuPG for Signature Verifcation and Package Signing

Checking GnuPG

Create a directory at a location of your choosing, ideally inside of /home/build/.

$ mkdir /home/build/checking_gpg
$ chmod 700 /home/build/checking_gpg
$ GNUPGHOME=/home/build/checking_gpg gpg -k

Whenever a build fails due to missing gpg public keys, the key can be added to this directory. Usually there should be a key file inside of the AUR pkg's directory, but otherwise the fingerprint can be used to fetch it directly.

# Load key from file
$ GNUPGHOME=/home/build/checking_gpg gpg --import < the_pub_key_file.pub
# Fetch key via fingerprint from a keyserver
$ GNUPGHOME=/home/build/checking_gpg gpg --recv-keys A_DEV_KEYS_FINGERPRINT

Signing GnuPG

A GnuPG public/private key pair will need to be generated. Only keys with signature creation is necessary, so generate accordingly. Like the previous GnuPG directory, this can be placed in /home/build/.

Note

If you encounter errors, try using --pinentry-mode loopback as a flag to pass to gpg. Otherwise, run the shell inside of a tmux session. This may occur if you are accessing the build user through an attached shell instead of ssh.

Also, be prepared to set up a password for this key.

Warning

Write the password down somewhere so you don't forget it! If you ever lose this password, you will need to revoke the old key, re-generate a new key, delete all package signatures, and re-sign all packages and the package database. You can do so by following instructions here.

Note

It may be beneficial to use a long password for this key instead of a short memorable one, as a malicious PKGBUILD might attempt to access it if the PKGBUILD hasn't been properly vetted first.

Follow the following to generate a GnuPG key for signatures only.

$ mkdir /home/build/signing_gpg
$ chmod 700 /home/build/signing_gpg
$ GNUPGHOME=/home/build/signing_gpg gpg --pinentry-mode loopback --full-gen-key
gpg (GnuPG) 2.4.7; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: keybox '/home/build/signing_gpg/pubring.kbx' created
Please select what kind of key you want:
   (1) RSA and RSA
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (9) ECC (sign and encrypt) *default*
  (10) ECC (sign only)
  (14) Existing key from card
Your selection?
$ 10
Please select which elliptic curve you want:
(1) Curve 25519 *default*
(4) NIST P-384
(6) Brainpool P-256
Your selection?
$ 1
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
$ 0
Key does not expire at all
Is this correct? (y/N)
$ y

GnuPG needs to construct a user ID to identify your key.

Real name:
$ My Name (AUR Helper Signing Key)
Email address:
$ my_email@example.com
Comment:
$ Key for AnotherAURHelper
You selected this USER-ID:
    "My Name (AUR Helper Signing Key) (Key for AnotherAURHelper) <my_email@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
$ O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
Enter passphrase:
$ ***********
gpg: /home/build/signing_gpg/trustdb.gpg: trustdb created
gpg: directory '/home/build/signing_gpg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/build/signing_gpg/openpgp-revocs.d/BFD86E817FA4B097A8636507A4FDFD431A0D481B.rev'
public and secret key created and signed.
pub   ed25519 2025-03-04 [SC]
      BFD86E817FA4B097A8636507A4FDFD431A0D481B
uid                      My Name (AUR Helper Signing Key) (Key for AnotherAURHelper) <my_email@example.com>

Verify you inputed the password correctly:

$ echo test_file > test_file
$ GNUPGHOME=/home/build/signing_gpg gpg --pinentry-mode loopback --detach-sign test_file
Enter passphrase:
$ ***********
$ GNUPGHOME=/home/build/signing_gpg gpg --verify test_file.sig
gpg: assuming signed data in 'test_file'
gpg: Signature made Tue Mar  4 03:59:43 2025 UTC
gpg:                using EDDSA key BFD86E817FA4B097A8636507A4FDFD431A0D481B
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: Good signature from "My Name (AUR Helper Signing Key) (Key for AnotherAURHelper) <my_email@example.com>" [ultimate]
# cleanup
$ rm test_file test_file.sig

Set up Output Dir and Configuration

Create an output directory for your built packages.

$ mkdir /home/build/aur_pkgs

Set up a /home/build/config.toml file with config for AnotherAURHelper.

Note

The config.toml file can be named anything.

Refer to the example_config.toml file inside AnotherAURHelper's repo as a reference.
At this point, we will clone AnotherAURHelper.

$ git clone https://github.com/Stephen-Seo/AnotherAURHelper.git

Your config should look like the following:

########## MANDATORY VARIABLES
chroot = "/home/build/chroot"
# Location to place built packages.
pkg_out_dir = "/home/build/aur_pkgs"
# It is recommended to put the repo file in the "pkg_out_dir".
# If the tar file doesn't already exist, it will be automatically created.
repo = "/home/build/aur_pkgs/MyRepo.db.tar"
# Location to clone packages from AUR.
clones_dir = "/home/build/aur"
gpg_dir = "/home/build/checking_gpg"
logs_dir = "/home/build/logs"
signing_gpg_dir = "/home/build/signing_gpg"
signing_gpg_key_fp = "BFD86E817FA4B097A8636507A4FDFD431A0D481B"
editor = "/usr/bin/nano"
# if true, all logs are prepended with current time in UTC
is_timed = true
# if true, all output build logs are prepended with current time in UTC
is_log_timed = true
# Default log_limit is 1 GiB
log_limit = 1073741824
# If true, then make the build fail if the limit is reached
error_on_limit = true
# If true, timestamps are in localtime. If false, timestamps are UTC.
datetime_in_local_time = true
# If true, all builds will be done in a tmpfs. Recommended to have a lot of RAM and/or swap.
tmpfs = false
# If true, only packages to be built will be printed when USR1 is signaled.
print_state_info_only_building_sigusr1 = true
# The path to the persistent state.
persistent_state_db = "/home/build/aur_helper_state.db"
########## END OF MANDATORY VARIABLES

Note

The repo = ... option determines the name of the repository. If you want to name it "MyCoolRepo", then it should be set as repo = "/home/build/aur_pkgs/MyCoolRepo.db.tar".

Note

The signing_gpg_key_fp = ... option ensures the correct signing key is used. You can use GNUPGHOME=/home/build/signing_gpg gpg -K to get your signing key's fingerprint to put in here.

Note

The persistent_state_db = ... option ensures that the per-package-option hash_compare_PKGBUILD doesn't skip a PKGBUILD that hasn't been explicitly trusted. Also note this is a fairly new feature that may still be only in the dev branch of AnotherAURHelper's repository.

Create some necessary directories.

$ mkdir -p aur_pkgs
$ mkdir -p aur
$ mkdir -p logs

Create some necessary symlinks based on the previously set repo = ....

$ ln -s MyRepo.db.tar /home/build/aur_pkgs/MyRepo.db
$ ln -s MyRepo.files.tar /home/build/aur_pkgs/MyRepo.files

Here is a few packages you can add to your config.toml.

[[entry]]
name = "stdman"

[[entry]]
name = "cpufetch-git"

Registering the Repo on other Arch systems

Warning

Some commands/config should be used on in your LXC container and some on a different ArchLinux system that will install the packages built by AnotherAURHelper. Thus, be sure you are on the right system before inputting commands as it may get confusing.

The following assumes that the AUR repo's name is MyRepo as indicated in the previous config.

Add the following to your /etc/pacman.conf on an ArchLinux system that will install the built AUR packages you build.

[MyRepo]
SigLevel = Required TrustedOnly
Server = file:///home/user/aur_pkgs

Note

This config assumes use of sshfs or rsync.

Note

It is possible to use nginx (or others) to host the directory to use as a repo accessible over http/https. This is a little more involved but is possible. Accessing such on other systems may set the Server = ... line in the /etc/pacman.conf to a url like Server = https://example.com/aur_pkgs.

We're not done yet, as the other ArchLinux system needs to get the public key of the AUR Helper signing key to verify the packages built and signed by AnotherAURHelper.

Export the public key of your GnuPG signing key from your LXC instance.

$ GNUPGHOME=/home/build/signing_gpg gpg --export > signing_key.pub

Use scp, sftp, or sshfs to get this public key out of the container. Use pacman-key on the other ArchLinux system to import and locally sign the public key to trust it.

> sudo pacman-key -a signing_key.pub

Check that the imported key is the only key listed when querying for it.

> sudo pacman-key --finger 'AUR Helper Signing Key'
pub   ed25519 2025-03-04 [SC]
      BFD8 6E81 7FA4 B097 A863  6507 A4FD FD43 1A0D 481B
uid           [ unknown] My Name (AUR Helper Signing Key) (Key for AnotherAURHelper) <my_email@example.com>

If there is only one key listed, then you can use the AUR Helper Signing Key string to specify the correct key to sign. (Signing another key in GnuPG means that you trust it.) If more than one key is listed, you will have to adjust the string passed to pacman-key --finger ... until only the key you want to sign is shown.

Once you've determined the string that specifies the key you created and want to sign, sign it.

> sudo pacman-key --lsign-key 'AUR Helper Signing Key'

Once this is done, the ArchLinux system will now trust packages signed by your signing key. If you want to revoke such a key, you can delete it from your pacman's keyring.

Warning

Be careful with pacman-key's delete command, as you might accidentally delete keys you don't mean to delete. If such a thing happens, you may have to regenerate your ArchLinux installation's pacman keyring.

Use the following command to delete a key from your ArchLinux system's keyring.

> sudo pacman-key -d 'AUR Helper Signing Key'

Testing

The build process will typically involve running the following.

$ ./AnotherAURHelper/update.py --config /home/build/config.toml

Just follow the steps, and by the end of it, it should build your packages, sign them, and place them in the directory specified in your config.toml.

Warning

Be sure to pacman -Syu in the container before running update.py. You should be doing this at most once per day (if you use AnotherAURHelper once a day).

Serving the Packages

As mentioned earlier, the contents of your /home/build/aur_pkgs directory can be served with nginx or others. The directory can be copied from your LXC container to elsewhere with ssh (sshfs maybe) or even rsync.