I’ve set up a local Arch repository, a dynamic reverse proxy cache using nginx — and a local “build server” for AUR packages, using aurutils.

Here is how, and why 👇

Table of contents


I have quite a few computers with Arch Linux — three desktops, two laptops, and some VMs. A local caching repository means I don’t have to download the same packages twice from the official mirrors.

Many of my computers use the same AUR packages, so it makes sense to build them once and install them with pacman.

The server

As the server; I set up an Arch Linux container on Alpha (my main Proxmox hypervisor).

Caching repository

I installed nginx, created the /srv/http/pacman-cache folder, and used the following /etc/nginx/nginx.conf:

user http;
worker_processes  1;

events {
  worker_connections 1024;

http {
  sendfile on;
  types_hash_max_size 4096;
  server_names_hash_bucket_size 128;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  resolver ipv6=off;

  server {
    listen      80;
    server_name aur-mirror.mydomain.no;
    root        /srv/http/aur;
    autoindex   on;

  # Pacman Cache
  server {
    listen      80 default_server;
    #server_name arch-mirror.mydomain.no;
    server_name _;
    root        /srv/http/pacman-cache;
    autoindex   on;

    # Requests for package db, signature files and files db should redirect upstream
    # without caching
    location ~ \.(db|sig|files)$ {
      proxy_pass http://mirrors$request_uri;

    # Requests for actual packages should be served directly from cache if available.
    #   If not available, retrieve and save the package from an upstream mirror.
    location ~ \.tar\.(xz|zst)$ {
      try_files $uri @pkg_mirror;

    # Retrieve package from upstream mirrors and cache for future requests
    location @pkg_mirror {
      proxy_store    on;
      proxy_redirect off;
      proxy_store_access  user:rw group:rw all:r;
      proxy_next_upstream error timeout http_404;
      proxy_pass          http://mirrors$request_uri;

  # Upstream Arch Linux Mirrors
  # - Servers are used in a round-robin fashion by nginx
  # - Add "backup" if you want to only use the mirror upon failure of the other mirrors
  upstream mirrors {
    server backup;
    server backup;

  server {

    location / {
      proxy_ssl_server_name on;
      proxy_set_header Host mirror.osbeck.com;
      proxy_pass       https://mirror.osbeck.com/archlinux$request_uri;

  server {

    location / {
      proxy_ssl_server_name on;
      proxy_set_header Host arch.jensgutermuth.de;
      proxy_pass       https://arch.jensgutermuth.de$request_uri;

  server {

    location / {
      proxy_ssl_server_name on;
      proxy_set_header Host mirror.neuf.no;
      proxy_pass       https://mirror.neuf.no/archlinux$request_uri;

And that is pretty much it for the caching mirror web server 😎

AUR build server

For the AUR build server we first need to install a few packages, and set up the local AUR repository:

You will need to install an AUR helper — I like yay.
$ yay -S aurutils vifm

$ sudo sudo mkdir /srv/http/aur
$ sudo repo-add /srv/http/aur/aur.db.tar.bz2

$ sudo chown your-user:your-group -R /srv/http/aur

Then we need to edit /etc/pacman.conf, and change the following configuration:

CacheDir    = /var/cache/pacman/pkg/
CacheDir    = /srv/http/aur/
#CleanMethod = KeepInstalled
CleanMethod = KeepCurrent

SigLevel = Optional TrustAll
Server = file:///srv/http/aur

CacheDir Overrides the default location of the package cache directory. The default is /var/cache/pacman/pkg/. Multiple cache directories can be specified, and they are tried in the order they are listed in the config file. If a file is not found in any cache directory, it will be downloaded to the first cache directory with write access. (…)

CleanMethod If set to KeepInstalled (the default), the -Sc operation will clean packages that are no longer installed (not present in the local database). If set to KeepCurrent, -Sc will clean outdated packages (not present in any sync database). The second behavior is useful when the package cache is shared among multiple machines, where the local databases are usually different, but the sync databases in use could be the same. (…)


Now we can start adding packages with aurutils:

$ aur sync yay
$ aur sync drawio-desktop-bin

To update and build all synced packages:

$ aur sync -u

And lastly; a small script to clean up old repository packages:


find /srv/http/pacman-cache/ -type d -exec paccache -v -r -k 2 -c {} \;
paccache -v -r -k 2 -c /srv/http/aur/

-v Increase verbosity, can be specified up to 3 times.

-r Remove candidate packages from the cache directory.

-k <num> Specify how many versions of each package are kept in the cache directory, default is 3.

-c <dir> Specify a different cache directory. This option can be used more than once. Default is to use the cache directory configured in pacman.conf.

man paccache

That is the server done, now to configure the clients to use the local repositories 👇

The clients

In /etc/pacman.d/mirrorlist — add your new local mirror, comment out all others:

### My local caching server
Server = http://arch-mirror.mydomain.no/$repo/os/$arch

Then, in /etc/pacman.conf, define your local AUR repository:

SigLevel = Optional TrustAll
Server = http://aur-mirror.my-domain.no/

And that is it 🙂 Now when you use pacman to install or update packages — it will use your local caching repository and already built AUR packages 👍


Last commit 2024-04-05, with message: Tag cleanup.