Enhance apt/apk mirror fallback logic

Improve package mirror resiliency in misc/build.func and misc/install.func by adding fallback and detection logic for Debian/Ubuntu and Alpine CDNs. Changes include:

- Detect distro (debian vs ubuntu) and use appropriate mirror lists and primary mirror (ftp.debian.org vs archive.ubuntu.com).
- Add retry loops that try a shuffled list of regional mirrors, test connectivity, update repo files, and attempt package installs/updates again.
- For Alpine (apk) installs and updates, try alternate mirrors on failure, write /etc/apk/repositories, and surface clearer warnings/errors if all mirrors fail.
- Update interactive prompts and informational messages to reference the correct mirror list (Ubuntu vs Debian) and generalize prompt wording.
- Improve exit handling so failures are reported and abort the process when necessary.

These changes make automated installs more robust against CDN sync issues and unreachable primary mirrors.
This commit is contained in:
CanbiZ (MickLesk)
2026-03-26 16:04:48 +01:00
parent f5fa1306f4
commit dd911670e1
2 changed files with 107 additions and 20 deletions

View File

@@ -204,9 +204,19 @@ pkg_update() {
local failed_mirror
failed_mirror=$(grep -m1 -oP '(?<=URIs: https?://)[^/]+' /etc/apt/sources.list.d/debian.sources 2>/dev/null || grep -m1 -oP '(?<=deb https?://)[^/]+' /etc/apt/sources.list 2>/dev/null || echo "unknown")
msg_warn "apt-get update failed (${failed_mirror}), trying alternate mirrors..."
local eu_mirrors="ftp.de.debian.org ftp.fr.debian.org ftp.nl.debian.org ftp.uk.debian.org ftp.ch.debian.org ftp.se.debian.org ftp.it.debian.org ftp.fau.de ftp.halifax.rwth-aachen.de debian.mirror.lrz.de mirror.init7.net debian.ethz.ch mirrors.dotsrc.org debian.mirrors.ovh.net"
local us_mirrors="ftp.us.debian.org ftp.ca.debian.org debian.csail.mit.edu mirrors.ocf.berkeley.edu mirrors.wikimedia.org debian.osuosl.org mirror.cogentco.com"
local ap_mirrors="ftp.au.debian.org ftp.jp.debian.org ftp.tw.debian.org ftp.kr.debian.org ftp.hk.debian.org ftp.sg.debian.org mirror.aarnet.edu.au mirror.nitc.ac.in"
local distro
distro=$(. /etc/os-release 2>/dev/null && echo "$ID" || echo "debian")
local eu_mirrors us_mirrors ap_mirrors
if [[ "$distro" == "ubuntu" ]]; then
eu_mirrors="de.archive.ubuntu.com fr.archive.ubuntu.com se.archive.ubuntu.com nl.archive.ubuntu.com it.archive.ubuntu.com ch.archive.ubuntu.com mirrors.xtom.de"
us_mirrors="us.archive.ubuntu.com archive.ubuntu.com mirrors.edge.kernel.org mirror.csclub.uwaterloo.ca mirrors.ocf.berkeley.edu mirror.math.princeton.edu"
ap_mirrors="au.archive.ubuntu.com jp.archive.ubuntu.com kr.archive.ubuntu.com tw.archive.ubuntu.com mirror.aarnet.edu.au"
else
eu_mirrors="ftp.de.debian.org ftp.fr.debian.org ftp.nl.debian.org ftp.uk.debian.org ftp.ch.debian.org ftp.se.debian.org ftp.it.debian.org ftp.fau.de ftp.halifax.rwth-aachen.de debian.mirror.lrz.de mirror.init7.net debian.ethz.ch mirrors.dotsrc.org debian.mirrors.ovh.net"
us_mirrors="ftp.us.debian.org ftp.ca.debian.org debian.csail.mit.edu mirrors.ocf.berkeley.edu mirrors.wikimedia.org debian.osuosl.org mirror.cogentco.com"
ap_mirrors="ftp.au.debian.org ftp.jp.debian.org ftp.tw.debian.org ftp.kr.debian.org ftp.hk.debian.org ftp.sg.debian.org mirror.aarnet.edu.au mirror.nitc.ac.in"
fi
local tz regional others
tz=$(cat /etc/timezone 2>/dev/null || echo "UTC")
@@ -280,11 +290,17 @@ pkg_update() {
fi
done
# Phase 2: Try ftp.debian.org
# Phase 2: Try primary mirror
if [[ "$apt_ok" != true ]]; then
if timeout 2 bash -c "echo >/dev/tcp/ftp.debian.org/80" 2>/dev/null; then
msg_info "Attempting mirror: ftp.debian.org"
if _try_apt_mirror "ftp.debian.org"; then
local primary
if [[ "$distro" == "ubuntu" ]]; then
primary="archive.ubuntu.com"
else
primary="ftp.debian.org"
fi
if timeout 2 bash -c "echo >/dev/tcp/$primary/80" 2>/dev/null; then
msg_info "Attempting mirror: ${primary}"
if _try_apt_mirror "$primary"; then
apt_ok=true
fi
fi
@@ -309,9 +325,13 @@ pkg_update() {
# Phase 4: All auto mirrors failed, prompt user
if [[ "$apt_ok" != true ]]; then
msg_warn "Multiple mirrors failed (possible CDN synchronization issue)."
msg_info "Find Debian mirrors at: https://www.debian.org/mirror/list"
if [[ "$distro" == "ubuntu" ]]; then
msg_info "Find Ubuntu mirrors at: https://launchpad.net/ubuntu/+archivemirrors"
else
msg_info "Find Debian mirrors at: https://www.debian.org/mirror/list"
fi
while true; do
read -rp " Enter a Debian mirror hostname (or 'skip' to abort): " custom_mirror </dev/tty
read -rp " Enter a mirror hostname (or 'skip' to abort): " custom_mirror </dev/tty
[[ -z "$custom_mirror" ]] && continue
[[ "$custom_mirror" == "skip" ]] && break
[[ ! "$custom_mirror" =~ ^[a-zA-Z0-9._-]+$ ]] && {
@@ -333,7 +353,31 @@ pkg_update() {
fi
;;
apk)
$STD apk update
if ! $STD apk update; then
msg_warn "apk update failed (dl-cdn.alpinelinux.org), trying alternate mirrors..."
local alpine_mirrors="mirror.init7.net ftp.halifax.rwth-aachen.de mirrors.edge.kernel.org alpine.mirror.wearetriple.com mirror.leaseweb.com uk.alpinelinux.org dl-2.alpinelinux.org dl-4.alpinelinux.org"
local apk_ok=false
for m in $(printf '%s\n' $alpine_mirrors | shuf); do
if timeout 2 bash -c "echo >/dev/tcp/$m/80" 2>/dev/null; then
msg_info "Attempting mirror: ${m}"
cat <<EOF >/etc/apk/repositories
http://$m/alpine/latest-stable/main
http://$m/alpine/latest-stable/community
EOF
if $STD apk update; then
msg_ok "CDN set to ${m}: tests passed"
apk_ok=true
break
else
msg_warn "Mirror ${m} failed"
fi
fi
done
if [[ "$apk_ok" != true ]]; then
msg_error "All Alpine mirrors failed. Check network or try again later."
return 1
fi
fi
;;
dnf)
$STD dnf makecache