How to Create a Debian Mirror Using debmirror

This guide explains what the debmirror utility is and provides a direct, step-by-step approach for system administrators to build and maintain a private Debian operating system mirror. Creating a local mirror allows organizations to optimize network bandwidth, drastically reduce package installation latency across internal fleets, and maintain reliable software distribution in air-gapped or restricted infrastructure environments.

What is debmirror?

debmirror is a Perl-based command-line utility designed to create and update a partial or full mirror of Debian-based package repositories. Unlike raw syncing tools like standard rsync, debmirror intelligently parses repository metadata, verifies package checksums, validates cryptographic GPG signatures, and allows administrators to filter content by distribution release, hardware architecture, and repository section.

Prerequisites

Before deploying a Debian mirror, ensure the host machine meets the following requirements:

  • Storage: A full mirror can exceed several terabytes. A filtered mirror (e.g., modern amd64 architecture for a single release like bookworm) requires roughly 100 GB to 300 GB of storage.
  • Packages: Install debmirror, rsync, and GPG support utilities.
  • Web Server: A lightweight HTTP server such as Nginx or Apache to serve the mirrored packages to client machines.

Run the following command on Debian to install the necessary tools:

sudo apt update && sudo apt install -y debmirror rsync ed gpgv

Configuring GPG Keyrings

debmirror validates packages against Debian's official archive keys. Import the active Debian archive keyrings into a dedicated keyring location:

mkdir -p /root/.gnupg
gpg --no-default-keyring --keyring /etc/apt/trusted.gpg.d/debian-archive-keyring.gpg --export | gpg --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --import

Creating the Mirror Script

To maintain consistent updates, create a dedicated script rather than running raw commands. Below is an example script targeting a modern Debian environment:

#!/usr/bin/env bash
set -e

# Target directory where packages will be stored
MIRROR_DIR="/var/www/html/debian"

# Upstream Debian server
UPSTREAM_HOST="ftp.debian.org"
UPSTREAM_DIR="/debian"

# Architecture, distribution, and sections to mirror
ARCH="amd64"
DIST="bookworm,bookworm-updates,bookworm-security"
SECTION="main,contrib,non-free,non-free-firmware"

debmirror \
    --host="${UPSTREAM_HOST}" \
    --root="${UPSTREAM_DIR}" \
    --method=rsync \
    --progress \
    --dist="${DIST}" \
    --section="${SECTION}" \
    --arch="${ARCH}" \
    --cleanup \
    --nosource \
    --rsync-extra=none \
    --check-gpg \
    "${MIRROR_DIR}"

Key arguments explained:

  • --method=rsync: Specifies the transfer protocol (HTTP and FTP are also supported).
  • --dist: The Debian releases to fetch.
  • --arch: Limits packages to specified architectures (e.g., amd64, arm64). Omitting unused architectures saves massive amounts of disk space.
  • --nosource: Skips downloading source code packages (.dsc and .tar.gz) to conserve bandwidth and storage.
  • --cleanup: Deletes packages locally that have been removed from the upstream archive.

Make the script executable and run the initial sync:

chmod +x /usr/local/bin/sync-debian-mirror.sh
/usr/local/bin/sync-debian-mirror.sh

Serving the Mirror Over HTTP

Install and configure Nginx to expose the repository directory over the local network:

sudo apt install -y nginx

Create an Nginx configuration file at /etc/nginx/sites-available/debmirror:

server {
    listen 80;
    server_name mirror.internal.lan;
    root /var/www/html/debian;

    location / {
        autoindex on;
    }
}

Enable the configuration and reload Nginx:

sudo ln -s /etc/nginx/sites-available/debmirror /etc/nginx/sites-enabled/
sudo systemctl reload nginx

Automating Repository Synchronization

Configure a cron job to keep the mirror updated on a scheduled basis, typically during off-peak hours:

sudo crontab -e

Add the following entry to update the mirror daily at 2:00 AM:

0 2 * * * /usr/local/bin/sync-debian-mirror.sh > /var/log/debmirror.log 2>&1

Configuring Client Machines

Update the /etc/apt/sources.list file on internal client machines to pull from the newly configured private mirror instead of external repositories:

deb http://mirror.internal.lan/debian bookworm main contrib non-free non-free-firmware
deb http://mirror.internal.lan/debian bookworm-updates main contrib non-free non-free-firmware
deb http://mirror.internal.lan/debian bookworm-security main contrib non-free non-free-firmware

Run apt update on the client to confirm successful connectivity and repository indexing.