singbox-panel Skill
管理自建的 sing-box 代理节点面板(面板地址与节点清单不入库,见下方「连接信息」)。
连接信息
- API:
https://<你的面板域名> - Admin UI: 同域根路径
/ - 认证:
POST /api/login拿 JWT,后续请求带Authorization: Bearer <jwt> - 管理员凭据: 面板机
.env里的ADMIN_USER/ADMIN_PASS
支持的协议(仅此三种)
| 协议 | 用途 | 需要域名 | 特点 |
|---|---|---|---|
| hysteria2 | 日常高速 | 是 | UDP/QUIC, Salamander 混淆 + BBR, 最快 |
| vless-reality | 稳定抗封 | 否 | TCP, 伪装正规网站, 零依赖 |
| vless-httpupgrade | CDN 中转 | 是 | 用于被墙IP/IPv6-only节点 |
核心流程
新增节点(一键)
# 1. 创建节点
POST /api/nodes
{"name":"my-node", "host":"1.2.3.4", "domain":"node.example.com"}
# 2. 配置 SSH(面板机的公钥还没进目标机器时)
POST /api/nodes/{id}/setup-ssh
{"password":"root密码"}
# 3. 安装 sing-box
POST /api/nodes/{id}/install
{"version":"latest"} 或 {"version":"1.13.8"}
# 4. 一键配置协议(自动选择、生成密钥、签证书、推送、启动)
POST /api/nodes/{id}/auto-setup
{"domain":"node.example.com", "mode":"direct"}
# direct → Hysteria2 + Reality
# cdn → HTTPUpgrade + Reality
# reality → Reality only
# 也可手动指定: {"protocols":["hysteria2","vless-reality","vless-httpupgrade"]}
用户管理
# 创建(管理员,默认启用)
POST /api/users {"name":"friend", "traffic_limit_bytes":107374182400}
# 注册(公开,默认禁用)
POST /api/register {"username":"someone", "password":"123456"}
# 启用
PUT /api/users/{id} {"enabled":true}
# 授权所有节点
POST /api/users/{id}/access {"all":true}
# 推送配置使生效
POST /api/batch/push-all
# 订阅链接
GET /sub/{sub_token} # base64 (v2rayN/Shadowrocket)
GET /sub/{sub_token}?format=clash # Clash Meta YAML
常用操作
# 查看所有节点状态
GET /api/nodes/{id}/status → {reachable, installed, version, running}
# 升级 sing-box
POST /api/nodes/{id}/install {"version":"latest"}
# DNS 与部署模式评估(不改任何东西,只解释判定依据)
GET /api/nodes/{id}/setup-assessment?mode=auto&domain=node.example.com
# 证书:auto-setup 自动签发 Let's Encrypt;CDN 场景手动上传
POST /api/nodes/{id}/cert-upload {"domain":"...","cert":"...","key":"..."}
# 证书续期(剩余不足 30 天才重签,重签会重启该节点 sing-box)
POST /api/nodes/{id}/cert-renew # 到期才续
POST /api/nodes/{id}/cert-renew {"force":true} # 强制重签
# 返回每张证书的 before/after 到期时间与 status: renewed | fresh | failed
# 到期天数也在节点状态里:GET /api/nodes/{id}/status → inbounds[].cert.days_left
# 查看原始配置(只读)
GET /api/nodes/{id}/raw-config
# 用量统计(谁、哪天、用了哪个节点)
GET /api/stats/usage?from=2026-08-01&to=2026-08-06&group=day,user,node
GET /api/stats/usage?from=2026-08-01&to=2026-08-06&group=user # 只看每人合计
GET /api/stats/users # 累计计数器(配额判定用)
GET /api/stats/nodes
# 重置流量
POST /api/users/{id}/reset-traffic
完整 API 列表
用户
GET /api/users— 列表POST /api/users— 创建PUT /api/users/{id}— 更新 (name/enabled/traffic_limit_bytes/expire_at/node_ids),用户与权限合并保存并同步受影响节点;同步失败自动回滚DELETE /api/users/{id}— 先从节点移除用户,节点同步成功后删除;失败自动回滚POST /api/users/{id}/reset-traffic— 重置流量并同步节点;失败自动回滚POST /api/users/{id}/reset-sub-token— 重置订阅令牌
访问控制
GET /api/users/{id}/access— 查看可访问节点POST /api/users/{id}/access— 授权 ({node_id} 或 {all:true}),自动同步节点,失败回滚PUT /api/users/{id}/access— 原子替换权限 ({node_ids:[1,2]}),自动同步节点,失败回滚DELETE /api/users/{id}/access— 撤销 ({node_id} 或 {all:true}),自动同步节点,失败回滚
节点
GET /api/nodes/POST /api/nodes/PUT /api/nodes/{id}/DELETE /api/nodes/{id}GET /api/nodes/{id}— 详情含 inboundsPOST /api/nodes/{id}/inbounds— 添加协议并立即同步节点,失败回滚DELETE /api/inbounds/{id}— 删除协议并立即同步节点,失败回滚
节点运维
GET /api/nodes/{id}/status— SSH 连通性、sing-box 状态、各入站 TCP/UDP 监听状态, 以及各 TLS 入站的证书到期天数(inbounds[].cert、cert_days_left取最差的一张)GET /api/nodes/{id}/version— sing-box 版本POST /api/nodes/{id}/setup-ssh— 注入公钥 ({password})POST /api/nodes/{id}/install— 安装/升级 sing-box ({version})GET /api/nodes/{id}/setup-assessment?mode=auto&domain=X— 检测 DNS 并解释部署模式建议;不会仅凭 DNS 不一致认定为 CDNPOST /api/nodes/{id}/auto-setup— 幂等配置和域名迁移 ({domain, mode, protocols, ports});mode 支持 auto/direct/cdn/reality。 幂等的含义是重新求值、结果相同才跳过:重跑会重新校验 Reality 握手目标(要求 h2 + 非错误状态码, 不合格才换)并把端口收敛到常规 HTTPS 端口(443 → 8443/2053/2083/2087/2096,跳过节点上已占用的)。 密钥对、short_id、用户 UUID 一律保留,所以重跑不会让已发出去的订阅失效——但端口或握手目标一变, 客户端必须重新拉一次订阅。
配置
POST /api/nodes/{id}/generate— 预览配置POST /api/nodes/{id}/push— 推送并重启POST /api/batch/push-all— 推送所有节点POST /api/batch/reprovision— 对所有启用节点重跑 auto-setup(协议加固、握手目标 或端口策略升级后用它,不要手工 ssh 上机循环调单节点接口)。{"mode":"auto","node_ids":[1,2],"dry_run":true}各字段均可省。 逐个串行(每个节点会重启 sing-box,并行等于全网同时断); 部分成功返回 207、全部失败返回 502,只看状态码不会把"半个机群"误读成成功。 先用dry_run: true看会动哪些节点。 CDN 节点要单独跑一次:默认mode:"auto"对橙云域名会返回 422(不肯只凭 DNS 不一致就断定是 CDN,要人明确表态),所以 de 这类节点补一条{"node_ids":[4],"mode":"cdn"}。整机群跑出 207 而失败的恰好是 CDN 节点时, 先看是不是这个原因,别当成故障。GET /api/nodes/{id}/raw-config— 只读查看已部署配置;不支持手动写入
证书
POST /api/nodes/{id}/cert-upload— 上传证书 + 私钥(CDN / HTTPUpgrade 场景); 直连场景由 auto-setup 自动签发 Let's Encrypt 并配置续期POST /api/nodes/{id}/cert-renew— 重签 TLS 入站证书({"force":true}无视有效期)。 只碰证书,不动端口 / UUID / Reality 密钥,所以不会让已发出去的订阅失效。 签完从节点回读到期时间,据此判定成败,不看 acme.sh 的退出码
订阅
GET /sub/{token}— 订阅 (自动识别客户端格式)GET /sub/{token}?format=clash— 强制 Clash 格式
统计
GET /api/stats/meta— 统计时区、今天、可查询的最早一天(留存边界)GET /api/stats/usage?from&to&group&user_id&node_id— 唯一的聚合接口:group可任意组合day/user/node(留空=总计一行),from/to为面板时区的YYYY-MM-DD闭区间; 超出留存的区间自动裁剪,整段过期则报错GET /api/stats/users— 用户累计计数器(配额判定用)GET /api/stats/nodes— 节点流量(留存窗口内)GET /api/me/usage?from&to&group— 同一套聚合,锁定为调用者自己
用量样本保留 3 个自然月(当月 + 前两个月),每天裁剪一次;查询超出边界会被拒绝。
时区由面板 TIMEZONE 决定(默认 Asia/Shanghai)。
公开
POST /api/register— 用户注册 ({username, password})GET /api/health— 健康检查
节点信息
节点清单(名称 / IP / 域名)不入库:面板自己就是权威源,用 GET /api/nodes 取。
部署
- 仓库:
github.com/briqt/singbox-panel - 服务: 面板机
/opt/singbox-panel/, systemdsingbox-panel.service - 反代: Caddy
panel.example.com → 127.0.0.1:2082 - 部署: 在仓库根目录
make deploy DEPLOY_HOST=<你的 ssh 主机别名> - 安装 skill:
npx skills add briqt/singbox-panel -g -y