Fuzzy Debian mirror picker centered in Europe
- Python 92%
- Shell 8%
| .gitignore | ||
| apply_debian_mirrors.template.sh | ||
| debian_mirror_picker.py | ||
| README.md | ||
debian-mirror-picker
Lazy, async, Europe-first Debian archive mirror picker (stdlib only, no dependencies).
What it does
- Fetches the authoritative mirror list from
https://mirror-master.debian.org/status/Mirrors.masterlist(fallback:https://www.debian.org/mirror/list-full— the same sourcesoftware-properties-style tools parse). The masterlist carries aCountry:code per site, which drives geographic ordering. - Orders candidates by proximity: home country first (autodetected from
current apt sources, e.g.
ftp.es.debian.org→ES, else--home-cc), then the rest of Europe, then the rest of the world. CDN entries (deb.debian.org) probe early. - Nudges each server with a tiny async ranged HTTP GET
(
<base>dists/stable/Release,Range: bytes=0-8191) and a deliberately short per-probe timeout (default 4 s). Slow or silent hosts surrender quickly and are reported asnot good enough. - Lazy early-exit (non-exhaustive by design): completions stream via
asyncio.as_completedso fast responses float up. As soon as--fast-count(default 5) European mirrors answer within--fast-threshold(default 1.5 s), pending probes are cancelled and non-European mirrors are downgraded/skipped. - Rewrites apt sources to
$HOME/tmp, never in place: every Debian archive entry in/etc/apt/sources.listand/etc/apt/sources.list.d/(*.listone-liners + DEB822*.sources) gets the fastest winner.security.debian.organd third-party repos (Brave, Mint, WezTerm, …) are left untouched. - Generates a helper script in
$HOME/tmpthat backs up current files with a timestamp and offers to install the new ones (run by hand).
Usage
python3 debian_mirror_picker.py [options]
| Option | Default | Meaning |
|---|---|---|
--fast-count |
5 | European mirrors ≤ threshold that trigger early-exit |
--fast-threshold |
1.5 | seconds; "fast enough" bar |
--timeout |
4.0 | per-probe surrender timeout (s) |
--concurrency |
20 | max parallel probes |
--top |
3 | winners recorded as primary + alternatives |
--home-cc |
autodetect | home country code, e.g. ES |
--outdir |
$HOME/tmp/apt-mirrors-<ts> |
rewritten sources go here |
--apply-script |
$HOME/tmp/apply_debian_mirrors.sh |
generated helper script |
--max-mirrors |
0 (no cap) | debug cap on candidates |
Example:
python3 debian_mirror_picker.py --timeout 4 --concurrency 20 \
--fast-count 5 --fast-threshold 1.5 --top 5
Applying the result (you, by hand)
Each run writes a ready-to-use helper to ~/tmp/apply_debian_mirrors.sh:
bash ~/tmp/apply_debian_mirrors.sh
The helper shows a diff, asks to back up current files
(/etc/apt/backups-<timestamp> plus *.bak-<timestamp> next to the
originals), then asks before copying the new ones in. Follow up with:
sudo apt update
Files
debian_mirror_picker.py— the whole tool, stdlib only.apply_debian_mirrors.template.sh— reference copy of the helper template (the picker embeds it asAPPLY_SCRIPT_TEMPLATEand writes a concrete copy with your output dir to~/tmp/apply_debian_mirrors.shon each run).README.md— this file.
Requirements
Python 3.10+ (uses asyncio, urllib, pathlib — nothing else).
Network access to mirror-master.debian.org and the mirrors.
Read access to /etc/apt/sources.list* (rewrites never touch them directly).