Hi, I’m Eric. I’m technical director @enginsightcom with deep interest in it security.
Eric Range

Building a Multi‑Architecture APT Mirror with apt‑mirror and nginx

Eric Range
Eric Range
Apr 19, 2025
Hi, I’m Eric. I’m technical director @enginsightcom with deep interest in it security.

In mixed environments with both AMD64 servers and ARM‑based devices (such as Raspberry Pi), running separate mirrors for each architecture quickly becomes a management headache. Instead, you can use apt‑mirror’s arch= option in mirror.list alongside an nginx front end to maintain a single, unified repository that delivers packages for armhf, arm64, amd64, and any other supported architectures. All without relying on finicky tools like debmirror. This guide shows you how to configure apt‑mirror for multiple arches, set up nginx to serve the combined mirror, and point your clients to the new local mirror for fast, reliable updates.

Prerequisites

  • A Debian or Ubuntu host with sudo privileges
  • A storage volume with enough free space

1. Install packages and prepare the mirror user

# Install apt‑mirror and nginx
sudo apt update sudo apt install apt-mirror nginx

# Create the aptmirror system user:
sudo adduser --system \ 
  --home <aptmirror-directory> \ 
  --shell /usr/sbin/nologin  aptmirror

# Create mirror directories and set ownership:
sudo mkdir -p <aptmirror-directory>/{mirror,skel,var}
sudo chown -R aptmirror:aptmirror <aptmirror-directory>

2. Configure multi‑architecture mirroring

Edit /etc/apt/mirror.list to specify your paths, hooks, suites and architectures:

set base_path         <aptmirror-directory>/
set mirror_path       <aptmirror-directory>/mirror
set skel_path         <aptmirror-directory>/skel
set var_path          <aptmirror-directory>/var
set cleanscript       <aptmirror-directory>/var/clean.sh
set postmirror_script <aptmirror-directory>/var/postmirror.sh

deb [arch=armhf] http://deb.debian.org/debian          bookworm          main contrib non-free non-free-firmware
deb [arch=arm64] http://deb.debian.org/debian          bookworm          main contrib non-free non-free-firmware
deb [arch=armhf] http://deb.debian.org/debian          bookworm-updates  main contrib non-free non-free-firmware
deb [arch=arm64] http://deb.debian.org/debian          bookworm-updates  main contrib non-free non-free-firmware
deb [arch=armhf] http://deb.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware
deb [arch=arm64] http://deb.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware

# source repositories
deb-src http://deb.debian.org/debian          bookworm          main contrib non-free non-free-firmware
deb-src http://deb.debian.org/debian          bookworm-updates  main contrib non-free non-free-firmware
deb-src http://deb.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware

# third‑party repo covering both architectures...
# deb [arch=armhf,arm64] https://download.docker.com/linux/debian bookworm stable
  • The [arch=…] filter ensures apt‑mirror downloads only the specified binary packages.
  • Comma‑separated architectures can be mirrored in one pass.
  • Test the setup by running: sudo -u aptmirror apt-mirror /etc/apt/mirror.list

3. Set up nginx to serve the mirror

Place this configuration in /etc/nginx/nginx.conf or in a site file under /etc/nginx/sites-available/:

worker_processes auto;

events {
    worker_connections 10240;
}

http {
    sendfile off;
    keepalive_timeout 65;
    gzip off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    server {
        listen 80;
        server_name _;

        location /mirror/ {
            alias <aptmirror-directory>/mirror/;
            autoindex on;
            sendfile off;
            add_header Cache-Control "no-store";
            expires off;
        }
    }
}
  • worker_processes auto: one process per CPU core for best throughput
  • worker_connections 10240: handles many concurrent clients
  • sendfile off: avoids stale‑file issues on networked storage
  • gzip off: prevents altering binary packages and metadata
  • autoindex on: allows directory listing so apt can discover releases
  • Cache-Control “no-store” / expires off: ensure clients always fetch fresh files

Reload nginx to apply:

sudo nginx -t
sudo systemctl reload nginx

4. Automate updates with cron

To synchronize every six hours, add this to /etc/crontab or a file in /etc/cron.d/:

0 */6 * * * sudo -u aptmirror /usr/bin/apt-mirror /etc/apt/mirror.list > <aptmirror-directory>/var/apt-mirror.log 2>&1

This runs apt‑mirror under the aptmirror user and logs output for review.

5. Configure client systems

Edit /etc/apt/sources.list:

deb http://<aptmirror-address>/mirror/deb.debian.org/debian          bookworm          main contrib non-free non-free-firmware
deb http://<aptmirror-address>/mirror/deb.debian.org/debian          bookworm-updates  main contrib non-free non-free-firmware
deb http://<aptmirror-address>/mirror/deb.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware

Running sudo apt update will now fetch packages and metadata from your local mirror, with correct directories for each architecture.