发布于 

自建 ZCode 内部 mirror:mirrors.changediff.top 与 apt 源落地记录

最近把 ZCode 的安装方式从「人工下载 + dpkg -i」改成了内部镜像源。这篇记录整个方案、踩过的四个坑,以及最后的使用配置指南。

背景:为什么要自己搭 mirror

ZCode(智谱 Z.AI 的 IDE 产品)官方的分发方式对国内用户不太友好:

  • 官网下载页 https://zcode.z.ai 只宣传 AppImage
  • 真实 CDN 在 https://cdn-zcode.z.ai/zcode/electron/releases/<版本>/linux-x64/,同目录下其实有 deb / rpm,但页面没写
  • 国内直连 CDN 慢,且没有 apt 源

对内部开发机来说,每次升级都要人工去 CDN 找版本号、下载、dpkg -i。既然公网服务器上已经有 nginx + certbot 和站点,顺手加一个 mirror 是最自然的做法。

方案

在一台公网服务器上用 nginx 搭内部镜像,内网开发机通过 apt 源安装/升级。

组件 说明
域名 mirrors.changediff.top
站点根 独立静态目录,与博客站点同级
包目录 zcode/debzcode/rpm
索引 deb 用 Flat Repository(Packages + Release);rpm 仅存文件,无 repodata
更新 每日定时同步官方最近 3 个版本
管理 全部由 Ansible playbook 管理(部署、同步脚本、nginx 模板、证书 SAN)

保留策略

只保留官方最近 3 个版本的 deb + rpm,不存 AppImage。当前是 3.14.1 / 3.14.0 / 3.12.3,旧版本由同步脚本的 KEEP=3 自动清理。

版本发现方式是抓官方 changelog 页面,正则取版本号后按语义版本降序排前 3。

索引页

访问 https://mirrors.changediff.top/zcode/ 会看到一个自动生成的 HTML 索引页,列出当前所有可下载文件、最新版本号和最近同步时间:

1
2
3
4
5
6
7
8
9
10
ZCode Mirror (mirrors.changediff.top/zcode)
最新版本: 3.14.1 · 保留最近 3 个版本 · 更新于 2026-09-22 03:17:01
deb:
ZCode-3.14.1-linux-x64.deb
ZCode-3.14.0-linux-x64.deb
ZCode-3.12.3-linux-x64.deb
rpm:
ZCode-3.14.1-linux-x64.rpm
ZCode-3.14.0-linux-x64.rpm
ZCode-3.12.3-linux-x64.rpm

注意:rpm 目录只存放原始文件,没有生成 repodata,所以 yum/dnf 暂时不能把它当仓库用,只能 curl -O 直接下载后 rpm -ivhdnf install ./xxx.rpm。deb 则是完整的 flat repository,可以直接 apt install

四个坑

1. 证书签发顺序:先建 nginx 站点,再扩 SAN

首次 certbot certonly --expand 报 404:

1
Detail: Invalid response from https://mirrors.changediff.top/.well-known/acme-challenge/xxx: 404

原因:mirrors.changediff.top 的 server 块还不存在时,这个域名的 HTTP 请求落到 nginx 的 default_serverreturn 444),ACME 挑战文件写下去了也取不到。

正确顺序:先建 nginx 站点并 reload,跑 certbot。playbook 里用 meta: flush_handlers 保证 reload 先发生。

2. certbot 的 webroot 必须是主站目录

换对顺序后仍然 404,因为用了 mirror 自己的 root 作 webroot——mirror 站点没有 acme-challenge location,挑战文件放进去同样取不到。

最终生效的命令用了主站点的 webroot

1
2
3
4
certbot certonly --webroot -w /var/www/<主站目录> \
--cert-name changediff.top --expand --non-interactive \
-d changediff.top -d www.changediff.top \
-d mirrors.changediff.top

mirrors.changediff.top 进 SAN,与主站共用同一张证书。

3. Flat Repository 必须生成 Packages 索引

一开始只把 deb 丢进目录就配 apt 源,结果报错:

1
E: The repository 'https://mirrors.changediff.top/zcode/deb ./' does not have a Release file.

deb 目录需要 dpkg-scanpackages 生成的 Packages 索引。装 dpkg-dev 提供该工具。

4. Release 的 checksum 段不能混算法

第一版脚本把 md5 和 sha256 都写进了 MD5Sum: 段,apt 报:

1
W: 无法鉴别的 .../Release: 无哈希条目

正确写法MD5Sum: 段只放 md5 行,SHA256: 段只放 sha256 行,各自独立。索引脚本里用 Python 分段生成。

线上现在的 Release 长这样,两种算法各自独立成段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Origin: mirrors.changediff.top
Label: ZCode Mirror
Suite: ./
Codename: zcode
Architectures: amd64
Components: main
Description: Internal ZCode deb mirror (latest 3 versions)
Date: Mon, 21 Sep 2026 19:17:07 UTC
MD5Sum:
a4947426b3bd48ca8066d2fca5d9998e 1857 Packages
335b159a03f0d1f355ac9b8e244f31dd 682 Packages.gz
8784a8f8c246bc3fe24b74cfe68a1a9f 732 Packages.xz
SHA256:
b33c4900c2ff14472a3706d388613ebb817dd3ae48871d1eed093e1253a23b61 1857 Packages
063e0ce696f127f438845111b4b4f5b46b8d435e17a49938c11f2bca8d76d70f 682 Packages.gz
3ff9299a85ad82ecb1612e6df35e5aeb7f5142dc578762dd0278823fb861eace 732 Packages.xz

小结

四个坑里有三个都指向同一个教训:nginx 站点结构(default_server、location、webroot)会直接影响 ACME 和 apt 客户端的行为,搭 mirror 时不能只想着「文件放进目录就行」。


📖 mirrors.changediff.top 使用配置指南

这一节是给使用者的:怎么在自己的机器上把 ZCode 的安装和升级接到这个 mirror 上。

一、Ubuntu / Debian(apt 源)

实测状态(2026-09-22):在客户端上完整验证过——apt update 正常拉取索引,apt install --only-upgrade 将 zcode 从 3.12.3-7463 成功升级到 3.14.1-7714,162 MB 安装包下载速度约 430 KB/s,升级后二进制可正常启动并注册 zcode:// 协议。下面的步骤是照抄可用的。

1. 添加软件源

一条命令,写进 /etc/apt/sources.list.d/zcode-mirror.list

1
2
echo "deb [trusted=yes] https://mirrors.changediff.top/zcode/deb ./" \
| sudo tee /etc/apt/sources.list.d/zcode-mirror.list

这里用的是 Flat Repository 形式(./ 指向源根目录下的 Packages),不需要 signed-by、不需要导入 GPG key。[trusted=yes] 表示跳过签名校验——内网自用场景可以接受,但如果这个源将来对公网开放,务必换成 GPG 签名

2. 更新索引并安装

1
2
sudo apt update
sudo apt install zcode

第一次装完验证一下版本:

1
zcode --version

3. 升级

mirror 每天自动同步官方最新版,所以你只需要:

1
sudo apt update && sudo apt upgrade

4. 常见问题

Q:apt update 后看不到 zcode?
检查索引是否真的拉下来了:

1
curl -s https://mirrors.changediff.top/zcode/deb/Packages | grep -E "^(Package|Version):"

有输出说明源是好的,问题在客户端(apt update 没成功/域名解析)。没有输出则是服务端同步挂了。

Q:依赖装不上?
ZCode 的 deb 依赖 GTK 相关库,都是 Ubuntu 官方源里有的包,不需要额外配置:

1
2
libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils,
libatspi2.0-0, libuuid1, libsecret-1-0

Q:想锁定某个版本不升级?

1
2
sudo apt-mark hold zcode    # 锁定
sudo apt-mark unhold zcode # 解锁

二、RHEL / Rocky / Fedora(rpm)

目前 rpm 目录没有 repodata,只能直接下载安装:

1
2
3
4
5
6
7
# 下载
curl -L -o zcode.rpm https://mirrors.changediff.top/zcode/rpm/ZCode-3.14.1-linux-x64.rpm

# 安装
sudo dnf install ./zcode.rpm
# 或者
sudo rpm -ivh zcode.rpm

升级时把版本号换成新的,重新走一遍即可。如果后续需要 yum/dnf 仓库形式,服务端补一个 createrepo_c 生成 repodata 就行——目前没做的原因是内部只有 deb 客户端。

三、直接下载(任何平台)

不想配源,直接拿文件也完全可以。索引页 https://mirrors.changediff.top/zcode/ 会列出当前所有可用文件和版本:

1
2
3
4
5
6
# 最新版 deb
curl -LO https://mirrors.changediff.top/zcode/deb/ZCode-3.14.1-linux-x64.deb
sudo dpkg -i ZCode-3.14.1-linux-x64.deb

# 最新版 rpm
curl -LO https://mirrors.changediff.top/zcode/rpm/ZCode-3.14.1-linux-x64.rpm

四、列出当前所有可用版本

1
2
3
4
5
# deb 源索引(机器可读)
curl -s https://mirrors.changediff.top/zcode/deb/Packages

# 索引页(人类可读)
curl -s https://mirrors.changediff.top/zcode/

目前固定保留最近 3 个版本,所以任何时候 Packages 里最多三条记录。需要更老版本的话,回官方 CDN 下载:

1
curl -LO https://cdn-zcode.z.ai/zcode/electron/releases/<版本>/linux-x64/ZCode-<版本>-linux-x64.deb

🔬 实测记录(2026-09-22)

所有结论都在一台真实客户端上跑过,不是纸上谈兵。

环境

  • 客户端:Debian GNU/Linux 13,amd64
  • 安装前版本:zcode 3.12.3-7463
  • mirror 端当时版本:3.14.1 / 3.14.0 / 3.12.3

1. apt update 拉取索引

1
2
3
Ign:3 https://mirrors.changediff.top/zcode/deb ./ InRelease
Hit:4 https://mirrors.changediff.top/zcode/deb ./ Release
Ign:6 https://mirrors.changediff.top/zcode/deb ./ Release.gpg

InReleaseRelease.gpg 显示 Ign预期的——flat repository 没有 GPG 签名,配合 [trusted=yes] 使用。看到 Hit + 618 字节的 Release 被拉下来,索引链路就是通的。

2. 版本解析

1
2
3
4
5
6
7
8
9
10
11
12
$ apt-cache policy zcode
zcode:
Installed: 3.12.3-7463
Candidate: 3.14.1-7714
Version table:
3.14.1-7714 500
500 https://mirrors.changediff.top/zcode/deb ./ Packages
3.14.0-7681 500
500 https://mirrors.changediff.top/zcode/deb ./ Packages
*** 3.12.3-7463 500
500 https://mirrors.changediff.top/zcode/deb ./ Packages
100 /var/lib/dpkg/status

三个版本全部可见,Candidate 正确指向最新版 3.14.1。

3. 真实升级

1
2
3
4
5
6
7
8
9
10
$ sudo apt-get install -y --only-upgrade zcode
Preparing to unpack .../zcode_3.14.1-7714_amd64.deb ...
Unpacking zcode (3.14.1-7714) over (3.12.3-7463) ...
Setting up zcode (3.14.1-7714) ...
Processing triggers for hicolor-icon-theme (0.18-2) ...
Processing triggers for mailcap (3.74) ...
Processing triggers for desktop-file-utils (0.28-1) ...

$ dpkg -l zcode | tail -1
ii zcode 3.14.1-7714 amd64

162 MB 的包完整下载、解包、配置,触发器全部正常。

4. 二进制启动验证

升级不是终点,能跑起来才算数:

1
2
[2026-09-22 16:17:28.281] [main] [crash-capture] configured remoteCrashReporterEnabled=true
[2026-09-22 16:17:28.389] [main] [deep-link] 注册协议成功 { scheme: 'zcode' }

zcode:// 协议注册成功,说明 Electron 应用的启动流程完整走通了。

5. 下载速度

从客户端 Range 请求 5 MB 测得:

文件 HTTP 速度
deb/ZCode-3.14.1-linux-x64.deb 206 Partial Content ~432 KB/s
rpm/ZCode-3.14.1-linux-x64.rpm 206 Partial Content ~405 KB/s

Range(206)正常工作意味着 apt 的断点续传能力可用——162 MB 的包中途断线可以续传,不用重下。

6. 顺手修掉的两个问题

这次复查还发现并修了两处:

  • 索引页泄漏内部主机名mirrors.changediff.top/zcode/ 的页面文案里印死了客户端主机名(用法: ... 之前写的是具体主机名)。这个页面是公网可访问的,已改为中性的「用法」。
  • 文件属主不一致:早期从 root 下载的 rpm 包属 root:root,而 deb 包和索引是 www-data:www-data。已统一修正,同步脚本增加 chown -R 兜底防止复发。

结论

deb 链路(添加源 → apt update → 版本解析 → 下载升级 → 二进制启动)全流程通过。rpm 文件可直接下载安装,但因没有 repodata,dnf/yum 暂不能当仓库用。