Automating Arch Linux Part 1b: Hosting an Arch Linux Repo in a Hosted Git Repository


This post is no longer being updated as I found too many limitations around git repos and storing larger packages inside them, quite often hitting the size limitations for some packages. It currently makes use of repose but aurutils is set to drop support for it at some point as there are a number of issues with it and so will eventually stop working. It should be possible to use repo-add but this creates symlinks which need to be dealt with as they do not work when accessed via the raw links.

In this three-part series, I will show you one way to simplify and manage multiple Arch Linux systems using a custom repo, a set of meta-packages and a scripted installer. Each part is standalone and can be used by its self, but they are designed to build upon and complement each other each focusing on a different part of the problem.

When you use Arch Linux for any length of time you start collecting sets of AUR packages that you frequently use. Now, Arch Linux has loads of AUR helpers that make managing AUR packages painless, but when you start using arch on multiple systems it becomes annoying and time consuming to rebuild AUR packages on each system. In this post, I will show you how to use an hosted git repository to create a cheap, low maintenance Arch Linux repository. As well as making use of the aurutils package to make building and upgrading AUR packages a painless exercise.

You can use any git provider you wish, for example Gitlab or Github the only requirement is they have a public URL you can fetch the raw files from. For this guide I will use Github.


We only require a few packages to get us going of which only aurutils needs to be installed from AUR. It will be the only package we are required to build and install manually.

  • aurutils: a set of utilities that make it easy to manage/update a repo with AUR packages.
  • git: to manage the git repo.
  • repose: an alternative to add-repo, but makes deploying the repo easier inside a git repo. Aurutils automatically uses repose if it is installed, so we will not explicitly use. ^
  • base-devel: needed to build aurutils and other packages.

To install all of these run the following.

sudo pacman -S --needed repose base-devel git
tar -xf aurutils.tar.gz
cd aurutils
makepkg -sci

If you get the following error while running makepkg.

==> Verifying source file signatures with gpg...
    aurutils-1.5.3.tar.gz ... FAILED (unknown public key 6BC26A17B9B7018A)
==> ERROR: One or more PGP signatures could not be verified!

Simply download the missing key with the following before running makepkg above.

gpg --recv-key 6BC26A17B9B7018A

^ We are using repose instead of repo-add as repo-add creates symlinks to the database which do not always work inside raw links to repos.

Creating the Git Repo

Head over to Gitlab and create a new repository.

New Repo

Give it an name and ensure that it is public. It needs to be public to allow pacman to download packages from it without any kind of authentication.

Create Repo

And finally grab the clone URL for your new repository.

Clone URL

And clone it locally and create a directory to house your Arch Linux repo such as x86_64 - It is convention to separate Arch Linux repos via the architecture of the packages they contain.

git clone
cd arch-repo
mkdir -p x86_64

Aurutils - Building and Managing Packages

Aurutils contains a suite of utilities that can be used to manage a repo of AUR packages. The two main utilities we will use are aursearch, which can search AUR for packages that match a given pattern.

% aursearch aurutils
aur/aurutils 1.5.3-5 (55)
    helper tools for the arch user repository
aur/aurutils-git 1.5.3.r234.g15ef2ab-1 (5)
    helper tools for the arch user repository

And aursync which will download and build packages and ensure packages in the repo are up to date.

For aursync to work, we need to add a repo to /etc/pacman.conf

SigLevel = Optional TrustAll
Server =

Give your repo a unique name by replacing [mdaffin] with something else. Change the URL to that of your repos raw link. You can get the raw link for most hosted git providers by creating a file in the repo and viewing the raw file, then just remove the filename form that url.

Now we can create the repo and upload our first package to it. For this, we are going to rebuild the aurutils package as it will be handy to have that stored in our repo.

aursync --repo mdaffin --root x86_64 aurutils

Replace mdaffin with the name of your repo, this must match the section in /etc/pacman.conf. Since we have a remote repo we need to tell aursync were to place the files using --root <dir> pointing it to the directory we created inside the git repo.

If all goes well you should end up with the package and arch repo database inside the git repo.

% ls x86_64
aurutils-1.5.3-5-any.pkg.tar.xz  mdaffin.db  mdaffin.files

Finally we need to commit and push these changes.

git add x86_84
git commit -m "added aurutils"
git push

Now they packages should be available to download with pacman.

% sudo pacman -Syy
% pacman -Ss aurutils                                                              :(
mdaffin/aurutils 1.5.3-5 [installed]
    helper tools for the arch user repository

And that's it, you have created a repo inside a hosted git repository. You can add more packages to this repo using the aursync command above.

To check for and update all the packages in the repo simply add -u to the aursync command.

aursync --repo mdaffin --root x86_64 -u

And remember to commit and push when you are done.

Wrapper Script

We can automate most of this with a simple wrapper script around aursync. Simply save this script somewhere, replace the CLONE_URL, GIT_BRANCH, REPO_PATH and REPO_NAME variables with your own and call it like you would aursync: ./aursync_wrapper PACKAGE or ./aursync_wrapper -u.

This script will automatically clone and sync the git repo to ~/.local/share/arch-repo/repo.

#!/bin/bash -x
# Wraps aursync command that stores built packages inside a git repo
set -uo pipefail
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
shopt -s expand_aliases

mkdir -p "${DATA_DIR}"
alias gitc='git -C "${DATA_DIR}/repo"'

if [[ -d "${DATA_DIR}/repo" ]]; then
    # DATA_DIR exists, reset and pull any changes
    gitc reset --hard
    gitc clean -xffd
    gitc checkout "${GIT_BRANCH}"
    gitc pull
    # DATA_DIR does not exist, so clone it
    git clone -b "${GIT_BRANCH}" "${CLONE_URL}" "${DATA_DIR}/repo"

mkdir -p "${DATA_DIR}/repo/${REPO_PATH}"

aursync --repo "${REPO_NAME}" --root "${DATA_DIR}/repo/${REPO_PATH}" "$@"

if ! gitc status | grep "nothing to commit, working tree clean" &>/dev/null; then
    gitc add .
    gitc commit -m "aursync $@"
    gitc push


There are some limitations with this approach, most git hosted git repos have a soft or hard limit on the repo size - typically around 1GB which you can quickly exceed with a collection of packages. You also need to make sure that when you prune packages you also squash your repo's history or you won't actually be saving any space.

This approach is more stable on weak connections than relying on a network mounted fuse file system as you are working locally and only syncing up changes when you start or have finished. The files remain cached on your local system but you do need to download all the files as a one-off when you first clone the repo which can take a bit more time than using a networked file system.

Luckily it is very easy to switch between the two methods as it just requires you to download the repo and upload it somewhere else.

Discuss on Reddit