Be Kind to Your Bandwidth (and Mirrors): Building a Local Arch Linux Package Cache

Estimated reading time: 8 minutes

Table of contents

If you run one Arch Linux system, updates are a daily joy. If you run four five of them – like I currently do – updating becomes a bandwidth-hogging chore. That is exactly why I decided to set up an local Arch Linux package cache to save bandwidth and speed up updates across my network.

I have four Arch Linux machines (plus a new cache server makes five), and one Garuda Linux system that I set up ages ago for Sunshine+Moonlight game streaming. It still works perfectly, so I’m keeping it until it breaks! But every time a major update drops, I found myself downloading the exact same gigabytes of data five times over.

It felt senseless. Why pull the same linux-zen kernel, cuda or nvidia-dkms package from a public mirror halfway across the world for every single machine?

The Solution: An Arch Linux Local Package Cache

I decided to solve this by building a dedicated Arch Linux local package cache. My goals were simple:

  1. Speed: Downloading packages over my local 2.5GbE network (or even Wi-Fi 6) is exponentially faster than reaching out to the internet.
  2. Efficiency: I wanted proactive prefetching. The server should download updates for commonly used packages overnight. This way, when I sit down to update my first machine in the morning, almost all the files are already cached locally and install instantly (assuming no new updates dropped since the prefetch!).
  3. Community: By running a local Arch Linux mirror, I significantly reduce my load on public mirrors. It’s a small way to give back to take less from the community infrastructure. (I guess my real way of giving back is sharing this guide and script with you all! 🙂)
  4. Experimentation: I wanted to test Arch Linux as a server OS. While it’s famous for its rolling release model on desktops, I was curious to see if it could be stable and reliable enough for long-term server use. Setting up this cache server was the perfect low-risk project to find out. (Time will tell!)
1702 pacman packages updated via my Local Arch Linux Package Cache

The “Secret Sauce”: Automating the Local Arch Linux Package Cache

To make this happen, I used Pacoloco, a fantastic caching proxy for Pacman, acting as my primary pacman proxy server. But a proxy is only one piece of the puzzle. You also need a web server like Nginx to serve the files securely, optimized mirror lists to actually find the packages, and maintenance tasks to keep it all running smoothly. Doing all of this manually is tedious and error-prone.

So, naturally, I wrote a comprehensive script to automate the entire process of setting up an local Arch Linux package cache – from installing dependencies and configuring Nginx with authentication to setting up daily auto-updates.

You can find the full script on my GitHub: setup_pacman_proxy.sh

Under the Hood: Solving the Technical Hurdles

Building this local Arch Linux package cache wasn’t just a matter of pacman -S pacoloco. I hit a few bumps along the way that shaped how the script works.

1. The Missing .sig Files

One of the biggest headaches I encountered was with package signatures. For some reason, if the pacman proxy server cached the database (.db) or signature (.sig) files, clients would often end up with stale data, causing pacman to scream about invalid or corrupt signatures.

I solved this by explicitly configuring Nginx to bypass its own cache for these specific file types. The script generates an Nginx config containing a location block that matches \.db(\.sig)?$. This forces Nginx to pass these requests directly to Pacoloco. Unlike a standard Nginx cache, Pacoloco handles these critical files intelligently, ensuring they are fresh from the upstream mirror before serving them to the client.

2. Hybrid Fallback System

Reliability is key. I didn’t want my inability to maintain my home lab to prevent me from updating my laptop when I’m on the road.

The client-side configuration (which the script generates instructions for) works in a hybrid mode. You add your local Arch Linux Package Cache server to the top of your /etc/pacman.conf, but you keep your standard mirror list below it.

  • If I’m at home: Pacman hits my cache server first. Fast downloads!
  • If the server is down or I’m traveling: Pacman notices the cache is unreachable and seamlessly falls back to the standard public mirrors. (Well, actually, I can even access it when I’m on the road – and it’s fast thanks to my 1Gbit fiber connection at home – but more on that in the Security section below!)

3. Security: HTTP Basic Auth

Since I might want to expose this to the internet (securely) to update my laptop while traveling, I added HTTP Basic Authentication. The script prompts you to create a username and password, which Nginx uses to gate access.

“But wait, where is the SSL?” You might notice the script configures Nginx on port 80 without SSL. This is intentional for my setup. I run this behind an Nginx Proxy Manager instance which handles all the SSL termination and certificates, sitting safely behind Cloudflare. Adding SSL logic directly to this script felt redundant for my use case, though I might add a Let’s Encrypt option in a future version for standalone setups.

Update: I wanted to eliminate the dependency on an external proxy for internal traffic. So I moved to native Let’s Encrypt SSL, read more about it here.

4. Eating Its Own Dog Food: Server-Side Caching

One of the best optimizations for this Arch Linux update cache is configuring the server to use its own cache. The script modifies the server’s own /etc/pacman.conf to point to the local pacoloco instance (connecting directly to localhost:9129, bypassing Nginx authentication).

This creates a beautiful loop of efficiency:

  1. The server runs its automated daily-update.sh script at 4 AM.
  2. It downloads all the new updates for itself through the local proxy.
  3. Pacoloco caches these files.
  4. When I wake up and update my laptop or desktop later that morning, the packages are already sitting in the cache, ready to be served at LAN speeds. It effectively prefetches updates for my entire network just by keeping itself up to date.

5. Prefetching for Speed

On top of that, I configured Pacoloco’s built-in prefetching. The script configures a daily job that checks for updates to any other packages currently in my cache (that the server itself might not use). If a new version of firefox or the kernel is available, the server downloads it automatically while I sleep.

Unleash the Speed: Running the Local Arch Linux Package Cache Script

If you want to set up your own local Arch Linux mirror, it’s incredibly straightforward. Spin up a fresh Arch Linux container or VM (I use Proxmox, of course), and run:

wget https://raw.githubusercontent.com/ramonvanraaij/Scripts/main/linux/Arch%20Linux/setup_pacman_proxy.sh
chmod +x setup_pacman_proxy.sh
sudo ./setup_pacman_proxy.sh

The script will handle dependencies, user creation, Nginx configuration, and even set up a daily update & reboot cycle (that only runs if the network is idle!). At the end, it spits out the exact configuration block you need to copy-paste into your client machines.

It’s been running for about a week now, and seeing a Download Rate of 280 MiB/s in my terminal never gets old…

Local Arch Linux Package Cache Speed
Download Rate: 280MiB/s

Bonus Round: Adding APT Caching for Debian/Ubuntu

Since you made it to the very end of this blog post, I have a little bonus for you.

While Arch Linux is my daily driver, I (like many of you) still run plenty of Debian VMs and containers in my homelab. It seemed silly to have a robust cache server for one ecosystem but leave the others out in the cold.

So, I wrote an add-on script: setup_apt_proxy.sh.

Important: This script is designed to be run on the same Arch Linux server after you have completed the main setup_pacman_proxy.sh setup. It acts as an extension, not a standalone replacement.

Here is what it does:

  1. Installs apt-cacher-ng from the AUR repository.
  2. Enables and starts the service automatically.
  3. Configures Nginx: It intelligently injects a secure /apt/ location block into your existing Nginx configuration file (the one managed by the main script). This means your APT cache gets the same security (Basic Auth) and port (80) as your Pacman cache without you lifting a finger.
  4. Validates Everything: It runs a quick check to ensure the new configuration is valid and the service is responding.

To use it, just grab it from my GitHub and run it on your new cache server:

wget https://raw.githubusercontent.com/ramonvanraaij/Scripts/main/linux/Arch%20Linux/setup_apt_proxy.sh
chmod +x setup_apt_proxy.sh
sudo ./setup_apt_proxy.sh

Now you have a single, unified cache server handling updates for both your bleeding-edge Arch machines and your stable Debian servers. Enjoy the speed!

Final Thoughts: Faster Updates, Happier Mirrors

Building this local Arch Linux package cache server was one of those “quality of life” improvements that I wish I had done sooner. Not only do my six Arch (based) systems update almost instantly now, but I also feel better knowing I’m not slamming public mirrors with redundant requests for every single kernel update.

It’s a simple, automated solution that sits quietly in the background and just works – exactly how a home lab service should be. If you’re managing multiple Arch-based systems, give the script a try. Your bandwidth (and your patience) will thank you – and if you grabbed the bonus script, your Debian (and Ubuntu) VMs will thank you too!


Buy me a coffee 🙂
If you found this post helpful, informative, or if it saved or made you some money, consider buying me a coffee. Your support means a lot and motivates me to keep writing.
You can do so via bunq.me (bunq, iDeal, Bankcontact and Credit- or Debit cards) or PayPal (PayPal and Credit- or Debit cards). Thank you!

Disclaimer
The blog posts, guides, and scripts provided on this website are for informational and educational purposes only. They are provided “as is” and without any warranty of any kind, either express or implied, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement.
By using the information or scripts from this blog, you agree that I am not liable for any direct, indirect, incidental, consequential, or any other damages or losses arising from the use of or inability to use the information, scripts, or instructions contained herein. You assume full responsibility for any and all risks associated with the use of this content.
The blog posts, guides, and pages may contain referral/affiliate links. If you make a purchase through these links, I may receive a commission at no additional cost to you.

 
Posted in Arch Linux, Hardware, Home Lab, Linux, Linux Tutorials, Proxmox, System AdministrationTags:
Write a comment