作为运维,最头疼的场景之一就是:内网一堆Ubuntu机器等着装软件包,但外网带宽就那么大,几十台机器同时 apt update 的时候,能把出口堵得死死的。更别提某些离线网络环境,机器根本出不去,只能干瞪眼。我实战里的做法是搞一台镜像同步服务器,每天凌晨3点自动去上游拉取Ubuntu源,内网其他机器全部指向它。今天这篇就把这套从同步到发布再到客户端配置的完整链路拆开讲清楚,包含踩坑记录和优化细节。
1. 为什么选择自建同步源而不是直接换源
很多朋友一上来就想到“ubuntu换源”,把 /etc/apt/sources.list 改成阿里云或者清华源就完事了。这个操作在单机或者几台机器的情况下完全够用,速度也确实比官方源快很多。但一旦机器数量上了规模,或者网络环境属于隔离网段,直接换公网源就有几个绕不开的问题。
1.1 多机并发拉取的公网带宽压力
假设你有30台Ubuntu服务器,每台都配了阿里云源。平时还好,但在统一发版或者批量装软件的高峰期,30台机器同时去公网拉同一批 .deb 包,出口带宽瞬间被打满。实际上跑业务的内网流量也被挤占。相同的大版本更新,本地源只需要从公网拉一次,剩下的29台从内网走千兆甚至万兆,体感是完全不同的。
1.2 离线环境的刚性需求
还有一种更极端的场景——物理隔离的机房或者涉密内网,机器根本没有外网访问权限,这时候 “ubuntu挂载iso做本地源” 是很多人的应急方案。用Ubuntu安装ISO挂载出一个只读源,能解决系统安装后的一小部分基础包需求,但ISO里的软件包版本老旧、数量有限,连 docker-ce、nginx 这类常用软件都没有,更别提后续的 apt upgrade 安全更新了。
自建同步源不一样,它是rsync或apt-mirror从上游持续拉取整个仓库结构,包括 main、universe、multiverse 等组件以及对应的安全更新,Pull一次之后,内网就是一个完整且持续更新的软件仓库。
1.3 自建同步源的适用边界
写这篇之前先明确一下,自建同步源不是银弹。如果只是个人开发机或者三五台测试服务器,配一下阿里云源、华为云源,完全没必要折腾一台服务器天天跑同步。自建源更适合下面这些场景,你可以对照一下:
- 内网服务器数量超过10台,且有统一运维管理诉求
- 网络架构中有DMZ区或离线区,需要定期向隔离网段推送软件包
- 对软件包版本有审计需求,需要固定某个时间点的仓库快照
- 出口带宽紧张,希望把重复流量收敛到内网
以上条件满足任意两条,就值得把这套方案落地。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 同步链路设计:上游选择与同步工具选型
整体架构其实很简单:一台有外网访问权限的服务器(同步机),配置定时任务每天凌晨同步Ubuntu官方源或国内镜像源,同步完成的数据存放到本地目录,再通过Nginx或Apache把这个目录以HTTP形式暴露出去,内网其他机器的apt源地址指向这台同步机。
2.1 上游源选哪个更省流量
既然是自己搭源,上游选得不好,每天凌晨的rsync流量会很难看。官方源(archive.ubuntu.com)虽然数据最全,但服务器在欧洲,跨洋同步的稳定性和速度都不理想。国内更推荐下面几个:
| 上游源 | 同步地址 | 特点 |
|---|---|---|
| 阿里云 | rsync://mirrors.aliyun.com/ubuntu/ |
速度快,国内访问延迟低,支持rsync协议 |
| 清华TUNA | rsync://mirrors.tuna.tsinghua.edu.cn/ubuntu/ |
更新频率高,带宽充足,教育网优先 |
| 中科大USTC | rsync://rsync.mirrors.ustc.edu.cn/releases/ |
同步策略较为保守,稳定性好 |
| Ubuntu官方 | rsync://archive.ubuntu.com/ubuntu/ |
数据最完整,但跨洋同步慢 |
我这边之前用的是清华源,后来切了阿里云。原因很实际:阿里云的rsync并发限制没那么严格,凌晨同步的带宽跑得起来,清华源偶尔会遇到连接被重置的情况。另外要注意,如果你需要同步ports(ARM、RISC-V等架构的软件包),上游地址要选对应架构的路径,标题和这里默认讲解amd64架构。
2.2 工具选型:rsync与apt-mirror的取舍
同步工具主流有两个方案,一个是传统的 rsync 直接拉取,另一个是 apt-mirror 工具。很多教程会推荐apt-mirror,但我实际用了两年后,最终更倾向于纯rsync脚本,原因下面展开说。
apt-mirror 的原理是解析源列表里的Packages索引文件,然后根据索引逐个下载 .deb 包。它的好处是灵活,可以只同步某一个组件或者某一个架构。但坑也很明显:索引解析偶尔会因为上游Packages文件更新中的异常而中断,而且apt-mirror的断点续传能力比较弱,一旦同步中途断掉,重新跑的时候容易重复下载大量包。
rsync 是文件级增量同步,它的思路是直接把上游整个 dists 和 pool 目录结构与本地做一个镜像,每次同步只传输有变化的文件。配合 --delete 参数还能自动清理上游已经删除的旧包,长期跑下来目录不会越来越臃肿。对于“每天定时同步”这种场景,rsync的增量特性比apt-mirror的逐包下载效率高很多,尤其是软件包数量上万之后,这个差距非常明显。
所以我的方案是:rsync做主力同步,apt-mirror备用。后面会给出我实际使用的rsync同步脚本,里面有一些非默认参数的取舍,是实战中调优的结果。
2.3 同步目录的空间规划
这一个坑,我最早是没重视的。Ubuntu完整仓库(amd64 + i386 + 源码包)同步下来,体积是逐年膨胀的。以Ubuntu 24.04(Noble)为例,仅amd64架构的二进制包,完整同步一次大约需要500GB到700GB,如果再把源码包一起同步,总量轻松突破1TB。加上我上面要求保留历史版本,pool 目录里同一软件的多版本会同时存在,实际占用空间更大。
规划同步目录时,建议按下面的容量评估方式来:
bash复制# 只同步amd64二进制包(不含源码包)
# 预估容量: 600GB ~ 800GB
# 同步命令里排除源码包目录,不添加deb-src
# 完整同步(含源码包)
# 预估容量: 1.2TB ~ 1.5TB
# 需要确认同步机上磁盘空间充足
还有一个经常被忽略的点:rsync同步时会产生临时文件,如果inode不够或者磁盘余量不足5%,同步过程很容易在中途失败并留下半截文件。建议同步目录所在文件系统预留至少10%的余量。
3. 核心实现:rsync同步脚本与Nginx发布
下面直接给出一套可以落地的配置和脚本。我的环境是Ubuntu 24.04同步机,IP为 192.168.1.10,同步数据目录 /data/mirror/ubuntu,通过Nginx的80端口发布。
3.1 写一个稳健的rsync同步脚本
脚本逻辑并不复杂,但上线前一定要把几个rsync参数的含义吃透。
bash复制#!/bin/bash
# /usr/local/bin/sync_ubuntu_mirror.sh
# 作用:每天定时同步Ubuntu apt源到本地目录
MIRROR_DIR="/data/mirror/ubuntu"
LOG_FILE="/var/log/ubuntu-mirror-sync.log"
LOCK_FILE="/var/run/ubuntu-mirror-sync.lock"
# 防止上一个同步任务还没结束就开启新任务
if [ -e "$LOCK_FILE" ]; then
echo "[$(date '+%F %T')] 上次同步尚未结束,本次同步跳过" >> "$LOG_FILE"
exit 1
fi
touch "$LOCK_FILE"
# 记录开始时间
echo "[$(date '+%F %T')] ====== 开始同步 Ubuntu 24.04 noble ======" >> "$LOG_FILE"
# 执行rsync同步
rsync -avz --delete \
--progress \
--partial \
--timeout=600 \
--exclude="*.~tmp~" \
--exclude=".~tmp~" \
--exclude="lock" \
--exclude="ls-lR*" \
--exclude="project" \
--exclude="dists/*/universe" \
rsync://mirrors.aliyun.com/ubuntu/ "$MIRROR_DIR/" >> "$LOG_FILE" 2>&1
# 记录结束时间
echo "[$(date '+%F %T')] ====== 同步结束 ======" >> "$LOG_FILE"
# 清理锁文件
rm -f "$LOCK_FILE"
脚本里我特意加了几个东西,解释一下:
--timeout=600这个很关键,不加的话rsync在长时间空闲连接时可能一直挂起,定时任务直接就卡死了。600秒内如果没有数据传输就断开,配合systemd定时器或crontab下次重试,整体更健康。--partial参数保留部分传输的文件。rsync默认如果传输中断会把半成品文件删掉,下次从头传,加了--partial之后,已经传完的部分会保留,下次同步自动续传,这对大仓库很友好。--exclude="ls-lR*"是排除上游生成的递归文件列表索引,这个文件在完整仓库里体积不小,但对apt客户端完全没用。- 末尾那个
--exclude="dists/*/universe"是我刻意排除的。universe组件包含的软件包数量相当庞大,但我内网环境用不到,排除后同步时间能缩短一半以上。如果你也有类似需求,可以按需调整。
3.2 crontab定时任务配置
定时任务本身很简单,直接写进root的crontab:
bash复制# 每天凌晨3点执行同步任务
0 3 * * * /usr/local/bin/sync_ubuntu_mirror.sh
讲一下为什么定时到凌晨3点。这个时间选择有讲究:上游镜像站的同步完成时间通常都在凌晨1点到2点之间(它们自身也是从官方源或者其他更上游的源拉数据),凌晨3点去同步,数据基本已经是最新状态。而且这个时间段业务流量最低,即便rsync把出口带宽占满,也不会影响白天的工作。
这里额外提一句,如果你发现自己的机器时间和标准时间有偏差,务必先配置好 chrony 或者 systemd-timesyncd 做时间同步。定时同步源的场景对时间精度要求不算苛刻,但如果偏差超过几分钟,日志排查会变得很混乱。
3.3 Nginx发布HTTP源
rsync只是把文件从上游拉到了本地,要让它成为内网apt源,还得有一个HTTP服务把这些文件暴露出去。Nginx配置如下:
nginx复制server {
listen 80;
server_name mirror.local;
root /data/mirror/ubuntu;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
location / {
# 防止apt客户端在半截文件上反复重试
satisfy any;
allow all;
}
# 对dists目录下的索引文件做缓存,减少磁盘IO
location ~* \.(gz|bz2|xz)$ {
expires 1h;
add_header Cache-Control "public";
}
}
关键点是 autoindex on,没有这个,客户端访问目录时会403找不到包。另一个实用细节是在Nginx的error log里,如果看到大量 open() "/data/mirror/ubuntu/dists/..." failed (2: No such file or directory) 的错误,先检查root路径是不是配错了,尤其是同步目录层级多了还是少了一层,这类问题很常见。
配置完成后:
bash复制nginx -t
systemctl reload nginx
curl -I http://192.168.1.10/ubuntu/dists/noble/InRelease
能返回HTTP/1.1 200就代表发布成功。
3.4 systemd定时器替代crontab的可选方案
crontab本身足够稳定,但Ubuntu 24.04这类新版本系统上,systemd的timer单元是一种更现代的方式,日志也更好查。我个人因为要配置随机延迟,避免凌晨大量机器同时去上游同步,所以选择用timer。如果你也有多台同步机,建议参考这个写法:
ini复制# /etc/systemd/system/ubuntu-mirror-sync.service
[Unit]
Description=Sync Ubuntu Mirror
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/sync_ubuntu_mirror.sh
ini复制# /etc/systemd/system/ubuntu-mirror-sync.timer
[Unit]
Description=Run Ubuntu mirror sync daily at 3am
[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.target
Persistent=true 的意思很实用:如果凌晨3点机器正好关机或者宕机了,下次开机时会自动补跑一次同步。RandomizedDelaySec=300 是在3点基础上增加一个不超过300秒的随机延迟,避免多台机器同时连接上游导致触发限流。
启用方式:
bash复制systemctl daemon-reload
systemctl enable --now ubuntu-mirror-sync.timer
systemctl status ubuntu-mirror-sync.timer
4. 客户端源配置:从手动换源到deb822格式
源服务器那边就绪了,剩下就是客户端把apt源指过来。这里要特别提醒:Ubuntu 24.04开始,apt源配置从传统的 /etc/apt/sources.list 迁移到了 /etc/apt/sources.list.d/ubuntu.sources,格式也换成了deb822风格。这个变化让很多习惯了老版本的朋友栽了跟头,照着旧教程改 /etc/apt/sources.list 会发现文件是空的。
4.1 Ubuntu 24.04的deb822格式源配置
在24.04上配置本地源的正确方式,是直接修改 /etc/apt/sources.list.d/ubuntu.sources:
ini复制Types: deb
URIs: http://192.168.1.10/ubuntu
Suites: noble noble-updates noble-backports
Components: main restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
这里解释一下几个字段的含义:
Types: deb表示只同步二进制包,不需要源码包。如果同步机那边你保留了源码包,这里可以加一行deb-srcSuites对应dists目录下的发行版本代号。noble是基础发行版,noble-updates是更新仓库,noble-backports是向后移植的软件包Signed-By指向Ubuntu官方GPG公钥路径,用于校验Release文件的签名。这个比旧版用[trusted=yes]绕过签名校验要安全得多,建议不要偷懒跳过签名验证
安全更新源 noble-security 需要单独配。Ubuntu的security仓库不在主同步路径下,它在另一个独立的发布通道里。如果要同步security,需要在rsync命令中把对应路径加进去,或者在源配置中把security源依然指向公网。我的内网场景要求全量离线,所以 rsync 脚本里额外包含了 security 仓库的同步路径,客户端这边就多一行 noble-security,和上面结构类似,这里不重复贴。
4.2 传统sources.list格式(适用于20.04及更早版本)
如果你的内网还跑着Ubuntu 20.04或更老的版本,修改 /etc/apt/sources.list 才是正解:
bash复制deb http://192.168.1.10/ubuntu focal main restricted universe multiverse
deb http://192.168.1.10/ubuntu focal-updates main restricted universe multiverse
deb http://192.168.1.10/ubuntu focal-security main restricted universe multiverse
改完之后执行 apt update,如果能看到每个仓库的 Get 记录,且没有报错,就说明客户端指对了。
4.3 客户端换源的自动化脚本思路
几十台机器如果全手动改,肯定不现实。这里分享一个我在内网批量分发源配置时用的思路:直接把源文件放到一个内网HTTP路径下(比如 http://192.168.1.10/tools/ubuntu.sources),然后用一段脚本批量推送覆盖。
bash复制#!/bin/bash
# 批量推送源配置到内网所有Ubuntu 24.04节点
# 依赖: sshpass 或提前配置好的SSH免密登录
for host in $(cat /tmp/hosts_list.txt); do
echo "正在处理 $host ..."
ssh "$host" "cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak"
scp /data/conf/ubuntu.sources "$host:/etc/apt/sources.list.d/ubuntu.sources"
ssh "$host" "apt update" &
done
wait
echo "所有节点源配置已完成"
实际执行的时候,别一次性并发太多,建议10到20台一批。apt update 同时跑太多会把自己的Nginx服务器打满,别问我是怎么知道的。
5. 补充方案:ubuntu挂载ISO做临时本地源
上面讲的都是全量同步的正式方案,但有一个场景用它就太重了:新装了一台Ubuntu服务器,系统装完基本工具都没有,网卡驱动可能也有问题,想快速装个 openssh-server,结果apt源访问不了外网。这时候如果手边有一张Ubuntu安装ISO,挂载来做临时源是最快的应急方案。
5.1 ISO挂载与源配置实操
操作步骤如下:
bash复制# 1. 创建挂载点并挂载ISO
sudo mkdir -p /mnt/iso
sudo mount -o loop ubuntu-24.04.2-live-server-amd64.iso /mnt/iso
# 2. 查看ISO内目录结构,确认源路径
ls /mnt/iso
Ubuntu桌面版ISO和服务器版ISO的仓库路径不太一样。以24.04 server版为例,/mnt/iso 下会有 pool 和 dists 目录,直接就可以作为apt源使用。但需要注意,这个源里边的软件包只包含安装系统所需的最小子集,连 build-essential 都没有,装vim、curl这种常见软件多半会提示找不到包。
桌面板ISO通常还带 casper 和 /install 目录,仓库结构有时藏在 /mnt/iso 的父级或者嵌套路径中,需要自己 ls dists 确认一下。我试过最稳妥的方式是先挂载,然后进 dists 目录看里面是哪个发行版代号,再决定源配置。
bash复制# 3. 配置临时源(20.04及更早版本修改/etc/apt/sources.list)
deb file:///mnt/iso noble main restricted universe multiverse
deb822格式的24.04也是开一个文件指向file路径,这里不重复贴了。执行 apt update 就能看到本地源生效。用完记得卸载:
bash复制sudo umount /mnt/iso
5.2 ISO源和自建同步源的关系
ISO挂载的定位是“临时救急”,它解决的是“网络不通但手头有安装介质”的突发情况。而自建同步源解决的是“持续稳定提供内网软件分发”的长期问题。前者适合装机时用,后者适合服务器运行期日常用。两者并不冲突,我自己的做法是装机时把ISO源配置写到preseed或cloud-init里,装完系统立刻切到内网同步源。如果同步源已经积累了足够多的包,ISO源完全可以直接省略。
6. 常见故障排查与避坑实录
这部分是硬核干货区,拉长时间看,这套方案踩过的坑基本都集中在下面几个问题上。
6.1 apt update报错:Signature verification failed
这个报错几乎每个初搭源的人都会遇到。表现形式是 apt update 时提示 The following signatures couldn't be verified because the public key is not available。
原因通常有两种。第一种是客户端缺少Ubuntu官方GPG密钥:
bash复制# 安装ubuntu-keyring
sudo apt install ubuntu-keyring
# 或者手动下载密钥
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/ubuntu-archive-keyring.gpg --keyserver keyserver.ubuntu.com --recv-keys F6ECB3762478EDA9
第二种原因是源配置写成了 [trusted=yes] 绕过签名校验。这个做法虽然能消除报错,但同时也放弃了完整性校验,内网如果被中间人攻击或同步数据损坏,apt无法感知。不建议这么做。
6.2 rsync同步中断,日志里全是connection reset
排查这类问题,第一步先看上游是否限制了并发连接数。阿里云、清华这些大镜像站对单个IP的rsync并发数都有限制,超过限制就会直接reset连接。之前我在同一台机上同时跑了多个rsync进程(比如Ubuntu源和CentOS源同时同步),就经常遇到这个问题。
解决办法也很简单:
- 错开不同源的同步时间,比如Ubuntu定在凌晨3点,CentOS定在凌晨4点
- 或者在rsync脚本中加一个
--bwlimit=10000(单位是KB/s),把同步带宽限制在10MB/s左右,避免带宽跑满导致连接被重置
限制带宽后同步时间会变长,但稳定性显著改善。完整同步一次首次可能需要4到6个小时,增量同步在10分钟内能完成。对于每晚一次的任务,时间完全可接受。
6.3 apt update报错404 Not Found
这个问题通常不是Nginx配置错了,而是rsync同步还没跑完,客户端就去抓取索引文件了。尤其是首次全量同步时,dists 下面的Release和Packages索引文件在同步完成前是不完整的,此时如果有客户端执行 apt update,就会报各种404。
我在生产上用的规避手段有两个:
- Nginx发布目录不在同步目录本身上操作,而是同步完成后用
ln -s或mv切换软链接。比如真实数据在/data/mirror/ubuntu-rsync,同步完成后把/data/mirror/ubuntu这个软链接指向它 - 或者直接在同步脚本末尾调用
touch /data/mirror/ubuntu/.sync_complete,Nginx这边通过if (-f $document_root/.sync_complete)判断同步是否完成,未完成时直接返回一个维护页面
对于绝大多数内网场景,第一种方案更简单直观一些。
6.4 磁盘空间告警:pool目录无限膨胀
之前提到过我在同步命令里用了 --delete 参数,它会删除本地存在但上游已经不再拥有的文件。这个参数非常关键,不加的话,上游删除的旧版本软件包,在本地会一直保留,日积月累磁盘再大也不够用的。
但加了 --delete 也不是万事大吉。如果上游临时出现目录结构变更或同步故障,某些文件短暂消失,--delete 会“误伤”把这些本地文件删掉。为了防这种情况,我建议在rsync脚本中加入一个临时目录中转,而不是直接同步到正式目录:
bash复制rsync -avz --delete ... rsync://mirrors.aliyun.com/ubuntu/ /data/mirror/ubuntu-tmp/
# 同步完成后切换
rm -rf /data/mirror/ubuntu && mv /data/mirror/ubuntu-tmp /data/mirror/ubuntu
这个方法能让客户端永远只看到一个完整的仓库目录,不会有半截状态。代价是双倍磁盘空间,为了稳定性和完整性我觉得值得。
6.5 客户端报错:Failed to fetch ... Connection refused
排障思路按顺序从下往上查:
bash复制# 1. 先确认Nginx服务状态
systemctl status nginx
# 2. 确认防火墙放行80端口
ufw status
# 如果有防火墙,放行
ufw allow 80/tcp
# 3. 从客户端机器上测试HTTP连通性
curl -I http://192.168.1.10/ubuntu/dists/noble/Release
如果curl能通但是apt还是报Connection refused,检查一下apt是否配置了代理,内网有些机器 /etc/apt/apt.conf.d/ 下会残留外网代理配置。这问题我在排查时至少碰到过三次,每次都是花半天才发现是代理残留。
7. 实操过程记录与性能基准确认
下面结合我实际环境中一次完整的同步过程,给出这套方案的时间基线,方便你上线前做容量评估。
我的同步机配置是8核16GB内存、2TB HDD、千兆内网口,上游为阿里云镜像站,外网下行带宽约80Mbps(大致10MB/s)。
第一次全量同步,排除universe组件,累计同步数据量约340GB,耗时约7小时。增量同步阶段,通常每天的净增量在100MB到500MB之间,耗时基本在5分钟以内。如果当天上游有大规模版本更新(比如firefox、内核点版本),增量可能达到2GB左右,耗时约20分钟。
日志文件 /var/log/ubuntu-mirror-sync.log 中每天的增量大小和时间可以看到,建议每周检查一次,如果发现连续几天增量异常增大,去上游Release页面确认是不是官方仓库结构有所调整。
8. 一些实战心得与长期维护经验
最后分享几个经验,都是我在这套方案运行中慢慢积累出来的。
第一个建议是做好监控告警。我最初没加任何监控,结果同步脚本因为磁盘写满静默失败了三天,内网机器安装软件时才发现。血的教训,至少配置一个最简单的定时检查:
bash复制#!/bin/bash
# 检查同步时间戳,超过2天未同步则告警
LAST_SYNC=$(stat -c %Y /data/mirror/ubuntu/.sync_complete)
NOW=$(date +%s)
DIFF=$(( (NOW - LAST_SYNC) / 86400 ))
if [ "$DIFF" -gt 2 ]; then
echo "Ubuntu镜像源同步中断已超过48小时,请检查!" | mail -s "Mirror Sync Alert" ops@example.com
fi
这个配合crontab每小时跑一次,成本极低,收益非常明显。如果机器没有mail服务,也可以改成对接企业微信、钉钉机器人的webhook脚本,思路都是一样的。
第二个建议是定期做客户端源连通性验证。我从一堆节点里抽了3台代表性机器,每天在同步完成后自动跑一次 apt update,验证Nginx发布、索引文件完整性和GPG签名链路这几个环节是否正常。一旦发现问题,当天的定时同步刚跑完还热乎着,排查起来比隔几天容易得多。
第三个建议是关于logrotate。同步脚本会把日志写到 /var/log/ubuntu-mirror-sync.log,但日志轮转经常被忽略。rsync每次都带 -v 参数输出文件列表,第一次全量同步那个日志文件能到几十MB甚至上百MB。我给 /etc/logrotate.d/ubuntu-mirror 加了配置,保留7天,按天轮转,完美解决。
第四个建议是针对多版本Ubuntu混合环境的。如果你的内网同时存在20.04(focal)和24.04(noble)的机器,同步脚本里就不能只同步一个发行版本。需要在rsync源路径上把两个版本的 dists 和 pool 都配上。pool目录下不同发行版的软件包结构会有重叠,但apt源设计上其实已经兼容了多版本共存,只需在同一个根目录下同步多个 dists 即可,客户端各自指定自己的 Suites,各取所需,互不干扰。我目前线上是focal和noble两代并存,实际运行稳定。
这套方案跑起来之后,内网机器装包速度基本能达到千兆网卡的上限(磁盘IO够快的前提下),几十台机器同时 apt upgrade 也不会再卡脖子。如果你的环境也在被外网源的速度和稳定性困扰,不妨按着这条链路搭建起来,从rsync同步脚本到Nginx发布再到客户端配置,全过程半小时内能完成,之后就是长期受益的事。
