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
amd64architecture for a single release likebookworm) 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 gpgvConfiguring 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 --importCreating 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 (.dscand.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.shServing the Mirror Over HTTP
Install and configure Nginx to expose the repository directory over the local network:
sudo apt install -y nginxCreate 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 nginxAutomating Repository Synchronization
Configure a cron job to keep the mirror updated on a scheduled basis, typically during off-peak hours:
sudo crontab -eAdd 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.