代理订阅刚开始用的时候,事情通常很简单。
服务商给你一条链接,复制,粘贴,客户端里点一下更新。几秒钟以后,一排节点整整齐齐地出现了。看上去这件事已经结束,甚至没有什么值得管理的。
后来设备多了,客户端也多了。
电脑上用 Mihomo,手机上可能是 Shadowrocket、Loon 或 Quantumult X;手里有两三份订阅,有的节点名称很长,有的地区标识不统一,还有几条测试节点总在列表里晃来晃去。每换一个客户端,就要重新导入、重新筛选、重新整理一遍。
链接没有变多到不可收拾,麻烦却一点点长了出来。
这时候,Sub-Store 就有用了。
Sub-Store 是一个开源的高级订阅管理工具。
它位于“上游订阅”和“代理客户端”之间,负责把原始订阅收进来,经过解析、合并、过滤、重命名、排序和格式转换,再生成适合不同客户端使用的新订阅。
可以把它理解成一条配置流水线:
上游订阅 / 手动节点
↓
Sub-Store
解析、清洗、组合、加工
↓
Mihomo / Surge / Loon / Stash
sing-box / Shadowrocket / QX ...它做的是配置管理,不是网络连接。
因此,Sub-Store:
它只是把原来散落在各处的订阅配置,收拾得更适合你使用。
这有点像机柜里的理线架。它不会提升交换机的带宽,但线一旦多起来,没有它还真不太行。
如果你只有一份订阅、一个客户端,而且上游给出的格式刚好能直接使用,那么最省事的办法仍然是:直接导入。
没有必要为了管理一根线,先买一个机柜。
Sub-Store 真正解决的是订阅规模变大以后出现的几类问题。
代理工具的生态很丰富,配置格式也没有完全统一。
同一份节点数据,在 Mihomo、Surge、Loon、Quantumult X、sing-box 等客户端里,可能需要不同的字段、语法和输出结构。过去常见的做法是为每个客户端分别寻找转换链接,或者手工维护多份配置。
Sub-Store 可以把一份上游数据转换为多个目标格式。
根据项目当前的官方说明,它支持 Plain JSON、Mihomo、Surge、Surge Mac、Loon、Stash、Egern、Shadowrocket、Quantumult X、sing-box、V2Ray 等多种输出目标。[1]
上游只有一份,下游可以各取所需。
订阅一多,客户端里的更新按钮也会跟着变多。
你可能希望把:
组合成一个统一入口。
Sub-Store 可以把多个订阅放进一个组合中,最后对外生成一条新的订阅链接。客户端不再关心后面有多少来源,只需要更新这个入口。
上游节点名称通常是为“大多数用户”准备的,不一定符合你的习惯。
常见情况包括:
Sub-Store 提供过滤、重命名、排序、去重和属性设置等操作。你可以先把原始数据整理成自己的命名规范,再交给客户端。
真正省下来的不是一次改名的时间,而是以后每次更新都不必重新改。
如果每台设备都在本地维护一套筛选规则,时间长了,它们一定会慢慢长成不同的样子。
电脑上删过一条,手机上忘了删;平板使用新的命名方式,旧手机还保留着两个月前的排序。单看都能用,放在一起却像三个版本的自己。
Sub-Store 把这些处理规则集中起来。设备只负责读取结果,不再各自加工原始数据。
第一次打开 Sub-Store,界面里的名词可能会让人稍微停顿一下。其实它的模型并不复杂。
“订阅”可以理解为一个上游数据源。
它可能是一条远程订阅 URL,也可能是你手动录入的节点。Sub-Store 会读取并解析这些内容,形成后续可以处理的节点列表。
订阅对象主要回答一个问题:
数据从哪里来?
“组合”负责把多个订阅或节点集合并起来。
例如,你可以建立:
Daily:日常使用的主要订阅;Backup:备用来源;Mobile:只保留适合移动设备的节点;All:合并全部来源,用于统一备份。组合主要回答:
这次要拿哪些数据?
操作是 Sub-Store 最有价值的部分之一。
常见处理包括:
这些操作通常会按照顺序依次执行,因此顺序很重要。
例如:
读取三份订阅
→ 删除“到期提醒”和“官网地址”
→ 只保留香港、日本、新加坡节点
→ 统一地区名称
→ 删除重复项
→ 按地区排序
→ 输出为 Mihomo 格式这已经不只是“订阅转换”,而是一条小型的数据处理管道。
处理完成后,Sub-Store 会生成可供客户端读取的输出。
同一个组合可以面向不同客户端生成不同格式。你不必为了 Mihomo 和 sing-box 复制两套来源与过滤规则,只需要在输出阶段选择对应的目标格式。
数据是一份,出口可以有很多个。
从架构上看,Sub-Store 可以分为前端和后端两部分。
前端提供图形界面,让你创建订阅、组合和处理规则。
官方项目目前提供的前端地址是 sub-store.vercel.app。官方 README 也特别提醒:项目并不拥有 sub.store 这个域名,不应该把两者混为一谈。[1]
前端更像一个控制面板。你在这里编辑数据,但真正读取订阅、保存配置和生成输出的是后端服务。
后端会:
这也是为什么只打开一个网页,并不等于已经拥有完整的 Sub-Store。
你仍然需要一个可用的后端。它可以运行在部分代理工具提供的模块环境中,也可以通过 Docker 或 Node.js 自行部署。官方仓库和 Wiki 提供了不同平台的安装入口。[1][2]
部分代理工具支持通过模块、插件或重写机制运行 Sub-Store。
这种方式通常适合:
它的好处是部署轻,缺点是数据和能力可能依赖具体客户端。换设备、换平台时,需要重新考虑迁移问题。
如果有 NAS、家庭服务器或云主机,Docker 是比较清晰的部署方式。
官方 Docker 镜像为 xream/sub-store,支持持久化数据目录、配置后端访问路径,并可选启用同步和推送服务。[2]
一个更稳妥的基本思路是:
浏览器
↓ HTTPS / 身份验证
反向代理
↓ 仅本机访问
Sub-Store Docker 容器
↓
持久化数据目录我不太建议为了“先跑起来”,直接把一个没有访问控制的后端端口暴露到公网。
能访问后台的人,往往也能接触你的订阅信息。这不是一个适合裸奔的服务。
Sub-Store 后端也可以作为 Node.js 服务运行,适合需要调试、二次开发或自定义部署流程的人。
这种方式自由度更高,但也意味着你需要自行处理:
如果只是普通使用,Docker 往往更省心。如果准备读源码、改功能,Node.js 方式会更直接。
订阅链接看上去只是一串 URL,但它通常包含身份凭据或访问令牌。
拿到链接的人,可能可以读取你的订阅内容,甚至消耗对应账户的流量。因此,应该把订阅 URL 当成密码,而不是普通网页链接。
公开的在线转换服务确实方便,但你很难知道:
Sub-Store 的价值之一,就是让订阅处理可以留在自己控制的环境里。
但“使用 Sub-Store”不自动等于“安全”。如果后端仍然公开暴露、没有认证,问题只是从别人家的服务器搬到了自己家门口。
官方 Docker 文档明确提醒,不应将内部裸后端直接暴露在公网上。[2]
更合理的做法包括:
127.0.0.1;随机路径可以减少被随手扫到的概率,但它不是完整的身份认证。路径再长,也不应该被当成门锁。
官方 README 特别说明,sub.store 域名并不属于 Sub-Store 项目;当前官方前端是 sub-store.vercel.app。[1]
域名只差几个字符,数据的去向可能差得很远。
这类工具处理的又恰好是敏感配置,所以在打开网页、安装模块或复制脚本以前,最好回到官方 GitHub 仓库核对一次。
多花半分钟,通常比事后更换全部订阅链接轻松。
两者都会出现在“订阅转换”的讨论里,但侧重点并不完全相同。
| 工具 | 更像什么 | 主要特点 |
|---|---|---|
| 客户端直接订阅 | 把原材料直接拿来用 | 最简单,几乎没有额外维护 |
| subconverter | 转换引擎 | 擅长通过规则和参数完成格式转换及配置生成[3] |
| Sub-Store | 订阅管理工作台 | 有图形界面、持久化数据、组合、操作链和多目标输出 |
简单理解:
它们并不是绝对的替代关系。在复杂配置中,二者也可能处于同一条处理链的不同位置。
如果只是偶尔转换一次格式,完整部署 Sub-Store 可能有点重;如果订阅需要长期维护、反复组合并分发到多台设备,Sub-Store 的管理能力会更有价值。
如果你符合下面几种情况,Sub-Store 值得尝试:
如果你:
那么直接订阅通常更合适。
工具的价值不是功能越多越好,而是它刚好处理了你已经遇到的问题。
如果生活里还没有这团线,也就不必急着买理线器。
Sub-Store 的操作能力很强,尤其是脚本处理,很容易让人产生“既然能改,那就全部重做一遍”的冲动。
我的建议是分四步:
一开始就堆十几条正则、多个脚本和四层转换,确实很有“搭系统”的满足感。三个月后再打开,通常也很有考古的感觉。
能用内置操作解决的,不必急着写脚本;能用一条清楚的规则完成的,也不必拆成五层。
订阅管理的目标本来是减少混乱,不要让管理工具自己成为新的混乱。
Sub-Store 不会让网络变快,也不会把普通节点变成什么神奇线路。
它做的事情没有那么热闹:把几份来源收进来,删掉不需要的,改好名字,排整齐,再交给不同设备。
但很多工具的价值,本来就不在“创造新东西”,而在于让已有的东西各归其位。
桌面上只有一根线的时候,随手放着也无所谓。等设备多了,充电线、网线、串口线和示波器探头缠在一起,才会发现整理并不是洁癖,而是为了下一次伸手时,知道自己拿到的是什么。
Sub-Store 大概就是这样一个工具。
不负责远方,只负责把出发前的东西收拾好。