# MinIO 把 Docker Hub 仓库删了——但你的对象存储不必陪葬

LLMS 索引： [llms.txt](/llms.txt)

---

我先把一个日期钉在这儿：**2026 年 9 月 11 日**，UTC 时间 18:31 到 19:36 之间，MinIO 把 Docker Hub 上的 `minio/minio` 和 `minio/mc` 两个仓库，**直接删了**。

不是限流，不是换个 tag，是整个仓库返回 404——“repository does not exist”。

那天全世界的 CI 都在悄悄变红。我随手翻了翻 GitHub，各种项目[当天就炸出了 issue](https://github.com/shellhub-io/shellhub/issues/7117)：`docker compose up` 起不来，
报的是 `pull access denied for minio/minio, repository does not exist or may require 'docker login'`。很多人第一反应是自己登录失效了，翻来覆去查凭证——其实跟凭证一点关系没有：
Docker Hub 对“不存在的仓库”和“需要登录的私有仓库”返回的是同一句话，匿名用户根本分不清。有人查了半天才反应过来：不是我坏了，是上游没了。

有个荷兰开发者在自己项目的 [issue](https://github.com/cloudmarktplaats/cloudmarktplaats/issues/48) 里写得最干脆，我原样翻译过来：
五、六月 MinIO 把免费社区版的整个管理控制台砍成了残废；十月停止发布社区版的镜像和二进制，仓库挂上“不再维护”；
今年二月仓库正式归档；9 月 11 日，`minio/minio` 和 `minio/mc` 被彻底从 Docker Hub 抹掉——不是限流，就是没了。

我是老冯，Pigsty 的作者。**Silo，就是我维护的那个 MinIO 社区 fork。**

这篇不是 release notes。Release notes 我另外写了，一条一条列变更，那是给要升级的人对着看的。这篇是篇总结——讲讲过去这一个多月到底发生了什么，
为什么我要在两个前沿模型刚发布的节骨眼上，带着两个 AI 干了一场“漏洞大清理”，以及，为什么我觉得这事儿值。

## MinIO 是怎么一步步跑路的

要讲清楚 Silo 为什么存在，得先把 MinIO 这几年怎么把自己活活作死的时间线摆出来。这不是情绪，是有据可查的一串日期：

**2021 年**，MinIO 把核心服务器代码从宽松的 Apache 2.0 换成了限制性很强的 AGPLv3
（其实[2019 年就开始铺垫](https://bizety.com/2025/12/06/minio-in-maintenance-mode-open-source-alternatives/)）。当时社区就吵过一轮，
但大多数用户无所谓——反正我自己用、不对外提供服务，AGPL 和 Apache 对我没差别。真正的问题埋在后面。

**2025 年五六月**，MinIO 干了让社区最愤怒的一件事：把免费社区版的完整管理 Console 砍了，只留一个残缺的对象浏览器。用户管理、桶策略、访问控制、
生命周期管理——**一夜之间全没了**。想要回来？行，上企业版，一年大概十万美元起步。

最讽刺的是，我后来[把 Console 恢复回来](/db/minio-resurrect/)，**根本不需要逆向**。他们就是把 `minio/console` 的子模块版本往前一退、换了个依赖版本，
把完整 Console 换成了阉割版。我把那个依赖版本退回去，Console 就回来了。

**2025 年 10 月**，MinIO 停止为社区版发布预编译二进制和容器镜像，改成“只给源码”。你想用？自己编译去。

**2025 年 12 月 3 日**，MinIO 在 GitHub 上宣布社区版进入“维护模式”。README 说安全修复会“逐个评估”。我当时就写了篇《[MinIO 已死](/db/minio-is-dead/)》开喷。

**2026 年 2 月 12 日**，仓库状态从“维护模式”改成“不再维护”，然后正式归档，只读。一个 6 万 star、十亿+ Docker 拉取的项目，变成了一块数字墓碑。而就在那个归档的仓库里，
`SECURITY.md` 还写着一行字：“我们永远为最新版本提供安全更新。”

**2026 年 9 月 11 日**，删 Docker Hub 仓库。这是跑路的最后一步，也是最狠的一步——前面几步好歹还给你留了个念想：镜像虽然旧，但还能拉。这一步是连念想都没了。

这条线连起来看，是一个非常干净的商业设计：**归档仓库，这样就没有修补的义务；继续发 CVE 公告，保持“曝光度”；然后把所有读到公告的人，一股脑引导到商业版 AIStor。**
AIStor 按容量收费，$0.02/GB/月，400 TiB 以内适用企业自助支持层——据第三方评测，起步价大概九万六千美元一年。对，就是这么个“清爽”的安排。

那总得有人来修那个被抛弃的老版本吧。这个人就是我。

## 为什么是我，为什么用 AI

其实早在 2025 年 12 月 MinIO 宣布维护模式的时候，我就已经自己编好了打过 CVE 补丁的二进制，切过去用了。
**因为 Pigsty 自己在生产里用 MinIO 做 PostgreSQL 的备份仓库**——这不是“我想做个开源项目”，是“我依赖的东西坏了，我得修”。

一开始我很偷懒。点一下 Fork，把包编出来，名字都懒得改，仓库就叫 `pgsty/minio`。我一个人用的时候这没问题。但等到镜像拉取超过五十万次、
一堆知名开源项目开始把默认镜像指向我这儿的时候，这就不行了——MinIO® 是注册商标，开源许可证不授予商标权，我不能把这个隐患甩进别人的供应链。所以 8 月我做了件事：把项目、仓库、
二进制、所有面向品牌的表面，从 MinIO 全部重命名成 **[PGSTY SILO](/db/long-live-silo/)**，简称 Silo。在数据圈，silo（数据孤岛）通常是个骂人的词——我偏要拿它当名字。
谷仓 silo 摆在 Pigsty 猪圈旁边，再加上 pig 包管理器和 sow 仓库工具，一家人整整齐齐。

那么，一个人怎么维护一个中等规模的 Go 代码库、还要处理不断掉下来的高危 CVE？答案是 AI。但**绝不是**对着 AI 说一句“去把所有问题都解决掉”那么简单。

我在 4 月那篇《[续命 MinIO：承诺兑现](/db/minio-promise-kept/)》里写过当时的流程：Codex 起草，Claude Code 做对抗式 review。到了这一轮 8、9 月的大清理，模式升级了，
但内核没变——**两个异构的 AI Agent 相互对抗，我在上面做裁判。**

具体到这一个多月：9 月 1 日 Anthropic 发了 Claude Fable 5.1，9 月 3 日 OpenAI 发了 GPT-6 Astra。两个当时的顶级模型前后脚落地，
这是我决定动手做一轮大清理的直接契机——工具够硬了，很多以前“知道有问题但改起来风险太大”的深水区，现在可以碰了。

分工是这样的：**Astra 6 发布之前，大体是 Fable 操刀设计、Sol（GPT-5.6 Sol，通过 Codex 用）负责实现；Astra 6 发布之后，基本由 Astra 自己负责设计和实现，
Fable 转过来做核对和对抗性 review。** 你去翻 [Silo 的 commit 记录](https://github.com/pgsty/silo/commits/main)能看到痕迹：PR 的 co-author 里挂着 `Claude Opus 4.8`、
`Claude Fable 5.1`，PR 描述里有 “Codex Astra 6 (Max) adversarial review: VERDICT PASS” 这样的字样，
分支名带 `codex/` 前缀——比如修 SN-2026-011 那个未签名头漏洞的分支就叫 `codex/unsigned-amz-header-copy-20260909`。**每一个 AI 提交，
最后都带一行 `Signed-off-by: Feng Ruohang`。** 那是我。

为什么非要两个 Agent 互掐？因为我发现，单个 Agent 修安全漏洞，特别容易给你一个“听起来很有道理、但悄悄漏了一个边界条件”的补丁。它太自信了。
让第二个不同厂商的模型站在攻击者的角度专门挑它的刺，绝大多数这种“自信的漏洞”就被筛出来了。而且对抗会逼着它们把权衡写下来——当两个实现分叉的时候，
总得有一方说清楚“为什么选 A 不选 B”。这段争论，恰恰是我作为最终拍板的人唯一能真正拿来判断的东西。如果它们俩一拍即合、都不解释，那我反而慌。

我的角色，是**宏观把控、分歧调解、资源协调**。我不逐行看实现细节——那样我一个人根本扛不住。我定义问题、设约束、在两个方案里挑、读 diff、跑测试、决定合并还是打回去。
真正的维护从来不是“一击必杀”，而是“补丁摞补丁”。LDAP STS 那个限流修复就是典型：第一版落地后我们才意识到，成功的请求不该计入限流、`X-Forwarded-For` 默认不能信、
限流键得用“源 IP + 归一化用户名”而不是单一维度——前后三个跟进 commit 才算稳。这种活儿要是纯手工一轮轮磨，时间成本高得离谱。

【待补：这一轮大清理里，有一次 Astra 和 Fable 在某个具体修复上僵住、我出面调解的真实细节，可在此补一个有画面感的小故事。】

## 这一个多月，到底修了什么

好，讲点硬的。

从 8 月初到 9 月 17 日，我发了**四个服务器版本**：08-04、08-06、09-03、09-16。光是最后的 [09-16 版](https://silo.pgsty.com/blog/release/silo-20260916/)，
单次就吞了 **210 个提交（其中 140 个非合并提交）**。

安全这块，把 4 月以来的账一起算：**8 个 CVE + 十来个 SN 项目本地条目**，官网口径是“14 个安全修复、17 条安全说明”。这些**全部继承自已归档的上游 MinIO**——也就是说，
这些洞在 MinIO 社区版里**永远不会被修**，官方只会让你去买 AIStor。挑几个说说它们有多离谱：

- **CVE-2026-33322，OIDC JWT 算法混淆，CVSS 9.8。** 在某些身份提供商配置下，一个知道 OIDC ClientSecret 的攻击者，
  可以伪造一个声称自己是任意身份——包括 `consoleAdmin` 超管——的令牌，而 MinIO 会照单全收。这个洞的脆弱窗口从 2022 年 11 月一直开到 2026 年 3 月，**大约三年半**。
- **CVE-2026-34204，复制头元数据注入。** 一个普通的 PUT 或 COPY 请求，带上特定的 `X-Minio-Replication-*` 头，
  就能把一个对象写成**永久不可读**的状态。数据还在盘上，你就是读不出来。
- **两个签名验证绕过（CVE-2026-40344 / CVE-2026-41145）。** unsigned-trailer 路径上的匿名或伪造签名请求，能在某些路由上成功写对象。这俩只有 GHSA 编号、
  没有公开的 CVSS 数字，但性质是 critical 级的。
- **CVE-2026-42600，ReadMultiple 存储层路径穿越。** 这个更值得一说——我们一开始只是删了那个没人用的内部端点，就宣布“修好了”。后来做审计才发现，端点是删了，
  **根本病因还在另外三个协议面上活着**：请求体和 grid 帧从不经过校验中间件，存储层也没有围栏。
  于是有了 [SN-2026-002](https://github.com/pgsty/silo/blob/main/docs/security/advisories.md)，把剩下的账还清：路径和卷两个维度的穿越、一个每帧就能弄崩一个节点的除零 panic、
  把截断分片误报成完整的元数据、三处按调用方声明值分配的内存……**12 个缺陷，全是从上游继承的，我们的 diff 在受影响文件上是纯删除、零新增行。**
  这个教训我[专门写了篇复盘](https://silo.pgsty.com/blog/security/cve-2026-42600/)：修一个端点，不等于关掉一整类漏洞；当你决定把下面那层先不管，一定要写在下一个人会绊到的地方。

9 月这轮还落地了一批更硬核的：**持久化 IAM 吊销**（保留删除修订和父级吊销边界，让旧凭证没法越过吊销历史复活）、**多池对象一致性**（条件 PUT、分片完成、
条件 DELETE 在共享命名空间锁下评估同一个逻辑对象）、**加密与联邦复制的一整套修复**（原样保存 SSE-C 密文副本、保留分片明文长度、正确处理 Object Lock 头）。

而且有几个洞是**用户报给我们的**，这点我要特别点名感谢：SN-2026-011 那个未签名 `x-amz-*` 头的问题，
是 Oren Yomtov（@orenyomtov）私下报告的——防的是一个签名 PUT 被偷换成带签名者权限的 CopyObject；Console 匿名分享代理的问题是 jiri-pejchal 报的；
慢 HTTP 拒绝服务是 @AEGEGE（issue #183）报的；CPU 指标并发读崩溃是 @aschyolkin（issue #210）报的。

除了安全，还有一大堆上游遗留的非安全缺陷被顺手清了，很多是**兼容性和默认行为的权衡**，这里能看出我做这事儿的分寸：

- **客户端来源地址可信性**，我做成了**需要显式开启**的加固。上游那套 `X-Forwarded-For` / `X-Real-IP` / RFC 7239 `Forwarded` 三个头都能被伪造的问题确实存在，
  但我新增了 `MINIO_API_TRUSTED_PROXIES` 这个显式信任配置——**不设置就完全保持上游行为**。为什么？一旦默认改了，所有在反向代理后面跑的存量部署都可能被打断。
  这种加固，我宁可让你主动打开，也不替你做决定。
- **distroless 镜像变体**：单文件、128MB（经典镜像是 199MB），内置 HEALTHCHECK，`/data` 层内可写。但我**没有**直接去瘦身经典镜像——经典镜像的内容本身是一个兼容性表面，
  之前上游就是在这个表面下偷偷改东西把大家坑过。所以 distroless 是一个**新名字、新契约**，谁的现有 healthcheck、
  `docker exec mc` 习惯[都不会被打断](https://silo.pgsty.com/compatibility/feature/healthcheck/)。
- **原生 `silo healthcheck` 子命令**：容器里不再需要 shell、curl 或 mc 来做探针。
- 还有 `mc watch`、桶通知、S3 Select keep-alive 的流式刷新回归修复，逐桶 CORS 落地，桶元数据串行化（一把 `metadata.lock` 防止并发写互相覆盖），缺桶时正确返回 `NoSuchBucket`……

还有一个我想强调的取舍：**外部贡献者的 PR，我不是照单全收。** 比如那个 CPU 指标竞态的修复，@mrjavadseydi 提了 [PR #215](https://github.com/pgsty/silo/pull/215)，锁改得是对的、
回归测试也能复现问题，但我已经在主线 #214 里用自研方案实现了同样的修复，就把他的 PR 作为 superseded 关闭了——同时在贡献者致谢里认了他的功劳。**关掉一个 PR 不等于否定贡献；
采用哪个方案，是维护者要负责的技术判断。** 这一个多月，一共有 **50 位社区贡献者**（49 位人类 issue/PR 作者 + 单独致谢的安全报告者 Oren Yomtov）参与进来，
外部合并的代码 PR 涵盖 go-jose/OpenTelemetry 依赖 CVE、桶通知流、逐桶 CORS、联邦 CopyObject legalhold、multipart ChecksumType 等等。**这早就不是我一个人的项目了。**

兼容性方面，[官方 compatibility 页面](https://silo.pgsty.com/compatibility/)把 Silo 相对 MinIO 的差异梳理成 **12 项兼容性改进、4 项细微差异、8 项条件性检查**，共 24 类，
比较基线是上游 2025-12-03 那版源码。我得诚实地补一句：这 24 类是**按用户场景分的，不是兼容率百分比**——我不想给你一个“99.x% 兼容”的漂亮数字然后让你踩坑。
能给的硬证据是内部验收：`make verify` 覆盖 FS、纠删码、分布式纠删码、多池、IPv6 多池，**174 PASS / 0 FAIL**；
[四节点 TLS 集群](https://silo.pgsty.com/blog/release/silo-20260903/)做过 1004 对对象的上传下载校验和逐一对比、双站点复制、单盘重建、完整回滚演练。

## 这事儿到底花了多少，值不值

说实话，花了不少。

这**绝不是**对 AI 喊一句“go and fetch 所有问题去解决”就行的事。它涉及大量的利弊权衡：哪些洞现在修、哪些留着；默认行为要不要改、改了会不会打断存量部署；兼容性的边界画在哪里；
一个外部 PR 是收编还是自研替换。这些判断，AI 给不了我，只能我来拍。

我手上有 **15 个 AI 订阅**。这一个多月的 Silo 大清理，大概**吃掉了其中 3 个 200 美元订阅的全部额度**，再加上我相当可观的一段人工时间。
（我在[别处的博文](/ai/yield-with-agents/)里给过一些不同口径的数字——“维持 7 个 200 美元订阅、烧掉一千亿多 token”“某一天烧掉 4 个 20 倍订阅”之类——不同时间段、不同算法，
别较真精确值，量级感受一下就好：**一个人 + 一堆顶配 AI 订阅 + 大量夜晚**。）

但我觉得这确实是一件很有意义的事。

意义在哪？在于 2026 年，“我来修”这句话的成本变了。放在一两年前，一个人想扛下一个中等规模 Go 代码库的安全维护——跟着 CVE 跑、写补丁、做对抗审计、
保住供应链——基本是天方夜谭。现在有了两个能互相拆台的编码 Agent，加上一个愿意在中间当裁判、做取舍的人，这件事**变得可行了**。
这不是什么关于开源韧性的宏大理论，就是当下一个很具体的操作点。

而且它托住了很多真实的部署。[Pigsty v4.5](https://pigsty.io/blog/pigsty/v4.5/) 已经把对象存储模块整个切到了 Silo，`minio_type` 现在只接受 `silo` 这一个值。
外面 RAGFlow 的默认 Compose、Dokploy 的产品模板、Grafana Loki 的 Helm chart、Dell 的 Omnia HPC 平台、nixpkgs、DaoCloud 镜像……几十个项目已经把默认镜像指向了我这儿。
这个应急 fork，某种意义上已经成了**最活跃、最显眼的那个 MinIO 分支**。

## 如果你还在跑 MinIO

结论很简单：**MinIO 跑路了，9 月 11 日删 Docker Hub 仓库是最新、也最决绝的一步。而你可以换成 Silo。**

Silo 的定位从第一天起就没变过，就一条规矩：**产品和交付表面全部重命名，协议和你的数据一个字不动。** `silo` 二进制、包、systemd 服务、Helm chart、容器镜像换了名字；
但 S3 和 Admin API、`MINIO_*` 环境变量、`minio_*` 指标、`x-minio-*` 头、`/minio/*` 路由、`.minio.sys` 磁盘格式——全部原样保留，而且有 CI 兼容性检查钉死。

这就是我给存量 MinIO 部署的承诺：**不动你的数据，持续修漏洞，持续出镜像，保持接口兼容。** [官网](https://silo.pgsty.com/)那句标语我一直很喜欢：

> **S3 Interface, Libre Object Store. Keep the interface. Own the objects.**
>
> 保住接口，掌控你自己的数据。

[迁移](https://silo.pgsty.com/compatibility/migration/)很便宜。Docker 用户把 `minio/minio` 换成 `pgsty/silo` 就行，卷不用动、数据不用动、API 不用重学；
容器入口还会翻译遗留的 `minio` 参数（[有人真的这么干了](https://github.com/ShyME/Pictogram/pull/245)），连 `command: minio server /data` 都能继续跑。
RPM/DEB 在 [GitHub Releases](https://github.com/pgsty/silo/releases) 上有，或者用 `pig` 装。想要一套现成的 HA 生产部署，[Pigsty](https://pigsty.io/) 免费给你一套。

我用的东西坏了，我在修它。就这么回事。下一个 CVE 掉下来的时候，我还在。
