使用 apt-p2p 搭建本地 Debian 软件包缓存

jopen 9年前

本人家里有好几台运行Debian GNU/Linux testing的计算机,共处于一个小局域网内。因为Debian testing是滚动更新的,所以我每隔几天就要把它们全部更新一遍。但是一来中国家庭的网速还是说不上很快,每台机器都要从上游软件源的服务器上下载成百上千兆字节的软件包要花不少时间;二来这样操作也给软件源的服务器造成不小的负担。

使用 apt-p2p 搭建本地 Debian 软件包缓存

后来我想起Debian曾开发过一个叫apt-p2p的软件,它的设计初衷是缓存已下载的软件包提供给其他同样运行着apt-p2p的peers,作为从软件源下载的补充。那么是否可以用这个软件在局域网内搭建一个Debian软件包缓存呢?

apt-p2p由Python写成,安装好后默认监听于TCP和UDP的9977端口,可通过/etc/apt-p2p/apt-p2p.conf改变其行为。TCP端口同时用于本机apt下载软件包,而UDP端口用于组建在p2p文件共享工具中常见的DHT网络。只需要在/etc/apt/sources.list文件中软件源的url,例如http://mirror.server/debian/的服务器域名前面插入localhost:9977,即成为http://localhost:9977/mirror.server/debian/,具体从互联网上获取软件包的工作便交给apt-p2p负责了:

  • 当收到来自本机apt的文件下载请求时,apt-p2p会先检测文件是否已经存在于缓存的目录树中
    • 如果已存在,则还要检查是否为最新(通过向软件源服务器发出HEAD请求来实现)
      • 如果是,则直接返回缓存的文件
      • 否则从互联网上下载文件供给apt,同时存入缓存并记录其散列值
  • 下载文件会首先尝试从peer处下载,不成再到软件源服务器处下载
  • 缓存下来的文件和散列值可供其他peer使用。可以通过apt-p2p的日志文件/var/log/apt-p2p.log深入观测这一过程。

以下是我安装了apt-p2p的主机mycastle的sources.list:

deb http://localhost:9977/mirrors.ustc.edu.cn/debian/ testing main  deb-src http://localhost:9977/mirrors.ustc.edu.cn/debian/ testing main    deb http://localhost:9977/mirrors.ustc.edu.cn/debian-security/ testing/updates main  deb-src http://localhost:9977/mirrors.ustc.edu.cn/debian-security testing/updates main    deb http://localhost:9977/mirrors.ustc.edu.cn/debian/ testing-proposed-updates main  deb-src http://localhost:9977/mirrors.ustc.edu.cn/debian/ testing-proposed-updates main    deb http://localhost:9977/mirrors.ustc.edu.cn/debian/ unstable main  deb-src http://localhost:9977/mirrors.ustc.edu.cn/debian/ unstable main

然而apt-p2p的缓存只能给本机使用,其他主机若试图直接访问9977端口只会得到404错误。因此还需要在安装apt-p2p的主机上架设一个http反向代理,使得在apt-p2p看来,所有的请求均来自本机。

我使用的反向代理是Pound,它在安装好后默认是禁用的。在/etc/pound/pound.cfg中配置好服务器后再到/etc/default/pound中启用它,然后使用service启动服务器即可。

我使用的配置如下:

...(keep default)  ListenHTTP      Address 0.0.0.0      Port    9978      ## allow PUT and DELETE also (by default only GET, POST and HEAD)?:      xHTTP       0      Service          BackEnd              Address 127.0.0.1              Port    9977          End      End  End

监听于9978端口,后台服务器在本机的9977端口。

这样一来,其他主机便也可以通过9978端口使用apt-p2p的缓存了。我的做法是在打算使用缓存的其他主机上将/etc/apt/sources.list移动到/etc/apt/sources.list.d/50_main.list,然后仿照缓存主机的软件源列表建立/etc/apt/sources.list.d/10_apt-p2p-home.list,只是要把url中的localhost:9977换成<hostname-of-cache-server>.local:9978即可,当然最好保持软件源服务器相同。这样apt会优先通过反向代理使用apt-p2p的缓存,当缓存不可用时仍可直接连接软件源服务器获取软件包:

10_apt-p2p-home.list:

deb http://mycastle.local:9978/mirrors.ustc.edu.cn/debian/ testing main  deb-src http://mycastle.local:9978/mirrors.ustc.edu.cn/debian/ testing main    deb http://mycastle.local:9978/mirrors.ustc.edu.cn/debian-security/ testing/updates main  deb-src http://mycastle.local:9978/mirrors.ustc.edu.cn/debian-security testing/updates main    deb http://mycastle.local:9978/mirrors.ustc.edu.cn/debian/ testing-proposed-updates main  deb-src http://mycastle.local:9978/mirrors.ustc.edu.cn/debian/ testing-proposed-updates main    deb http://mycastle.local:9978/mirrors.ustc.edu.cn/debian/ unstable main  deb-src http://mycastle.local:9978/mirrors.ustc.edu.cn/debian/ unstable main

50_main.list:

deb http://mirrors.ustc.edu.cn/debian/ testing main  deb-src http://mirrors.ustc.edu.cn/debian/ testing main    deb http://mirrors.ustc.edu.cn/debian-security/ testing/updates main  deb-src http://mirrors.ustc.edu.cn/debian-security testing/updates main    deb http://mirrors.ustc.edu.cn/debian/ testing-proposed-updates main  deb-src http://mirrors.ustc.edu.cn/debian/ testing-proposed-updates main    deb http://mirrors.ustc.edu.cn/debian/ unstable main  deb-src http://mirrors.ustc.edu.cn/debian/ unstable main

如安装了apt-transport-https,可以将50_main.list中的http换成https。

这种以主机名加“.local”的域名格式是mDNS/DNS-SD协议提供的一种在广播域内定位主机和发布服务的方法,主要实现有Avahi和Mac OS X的Bonjour

这样一来,在局域网内,任何一台主机都优先通过apt-p2p获取软件包,一台更新可以惠及全家;即使短时间内更新多台主机,也只需要向软件源索取一次;而且大规模的数据流动发生在带宽很高的局域网内,更缩短了更新时间,提高了效率。

只是这样一来相当于在非缓存主机上配置了两个软件源,而当这两个软件源重复部分的信息不同步时(如笔记本计算机在局域网外更新了直连软件源服务器的软件包列表),apt-get source是无法使用的,因为apt对源码包的检查更严格。