nerdstuff.org

crazy content for mankind, great stuff for nerds

09 Dec 2021

Managing Arch Linux ARM Repositories from x86_64 Systems

I have some custom repositories for Arch Linux packages that I use for packages from AUR and other packages that I created. Recently, I started supporting ARM architectures and thus needed a way to manage (i.e., add/build, update, remove) these packages for ARM architectures as well. One possibility to do so is installing Arch Linux ARM on an ARM device and use it for the management tasks. However, by combining some tools it’s also possible to manage ARM packages from a x86_64 system, even distributed builds via distcc are supported. In this blog post, I explain how this works.

The approach is based on the combination of two tools:

  1. crema is a tool to manage custom Arch Linux repositories. It is available for multiple architectures
  2. armutils provides scripts to create chroot containers for ARM architectures on x86_64 hosts and to utilize them

The idea is to create an ARM chroot container on an x86_64 host using armutils, install crema in that container and use it to manage ARM packages in a custom repository. The how-to below describes the detailed steps of that approach for an Aarch64 chroot container, but it also works for other ARM architectures, just replace the ARM image in the mkarmchroot command accordingly. A row starting with # indicates a command that must be executed as root, if a row starts with $ the command is executed as normal user.

  1. Install armutils:

     $ yay -Syu armutils-git
    
  2. Create an Aarch64 chroot container in the folder <YOUR-CHROOT-FOLDER> and install the base-devel group:

     # mkarmchroot -u http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz <YOUR-CHROOT-FOLDER>/root base-devel
    
  3. Enter chroot:

     # arm-nspawn <YOUR-CHROOT-FOLDER>/root
    
  4. Make user alarm a sudoer:

     [root@root ~]# echo "%wheel ALL=(ALL) ALL" > /etc/sudoers.d/10-alarm 
    
  5. (Optional) Enable parallel package downloads:

     [root@root ~]# nano /etc/pacman.conf
    

    Remove the comment sign from the row #ParallelDownloads = 5.

  6. Install crema and remove the cloned folder afterwards:

     [root@root ~]# pacman -Syu git
     [root@root ~]# cd /home/alarm
     [root@root alarm]# sudo -u alarm git clone https://aur.archlinux.org/crema-git.git
     [root@root alarm]# cd crema-git
     [root@root crema-git]# sudo -u alarm makepkg -si
     [root@root crema-git]# cd ..
     [root@root alarm]# rm -rd crema-git
    
  7. Create crema configuration and exit chroot:

     [root@root alarm]# sudo -u alarm mkdir -p .config/crema
     [root@root alarm]# sudo -u alarm nano .config/crema/repos.conf
     [root@root alarm]# exit
    
  8. Configure ssh: Create the keys and the ssh config as required to be able to access your repositories via rsync.

  9. (Optional) Enable distributed builds by installing distcc in the chroot container and configure <YOUR-CHROOT-FOLDER>/root/etc/makepkg.conf as described in this documentation.

  10. You are done. Now you can, for example, add an ARM package from AUR to your custom repository by executing

     # arm-nspawn <YOUR-CHROOT-FOLDER>/root sudo -u alarm crema add -r <YOUR_REPOSITORY> -n -a >PACKAGE>
    

    Since crema builds in a chroot per default and a chroot in a chroot is not working, the option --nochroot / -n has to be set. This applies to crema add ... and crema update ....

Notes

  1. Not all packages can be built that way
    While - at least as far as I tried that out - most packages could be built with the described approach, for some packages that does not work - I observed errors thrown by qemu in some cases. Building them on ARM hardware worked without problems.

  2. To make the execution of crema inside the chroot container more convenient, it might make sense to create a shell alias like below by adding that row to your ~/.bashrc or ~/.zshrc etc.:

     alias crema-armv7h="sudo arm-nspawn <YOUR-CHROOT-DIRECTORY>/root sudo -u alarm crema"
    

    To make the new alias know to the system, execute for example

     $ source ~/.zshrc
    
  3. If you want to add local packages to a repository (i.e., packages that are stored on your local file system), the corresponding host package folder must be bound explicitly to a folder inside the chroot container with --bind since otherwise the package files cannot be accessed from inside the container. The example below shows how this works:

    • Create an empty package folder in the chroot container (in the home folder of the alarm user in this case):

        # arm-nspawn <YOUR-CHROOT-FOLDER>/root sudo -u alarm mkdir home/alarm/pkg 
      
    • Add the package to a custom repository (the package folder of the host is bound to the just created folder pkg):

        # arm-nspawn <YOUR-CHROOT-FOLDER>/root --bind <PACKAGE-FOLDER-AT-HOST>:/home/alarm/pkg sudo -u alarm crema add -r <REPOSITORY> -n -l home/alarm/pkg
      
  4. If it is required to add a developer key, this must be done inside the chroot for the user that is used for package management. For example:

     # arm-nspawn <YOUR-CHROOT-FOLDER>/root sudo -u alarm gpg --recv-keys <KEY-ID>
     # arm-nspawn <YOUR-CHROOT-FOLDER>/root sudo -u alarm gpg --lsign-key <KEY-ID>
    
  5. To be able to sign packages or the repository DB, a private key must be known inside the chroot. Execute the following steps to do add the key for user alarm:

    Enter chroot and set the variable GPGKEY:

     # arm-nspawn <YOUR-CHROOT-FOLDER>/root
     [root@root ~]# nano /etc/makepkg.conf
    

    Replace the row

     #GPGKEY=""
    

    by

     GPGKEY=<ID-OF-YOUR-KEY>
    

    Import the private key from a file (here, we assume that the file was copied into the chroot):

    [root@root ~]# sudo -u alarm gpg --pinentry-mode loopback --import <YOUR-KEY-FILE>
    

    Set trust level for the key:

     [root@root ~]# sudo -u alarm gpg --edit-key <ID-OF-YOUR-KEY>
     gpg> trust
    

    Select the desired trust level and exit:

     gpg> quit                                
    

    To be able to use the key with crema, the GPG configuration of user alarm must be adjusted:

    Adjust ~/.gnupg/gpg.conf:

     [root@root ~]# sudo -u alarm nano /home/alarm/.gnupg/gpg.conf
    

    Add the rows

     use-agent 
     pinentry-mode loopback
    

    Adjust ~/.gnupg/gpg-agent.conf:

     [root@root ~]# sudo -u alarm nano /home/alarm/.gnupg/gpg-agent.conf
    

    Add the row

     allow-loopback-pinentry
    

    Exit chroot:

     root@root ~]# exit