Proxmox Package Mirror
🧭 Lab Architecture (what you’re building)
You will create two internet-connected machines:
| Name | Role | OS |
|---|---|---|
mirror-online |
Package mirror builder | Debian 13 (Trixie) |
|
Proxmox VE node (client) | Proxmox VE 9 |
Both are online for now. Later we simulate air-gap by disconnecting network.
🖥️ Step 0 — Create VirtualBox VMs
VM 1 — apt-mirror (Debian 13)
- Name:
apt-mirror - OS: Debian (64-bit)
- CPU: 2 cores
- RAM: 4 GB
- Disk: 200–500 GB (important for mirror!)
- Network: NAT (internet access)
Install Debian 13 (Trixie) minimal.
VM 2 — prox-online (Proxmox VE 9)
- Name:
prox-online - OS: Debian (64-bit)
- CPU: 4 cores
- RAM: 8 GB (minimum 4 works)
- Disk: 64–128 GB
- Network: NAT
Install Proxmox VE 9 ISO.
🌐 Step 1 — Basic networking
After install:
On apt-mirror
ip a
Example:
192.168.1.240
On prox-online
Test connectivity:
ping 8.8.8.8
🧱 Step 2 — Install mirror on apt-mirror
apt update
apt install apt-mirror nginx
⚙️ Step 3 — Configure mirror
nano /etc/apt/mirror.list
Use:
set base_path /var/spool/apt-mirror
set nthreads 20
set _tilde 0
############ Debian 13 ############
deb http://deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb http://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
############ Proxmox VE 9 ############
deb http://download.proxmox.com/debian/pve trixie pve-no-subscription
clean http://deb.debian.org/debian
clean http://security.debian.org/debian-security
clean http://download.proxmox.com/debian/pve
⬇️ Step 4 — Run initial mirror
apt-mirror
⏳ This will take a long time (first sync).
🌐 Step 5 — Serve mirror via nginx
nano /etc/nginx/sites-available/mirror
server {
listen 80;
server_name mirror01;
root /var/spool/apt-mirror/mirror;
autoindex on;
}
Enable:
ln -s /etc/nginx/sites-available/mirror /etc/nginx/sites-enabled/
systemctl reload nginx
🧪 Step 6 — Test mirror
From prox-online:
curl http://mirror01/deb.debian.org/debian/
If DNS fails, use IP:
curl http://192.168.56.10/deb.debian.org/debian/
⚙️ Step 7 — Configure Proxmox (prox-online)
Edit:
nano /etc/apt/sources.list
Replace with:
deb http://mirror01/deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb http://mirror01/deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
deb http://mirror01/security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
deb http://mirror01/download.proxmox.com/debian/pve trixie pve-no-subscription
Disable enterprise repo:
sed -i 's/^deb/#deb/' /etc/apt/sources.list.d/pve-enterprise.list
🔄 Step 8 — Test updates via mirror
apt update
apt upgrade
👉 If this works, your mirror is correct.
🔒 Step 9 — Simulate air-gapped environment
Now simulate real-world:
Option A (simple)
- Disable internet in VirtualBox (set network to “Host-only”)
Option B (better)
- Keep internal network between VMs
- Remove outbound internet
Then test again:
apt update
✅ If it still works → mirror is fully self-contained
💾 Step 10 — (Real-world) Transfer model
In production you will:
On internet system (mirror01):
apt-mirror
rsync -av --delete /var/spool/apt-mirror/mirror/ /media/usb/
Move to airgap:
rsync -av /media/usb/ /srv/mirror/
Serve via nginx → same as above
⚠️ Important lessons from this lab
1. DNS vs IP
In airgap, DNS usually doesn’t exist → use IP or internal DNS.
2. Mirror path structure matters
APT expects:
/deb.debian.org/debian
/security.debian.org/debian-security
/download.proxmox.com/debian/pve
Do NOT flatten directories.
3. Storage grows fast
Even in lab:
- Start small if needed:
deb http://deb.debian.org/debian trixie main
👍 Final result
You now have:
mirror01 (Debian) → builds mirror → serves HTTP
pve01 (Proxmox) → installs updates from mirror
And you verified:
- works online
- works offline
🚀 If you want next
I can help you:
- shrink mirror to “Proxmox-only minimal set” (~20–40GB)
- add USB incremental sync strategy (fast updates)
- or build a fully automated offline update pipeline with versioning
Just tell me 👍