一个轻量的订阅链接服务,支持按用户 Token 动态生成 Clash / V2Ray / Sing-box 订阅内容,并提供 Web 管理后台、用户与节点管理、访问统计。
- 动态订阅生成
GET /api/subscription/{token}GET /api/v2ray/{token}GET /api/singbox/{token}
- 用户 Token 管理(增删改查)
- 节点管理(增删改查)
- Web 管理后台(
/admin.html) - 访问统计(总量、按格式、按 Token、最近访问时间)
.
├── cmd/server/main.go
├── internal/
│ ├── api/
│ ├── generator/
│ ├── model/
│ ├── stats/
│ └── store/
├── data/
│ ├── clash.yaml
│ ├── xray.config
│ ├── users.json
│ └── nodes.json
├── web/
│ ├── index.html
│ └── admin.html
├── Makefile
└── go.mod
- Go
1.25+ - macOS / Linux / Windows(
make build可交叉编译)
- 初始化数据文件(首次建议写入空数组)
echo '[]' > data/users.json
echo '[]' > data/nodes.json- 启动服务(推荐设置
ADMIN_TOKEN)
ADMIN_TOKEN=your-secret-token go run ./cmd/server如果未设置 ADMIN_TOKEN,服务会自动生成一个 UUID 作为管理员密钥,并写入:
<DATA_DIR>/admin.key
可直接读取该密钥用于登录:
cat <DATA_DIR>/admin.key启用 Xray 同步(推荐):
ADMIN_TOKEN=your-secret-token \
XRAY_CONFIG_PATH=data/xray.config \
XRAY_RELOAD_CMD="" \
go run ./cmd/serverXRAY_CONFIG_PATH 默认值为 /usr/local/etc/xray/config.json,也可通过启动参数指定:
ADMIN_TOKEN=your-secret-token go run ./cmd/server --xray_config_path=/opt/xray/config.json可选:指定运行时数据目录(默认 data)
ADMIN_TOKEN=your-secret-token DATA_DIR=/opt/subscriptionlink/data go run ./cmd/server也可使用启动参数(优先推荐):
ADMIN_TOKEN=your-secret-token go run ./cmd/server --data_dir=/opt/subscriptionlink/data可选:自定义监听地址(默认 127.0.0.1:8081)
ADMIN_TOKEN=your-secret-token LISTEN_ADDR=127.0.0.1:18081 go run ./cmd/server- 打开页面
说明:服务当前监听 127.0.0.1:8081。
适用于在 Linux 服务器上以 systemd 管理 xray、subscriptionlink、caddy 的部署场景。
脚本位置:
./scripts/deploy_linux.sh执行方式:
sudo ./scripts/deploy_linux.sh或直接传入域名:
sudo ./scripts/deploy_linux.sh example.com也支持显式参数:
sudo ./scripts/deploy_linux.sh --domain example.com --yes脚本会自动完成以下动作:
- 检查并安装
caddy - 检查并安装
xray - 使用
data/Caddyfile生成/etc/caddy/Caddyfile - 使用
data/xray.config生成/usr/local/etc/xray/config.json - 构建并安装
/usr/local/bin/subscriptionlink - 初始化
/usr/local/etc/subscriptionlink - 写入或补齐
systemd服务 - 依次启动
xray -> subscriptionlink -> caddy - 最终输出
/usr/local/etc/subscriptionlink/admin.key
卸载脚本:
sudo ./scripts/uninstall_linux.sh默认只移除 subscriptionlink 本体和由部署脚本创建的 caddy/xray systemd 单元,不会卸载系统里的 caddy/xray 包,也不会删除运行数据。若要彻底清理:
sudo ./scripts/uninstall_linux.sh --full-clean --yes重装脚本:
sudo ./scripts/reinstall_linux.sh --domain example.com --yes默认保留 /usr/local/etc/subscriptionlink 里的运行数据;若要先清空再重装:
sudo ./scripts/reinstall_linux.sh --domain example.com --full-clean --yes./scripts/smoke_test.sh脚本会启动临时实例(默认 127.0.0.1:18081)、执行登录会话与 CSRF 写操作验证,并在结束后恢复 data/ 文件。
默认构建当前平台:
make build按指定平台跨平台构建(可单个或多个):
make build PLATFORM=linux/amd64
make build PLATFORM=linux/amd64,windows/amd64,darwin/arm64产物输出到 dist/,例如:
dist/subscriptionlink-linux-amd64dist/subscriptionlink-darwin-arm64dist/subscriptionlink-windows-amd64.exe
清理产物:
make clean本地生成指定平台的 release 安装包:
./scripts/package_release.sh --target linux/amd64 --version v1.0.0支持的目标格式为 OS/ARCH,例如:
./scripts/package_release.sh --target linux/arm64 --version v1.0.0
./scripts/package_release.sh --target darwin/arm64 --version v1.0.0
./scripts/package_release.sh --target windows/amd64 --version v1.0.0输出目录默认为 release/,每个安装包包含:
bin/:对应平台的预编译二进制data/:部署所需模板文件scripts/:部署、卸载、重装脚本INSTALL.md:安装说明
推送 v* 标签后,GitHub Actions 会自动构建并发布这些安装包到 GitHub Release。
{
"name": "alice",
"email": "alice@example.com",
"token": "user-token",
"uuid": "user-uuid",
"expire": 0
}expire为 Unix 时间戳(秒)expire=0表示不过期
{
"name": "hk-01",
"server": "1.2.3.4",
"port": 1234,
"protocol": "vless",
"network": "ws",
"security": "none",
"path": "/xhttp",
"host": ""
}GET /api/subscription/{token}GET /api/v2ray/{token}GET /api/singbox/{token}
返回规则:
- Token 不存在:
403 - Token 过期:
403 - 格式不支持:
404
管理鉴权流程:
POST /api/admin/login,提交ADMIN_TOKEN- 服务端设置
HttpOnly会话 Cookie(admin_session) - 返回
csrf_token - 后续写操作(
POST/PUT/DELETE)需带X-CSRF-Token - 管理页每次打开默认进入登录页(不会自动跳过登录)
说明:若未配置 ADMIN_TOKEN,服务启动时会自动生成并写入 <DATA_DIR>/admin.key,登录接口可正常使用。
POST /api/admin/loginGET /api/admin/sessionPOST /api/admin/logout
登录请求示例:
{
"token": "your-admin-token"
}GET查询所有用户POST新增用户PUT更新用户(按token定位)DELETE /api/admin/users?token=...删除用户
POST/PUT 请求示例:
{
"name": "alice",
"email": "alice@example.com",
"token": "optional-token",
"uuid": "optional-uuid",
"expire": 0
}说明:POST 时若不传 token 或 uuid,服务会自动生成。
说明:POST 时若不传 email,服务会按 name@example.com 自动补全。
GET查询所有节点POST新增节点PUT更新节点(按name定位)DELETE /api/admin/nodes?name=...删除节点
请求体示例:
{
"name": "hk-01",
"server": "1.2.3.4",
"port": 1234,
"protocol": "vless",
"network": "ws",
"security": "none",
"path": "/xhttp",
"host": ""
}GET返回访问统计
返回示例:
{
"request_count": 12,
"by_format": {"subscription": 5, "v2ray": 4, "singbox": 3},
"by_token": {"token-a": 8, "token-b": 4},
"last_access": 1741350000
}假设:
export ADMIN_TOKEN=your-secret-token
export BASE=http://127.0.0.1:8081登录(保存 Cookie 并提取 CSRF):
curl -i -c admin.cookie -X POST "$BASE/api/admin/login" \
-H "Content-Type: application/json" \
-d "{\"token\":\"$ADMIN_TOKEN\"}"从返回体中拿到 csrf_token 后,下面示例记为 CSRF_TOKEN。
新增用户:
curl -X POST "$BASE/api/admin/users" \
-b admin.cookie \
-H "X-CSRF-Token: $CSRF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"alice"}'新增节点:
curl -X POST "$BASE/api/admin/nodes" \
-b admin.cookie \
-H "X-CSRF-Token: $CSRF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"hk-01","server":"1.2.3.4","port":1234,"protocol":"vless","network":"ws","security":"none","path":"/xhttp"}'获取统计:
curl "$BASE/api/admin/stats" -b admin.cookie获取订阅:
curl "$BASE/api/subscription/<user-token>"data/clash.yaml为订阅模板,支持占位符:{{UUID}}{{SERVER}}{{PORT}}{{NODE_NAME}}{{NETWORK}}{{PATH}}{{HOST}}{{TLS}}
- 访问
/api/subscription/{token}时,服务会根据 token 选取一个节点并替换模板占位符。 - 当前
{{TLS}}默认替换为true。
用户新增/更新/删除后支持同步到 Xray(可选,未配置则跳过):
XRAY_CONFIG_PATH:Xray 配置文件路径XRAY_INBOUND_TAG:目标 inbound tag(可选)XRAY_RELOAD_CMD:写入配置后的重载命令
说明:
- 如果
xray.config的 inbound 没有tag字段,不要设置XRAY_INBOUND_TAG。 - 若设置了
XRAY_INBOUND_TAG,必须与 inbound 的tag完全一致,否则会报:sync xray failed: xray inbound tag not found: <tag> XRAY_RELOAD_CMD未设置时,默认执行:sudo systemctl restart xray- 若你不希望自动重载,可显式设置:
XRAY_RELOAD_CMD=""
--listen_addr/LISTEN_ADDR:监听地址,默认127.0.0.1:8081--data_dir/DATA_DIR:运行数据目录,默认data--xray_config_path/XRAY_CONFIG_PATH:Xray 配置路径,默认/usr/local/etc/xray/config.json
优先级:启动参数优先于环境变量。
admin.key是管理员登录密钥文件,请不要提交到仓库。- 建议将
DATA_DIR指向受控目录,并限制文件权限。
- 数据存储为本地 JSON 文件,不适合多实例并发写入
- 管理鉴权为单一
ADMIN_TOKEN(会话化),未做多角色权限划分 - 订阅协议字段为最小实现,可按客户端要求继续扩展