MagicPanel 配置文档
这份文档回答:有哪些配置、每项配置长什么样、要改它去哪里改、改完怎么验证和发布。
目标是让一个 Agent 拿到「把 X 改成 Y」这种需求时,不用读代码就能改对、改完能自测、然后安全地发出去。
目录
- 配置全景
- 产物结构
- 基础配置三层
- DNS 段:防污染
- 节点来源
- 本地节点
- 规则来源
- 策略组
- 分流规则
- 引擎平台
- 拓展模块
- 设备
- 设置项
- 怎么改:界面 / 接口 / 直接改库
- 改完怎么验证
- 改完怎么发布
- 改配置的禁忌
配置全景
面板里可配的东西一共十一类,按「先定大框架、再填内容」理解最省事:
| # | 配置 | 决定什么 | 改完要不要重新发布 |
|---|---|---|---|
| 1 | 节点来源 | 有哪些节点、什么时候更新、哪些留 | 要 |
| 2 | 本地节点 | 自己加的单个节点 | 要 |
| 3 | 规则来源 | 域名 / IP 清单 | 要 |
| 4 | 策略组 | 流量怎么分组 | 要 |
| 5 | 分流规则 | 什么流量走哪组 | 要 |
| 6 | 引擎平台 | 一类客户端的标识与专属扩展 | 要 |
| 7 | 引擎默认配置 | 这一类引擎的顶层键基线 | 要 |
| 8 | 引擎平台配置 | 某个「引擎+平台」的顶层键 | 要 |
| 9 | 设备独立配置 | 某台设备的个性化 | 不用,分发时实时叠加 |
| 10 | 拓展模块 | 可复用的 YAML 片段 | 要 |
| 11 | 设备 | 每台机器的订阅地址 | 不用(地址即刻生效) |
判断要不要重新发布:只有第 9 项(设备独立配置)和第 11 项(设备)是分发时实时生效的,其他都要重新构建发布。
产物结构
客户端拿到的 config.yaml 由四层合并而成,优先级由低到高:
① 基础配置 引擎默认配置 → 引擎平台配置 → 设备独立配置
② 结构化内容 节点 / 策略组 / 分流规则(服务端生成,任何配置层都不许覆盖)
③ 拓展模块 启用的 YAML 片段,与引擎匹配后深度合并
④ 平台扩展 单个引擎平台专属的 YAML 片段,最后应用
产物里有哪些段(以 Stash 为例):
| 段 | 内容 | 谁维护 |
|---|---|---|
| 基础键 | mixed-port、mode、log-level、allow-lan、ipv6、profile… |
基础配置三层 |
dns |
DNS 解析、Fake-IP、策略 | 基础配置 / 拓展模块 |
tun |
接管模式 | 基础配置 / 拓展模块 |
proxies |
节点(含本地节点 名称 (类型)) |
节点来源 / 本地节点 |
proxy-groups |
策略组 | 策略组页 |
rule-providers |
规则集引用 | 规则来源页 |
rules |
分流规则 | 分流规则页 |
hosts |
静态域名解析 | 基础配置 / 平台扩展 |
mtproto |
Telegram MTProto(仅 Stash) | 设备独立配置 |
http / cron / script-providers |
Stash 专属 | 拓展模块 / 平台扩展 |
五类键任何配置层都不许写:proxies、proxy-providers、proxy-groups、rule-providers、rules。服务端硬校验,写了直接被拒。
基础配置三层
键与作用域
| 层 | 存哪 | 生效时机 |
|---|---|---|
| 引擎默认配置 | base_configs,engine=<引擎>、platform=''、device_id=0 |
固化在构建快照 |
| 引擎平台配置 | base_configs,engine、platform 有值、device_id=0 |
固化在构建快照 |
| 设备独立配置 | base_configs,device_id>0 |
分发时实时叠加 |
只存与上层不同的差异:每层存的是「这一层相对上层的差量」,不是完整配置。
列表的合并语义(最容易踩)
| 层 | 语义 | 例子 |
|---|---|---|
| 引擎默认配置 | 整体替换 | 上层 dns.fake-ip-filter: [a, b],这一层写 [c] → 结果就是 [c] |
| 引擎平台配置 | 整体替换 | 同上 |
| 设备独立配置 | 只记新增,分发时追加 | 上层 [a, b],这一层写 [c] → 结果 [a, b, c] |
设备独立配置用追加语义,是为了「给这台机器加一条过滤」不必把整份列表复制一遍。
伪键
| 伪键 | 作用 | 出现在 |
|---|---|---|
_direct_domains |
生成置顶的 DOMAIN-SUFFIX,<域名>,DIRECT 规则 |
引擎默认配置 / 引擎平台配置 / 设备独立配置 |
_fake_ip_filter |
写进 dns.fake-ip-filter |
同上 |
_panel_direct_rule |
面板域名强制直连(置顶 DOMAIN-SUFFIX,<面板域名>,DIRECT) |
同上 |
伪键只存在于配置层,编译时会被翻译掉,产物里不会出现。
常用顶层键
| 键 | 说明 | 备注 |
|---|---|---|
mixed-port |
混合端口 | |
mode |
rule / global / direct |
|
allow-lan |
允许局域网连接 | MTProto 依赖它 |
ipv6 |
是否启用 IPv6 | |
log-level |
日志级别 | |
profile |
store-selected 等 |
|
dns.enable |
Mihomo 内核接管 DNS | Stash 由客户端接管 |
dns.nameserver-policy |
按域名指定 DNS | 设备独立配置常用 |
tun |
Mihomo 的 TUN 模式 | 设备独立配置常用(桌面机) |
hosts |
静态解析 | Mac mini 连家里 NAS 用 |
mtproto |
Telegram MTProto | 仅 Stash;port / secret / ipv6 / dc-config-url |
预设
base_config.PRESETS 里内置(基础配置的预设,经 /api/v1/base-config/schema 下发):
| 预设 | 引擎 | 说明 |
|---|---|---|
| Stash 官方完整默认 | stash | 按官方文档补全:DNS、嗅探、Geo、HTTP 引擎、Google 中国站重定向 |
| Mihomo 官方完整默认 | mihomo | 按官方文档补全:DNS、Geo、嗅探(HTTP 引擎是 Stash 专属) |
| 兼容现状(精简) | stash / mihomo | 精简版 |
| MTProto 代理(Telegram) | stash | 套用时现场生成 32 位十六进制密钥 |
拓展模块的预设是另一套,纯前端常量,在 src/snippetPresets.js 的 SNIPPET_PRESETS(服务端不提供预设接口)。
DNS 段:国内直连为默认,海外敏感域走代理(2026-10-27 重构)
DNS 段固化在「引擎默认配置」:源码基线 server/app/services/base_config.py 的
_DNS_COMMON / STASH_DNS / MIHOMO_OFFICIAL。引擎平台配置、平台扩展、设备独立配置、
拓展模块一律不写 dns: 键(追加合并会悄悄盖过基线);家用 Fake-IP 清单在平台层用
_fake_ip_filter 伪键维护。规范细则见 AGENTS.md 约束 31。
背景实测(2026-10-25 / 10-27,家里出口 R6S PPPoE)
| 通道 | 实测结果 |
|---|---|
| 明文 UDP(119.29.29.29 / 180.76.76.76 / 223.5.5.5 / 168.95.1.1) | 链路被注入,www.google.com 返回 104.244.42.197 这类假 IP |
| 国内 DoH(dns.alidns.com / 223.5.5.5 / doh.pub / dot.pub / 1.12.12.12 / 120.53.53.53) | 加密挡住了链路注入,但解析器服务端对海外被墙域名投毒;对国内域名返回正确的国内 CDN 节点 |
| 境外 DoH(1.1.1.1 / 8.8.8.8 / 9.9.9.9 / dns.google / quad9 …) | 国内直连一律超时或被重置,只能走代理出口 |
设计原则:本地答案只在两种场合被真正使用
Fake-IP 模式下,走代理的连接由代理节点在出口侧远程解析,客户端本地的解析答案 (哪怕是污染值)根本不会被使用。本地答案真正影响连通性的只有两处:
- 命中 Fake-IP 排除清单(
fake-ip-filter)的域名——应用拿到真实 IP,答案必须干净 (+.microsoft.com/+.live.com/lens.l.google.com这类海外域); - 走 DIRECT 的连接——必须拿到正确视角的 CDN 节点
(
cn/+.cn等国内集合要国内视角;mirror-accelerate/pt/trackers这类 「直连但服务器在境外」的集合要干净答案)。
由此得出各域名的解析路径:
| 域名类别 | 解析路径 | 位置 |
|---|---|---|
| 默认(含全部国内域名,未命中任何策略) | 国内 DoH 直连双运营商并发:120.53.53.53(腾讯 doh.pub)/ 223.5.5.5(阿里 alidns),裸 IP,最快者生效 |
基线 nameserver |
海外敏感域(Fake-IP 排除清单里的海外域:微软全家、lens.l.google.com) |
境外 DoH 走代理:1.1.1.1 / 8.8.8.8 |
平台层 nameserver-policy |
直连的海外集合(mirror-accelerate / pt / trackers) |
同上 | 平台层 nameserver-policy |
节点域名(*.magichub.top 等) |
国内 DoH 直连,独立链路不跟随规则 | proxy-server-nameserver |
国内域名不需要显式策略:默认解析器就是国内 DoH,为 cn / +.cn 等再写
nameserver-policy 是纯冗余(同一台服务器),且策略命中只用单服务器、反而比
默认路径的双运营商并发差。alidns(223.5.5.5)为什么可以放在默认路径:
它对海外域名的污染答案在本设计下永远不会被使用(fake-ip 由节点远程解析、
海外敏感域显式走境外 DoH),它的国内答案与 doh.pub 实测一致;放它只为运营商冗余。
引擎差异(海外敏感域的「走代理」写法):
| 引擎 | 写法 | 出处 |
|---|---|---|
| Stash | 策略值写裸 IP https://1.1.1.1/dns-query,靠 follow-rule: true + 出口 IP 规则送进代理 |
Stash 没有 #策略组 语法(stash.wiki/features/dns-server「DNS 查询跟随规则」) |
| Mihomo | 策略值写裸 IP https://1.1.1.1/dns-query,靠 respect-rules: true + 出口 IP 规则送进代理(需配 proxy-server-nameserver,已配;不建议与 prefer-h3 同用,prefer-h3 为 False) |
wiki.metacubex.one/config/dns:「dns 连接遵守路由规则」 |
配套规则与说明:
- DNS 服务器一律写裸 IP 形式。官方文档把「DNS 服务器地址是 IP 而不是域名」列为避免 递归查询的前提,写域名会多一层引导解析。
default-nameserver不再配置:它只用于解析「域名形式的 DNS 服务器」,本方案所有 服务器都是裸 IP,它永远不会被查询(留着只会误导,而且它是明文 UDP 通道)。- 不再配置
fallback/fallback-filter:配置 fallback 会默认启用 geoip CN 过滤 (mihomo 文档明示,Stash 的geoip-code同样默认 CN),多一个 geo 数据依赖; 且默认解析器已是国内直连、海外敏感域已显式走代理,没有”污染值”需要筛。 2026-10-27 之前的旧方案(默认境外 DoH 走代理 + Quad9 回退)已废弃——它把所有 未命中策略的域名(包括大量国内长尾域名)的解析与代理可用性绑在一起,代理一抖 国内网站就成片打不开。 - 不再配置
direct-nameserver(Mihomo):直连出口的域名遵循策略与默认 nameserver(国内直连),旧值dns.alidns.com会给直连的海外域名(镜像站、PT tracker) 投毒答案。 follow-rule(Stash)必须开:它同时决定两类 DNS 连接的走向——境外 DoH 裸 IP 靠 出口 IP 规则进代理,国内 DoH 裸 IP 靠直连 IP 规则保持直连。
改 DNS 段时必须同时成立的前提
- 规则里有
IP-CIDR,1.1.1.1/32/1.0.0.1/32/8.8.8.8/32/8.8.4.4/32→🚀 默认代理(境外 DoH 的出口;删掉这几条,海外敏感域解析直接超时)。 - 规则里有
IP-CIDR,120.53.53.53/32/223.5.5.5/32→DIRECT(国内 DoH 的直连出口;Stashfollow-rule下缺了这两条,默认解析会被兜底规则送进代理)。 nameserver-policy里的rule-set:<name>要逐个集合写成独立的键。rule-set:cn,ai-cn,apple-cn这种逗号合并写法是 Stash 专有扩展,Mihomo 不认, 合并键在 Mihomo 客户端上静默失效。- 兜底前的
RULE-SET,cn-ip,DIRECT不带no-resolve:它是”未列入集合的国内域名” 的最后直连机会,带 no-resolve 会让这些域名直接落到MATCH → 🚀 默认代理, 从境外出口访问国内站点。为这一条多付一次国内 DNS 解析是值得的。
怎么验证
DNS 段改完,静态校验查不出问题(Stash 目标只做静态校验),要真跑:
# 用真实产物在 mihomo 上实跑。注意:产物含 tun 段,测试机上要先 tun.enable: false
# 并改掉 mixed-port,否则会劫持测试机全部流量。
mihomo -d /tmp/mpverify -f /tmp/mpverify/config.yaml # config 里加 dns.listen 与 external-controller
curl -s "http://127.0.0.1:19090/dns/query?name=<域名>&type=A"
# 期望:国内域名(baidu / taobao / 小众国内站)→ 国内 CDN IP;
# 海外敏感域(microsoft / live / ghfast.top)→ 真实 IP(走代理的境外 DoH);
# 故障注入:把 1.1.1.1 出口规则改指向空组后,国内域名仍必须可解析——
# 默认解析不依赖代理,这是本方案与旧方案的核心区别。
节点来源
base_configs 之外的表:sources。
| 字段 | 含义 | 默认 |
|---|---|---|
name |
来源名 | 必填 |
url |
订阅地址(加密存储) | 必填 |
enabled |
是否参与分发 | true |
filter |
节点过滤正则 | 空 |
ua |
抓取时的 User-Agent | Stash |
interval |
抓取间隔(秒),0 = 关自动抓取 | 21600 |
test_interval |
测速间隔(秒),0 = 关自动测速 | 21600 |
client_interval |
客户端更新间隔,0 = 跟随抓取间隔 | 0 |
auto_fetch |
自动抓取开关 | true |
auto_test |
自动测速开关 | true |
allow_private |
允许内网地址节点 | false |
filter_unavailable |
只分发可用节点 | false |
proxy_url |
抓取走代理的地址(加密存储;留空 = 直连) | 空 |
headers_enc |
自定义请求头(名字 + 值,密文存储;列表只回显名字) | 空 |
source_kind |
remote(在线抓取)/ file(上传的文件) |
remote |
要点
- 抓取失败时用上一次成功的快照继续服务。
filter_unavailable打开后,抓完自动补测;自动构建发布要求来源有可用测速结果。- 节点来源整体被「过滤正则」筛掉的节点不会进产物。
- 删来源前要先看策略组有没有引用它(有引用会被拦下)。
source_kind='file'的来源没有在线地址:内容由上传时解析成快照,auto_fetch恒为 0, 定时抓取跳过它,「一键抓取」会明确报「文件来源没有在线地址,请重新上传订阅文件」。headers_enc里的请求头值按凭据处理:接口只回显名字,原文只在「查看」接口返回(记审计); 编辑时值不回显,提交null表示保持原值。Accept-Encoding一律丢弃——httpx 只声明自己能 解码的编码,镜像里没有 brotli。proxy_url非空时抓取经该代理出网(服务端出不去机场订阅站时的兜底), 界面默认给http://10.0.1.8:7890,可以改。- 这个地址是 Mac mini 上的 Stash 混合端口,而面板本身跑在 NAS 上,
所以必须写内网地址
10.0.1.8;写127.0.0.1会连到 NAS 自己、抓取全部失败。 详见环境与地址速查。
本地节点
表:local_nodes。
| 字段 | 含义 |
|---|---|
name |
节点名(产物里是 名称 (类型)) |
node_type |
本地 / 自建 / 家宽 / 机房 / 专线 / 中转 / 落地 |
protocol |
协议(决定参数表单) |
server / port |
地址与端口 |
params |
协议参数(加密存储) |
extra_yaml |
额外 YAML 片段 |
enabled |
是否写入产物 |
要点
- 协议不同参数不同(hysteria2 要
auth、trojan 要password+sni…),以/api/v1/local-nodes/schema返回的表单为准。 - 启用后不会自动进任何策略组,要去策略组里勾选。
- 停用的节点不写入产物;策略组引用了停用节点时构建会给出警告。
规则来源
表:rule_providers。
| 字段 | 含义 | 默认 |
|---|---|---|
name |
集合名 | 必填 |
kind |
remote(远程)/ inline(内联)/ repo(仓库托管) |
remote |
url |
远程地址(加密存储) | 远程必填 |
repo_path |
仓库内相对路径,如 rule/magic-chat.yaml |
仓库来源必填 |
inline_content |
内联内容 | 内联必填 |
behavior |
domain / ipcidr / classical |
domain |
format |
yaml / text / mrs |
yaml |
interval |
抓取间隔(秒) | 86400 |
client_interval |
客户端更新间隔 | 0 |
proxy_url |
抓取走代理的地址(加密存储;留空 = 直连) | 空 |
enabled |
是否参与分发 | true |
要点
- 分流规则用
RULE-SET,<集合名>引用;引用了停用或不存在的集合,这条规则会被剔除。 proxy_url非空时抓取经该代理出网,界面默认给http://10.0.1.8:7890。 这是 Mac mini 上的 Stash 混合端口;面板跑在 NAS 上,必须用内网地址, 不能写127.0.0.1(详见环境与地址速查)。- 集合名不能和已有集合重名。
- 内联集合在页面里直接编辑内容,格式与远程一致。
- 仓库托管(
kind='repo'):内容由「自主维护」页同步写入,界面改不动; 启用状态仍归面板。切换前后的产物逐字节一致(渲染层不读kind, 分发端点只读content)。
策略组
表:proxy_groups。
| 字段 | 含义 | 默认 |
|---|---|---|
name |
组名 | 必填 |
type |
select / url-test / fallback / load-balance / relay |
select |
hidden |
是否隐藏 | false |
use_sources |
聚合哪些节点来源 | 空 |
local_nodes |
勾选哪些本地节点 | 空 |
proxies |
直接列出的节点 / 其它组 | 空 |
filter |
节点过滤正则 | 空 |
url |
测速地址 | https://www.gstatic.com/generate_204 |
interval / timeout / tolerance |
url-test 的间隔 / 超时 / 容差(毫秒) | 600 / 8000 / 150 |
lazy |
延迟到被使用才测速 | true |
strategy |
load-balance 分配策略:一致性哈希 / 轮询 / 粘性会话 | 空 |
local_first |
本地节点优先 | false |
targets |
适用引擎平台(["*"] = 全部) |
["*"] |
devices |
适用设备(["*"] = 全部) |
["*"] |
要点
- 组名会出现在产物里,命名要能一眼看懂用途。
- 引用了不存在的来源 / 节点 / 其它组会被拦下。
- 空组会自动留占位节点,避免客户端把空组改写成别的。
targets与devices是交集关系:两个都填时,设备必须同时在指定平台上。- 适用范围多选里的 「包含所有」(内部存为
["*"])表示全部:节点来源就是所有来源 (以后新增的来源自动进来),引擎平台 / 设备就是全部。逐项选满时会自动归一成「包含所有」; 显式传空数组表示不适用任何平台 / 设备。 relay组只能用固定成员:不能用节点来源或过滤正则,且至少 2 个成员组成转发链。
分流规则
表:rules。
| 字段 | 含义 | 默认 |
|---|---|---|
type |
规则类型(见下) | 必填 |
value |
匹配内容 | 必填 |
target |
命中的策略组或 DIRECT / REJECT |
必填 |
enabled |
是否生效 | true |
no_resolve |
IP 字面量规则不触发解析 | false |
note |
备注 | 空 |
targets |
适用引擎平台(["*"] = 全部) |
["*"] |
devices |
适用设备(["*"] = 全部) |
["*"] |
规则类型分两层校验(server/app/config.py):
- 创建时只认全局 13 种(
config.RULE_TYPES,routers/policy.py):DOMAIN-SUFFIX、DOMAIN、DOMAIN-KEYWORD、DOMAIN-REGEX、IP-CIDR、IP-CIDR6、GEOIP、GEOSITE、RULE-SET、SRC-IP-CIDR、DST-PORT、PROCESS-NAME、MATCH。界面下拉就是这 13 种。 - 构建时再按引擎官方白名单复查(
config.STASH_RULE_TYPES/config.MIHOMO_RULE_TYPES)。超出该引擎白名单的类型客户端加载会失败。
no-resolve 只对 IP-CIDR、IP-CIDR6、GEOIP、RULE-SET、SRC-IP-CIDR 有效。
要点
- 规则按
sort排序,从上往下匹配,命中即停;MATCH/FINAL是兜底,永远在最后。 - 兜底之后还有规则 = 那条规则永远不生效(数据自检会报出来)。
- 规则的
targets/devices与目标组的targets/devices必须有交集,否则这条规则会被自动剔除。
引擎平台
表:targets。
| 字段 | 含义 |
|---|---|
name |
平台名(如 Stash-iOS),会拼进产物文件名 |
engine |
stash / mihomo |
platform |
ios / macos / tvos / windows / android / linux |
description |
说明 |
extra_yaml |
该平台专属的 YAML 片段,最后应用 |
要点
(engine, platform)唯一,重复写入返回 409。- 名称只能含字母、数字、下划线、短横线。
- 删平台前必须指定迁移目标,挂在它下面的设备会一起搬过去。
拓展模块
表:snippets。
| 字段 | 含义 | 默认 |
|---|---|---|
name |
模块名 | 必填 |
category |
分类(general / dns / panel / script / rewrite) | general |
engine |
stash / mihomo / all |
all |
content |
YAML 内容 | 必填 |
enabled |
是否启用 | true |
sort |
合并顺序(越大越后合并) | 0 |
note |
备注 | 空 |
要点
- 合并规则:字典递归、列表追加、标量覆盖。
- 同样不许写那五个结构化键。
- 预设清单在
src/snippetPresets.js的SNIPPET_PRESETS(纯前端常量,服务端不提供预设接口)。 - 与引擎默认配置重复的功能,可以关掉对应模块,产物不变。
设备
表:devices。
| 字段 | 含义 | 默认 |
|---|---|---|
name |
文件名(产物文件名就是 <name>.yaml) |
必填 |
platform |
平台标签(随所选引擎平台自动带出,不参与文件名) | 必填 |
target_id |
挂在哪个引擎平台 | 必填 |
env |
订阅环境 production / testing |
production |
note |
设备名(后台与门户展示用) | 空 |
last_pull_at |
任意资源(配置本体 + 规则集 + 节点来源)的最后拉取时间 | 空 |
last_config_at |
配置本体(config.yaml)的最后拉取时间 |
空 |
要点
- 订阅令牌是自动生成的,数据库里存哈希 + 加密副本;
轮换令牌后旧地址立即失效。 - 设备独立配置的键是
(engine, platform, device_id)——设备换平台或平台改引擎时要自动换键(服务端已处理)。 - 设备删了,它的订阅地址和设备独立配置一起清掉。
- 判断「设备有没有拿到新配置」只看
last_config_at:last_pull_at会被规则集、节点来源的 拉取一起刷新,拿它判断会把卡住的设备显示成正常的。超过 3 倍profile-update-interval没更新即判定陈旧,接口给config_stale,设备列表标「未更新」、概览统计devices_stale。
设置项
表:settings(键值对)。
| 键 | 含义 | 默认 |
|---|---|---|
base_url |
对外基础地址(生成订阅链接用) | 空 |
session_ttl_hours |
会话有效期(小时) | 168 |
profile_update_interval |
配置更新提示(小时,写入响应头 profile-update-interval) |
1 |
core_proxy |
核心下载代理(仅用于安装测速核心) | 空 |
scheduler_enabled |
内置定时任务总开关 | 1 |
auto_fetch_sources / auto_fetch_rules |
自动抓取来源 | 1 |
auto_test_sources |
自动测速 | 1 |
auto_build_enabled |
策略变化时自动构建 | 1 |
auto_build_interval_hours |
构建检查间隔(小时) | 1 |
auto_publish_enabled |
校验通过后自动构建发布 | 1 |
auto_publish_env |
自动构建发布到 production / testing |
production |
WebDAV 备份相关键:webdav_url、webdav_username、webdav_password_enc、webdav_dir、webdav_interval_hours、webdav_keep、webdav_enabled。
怎么改:界面 / 接口 / 直接改库
界面
最快的方式,路径:
| 要改 | 页面 |
|---|---|
| 节点来源 | 节点来源 |
| 本地节点 | 节点来源 → 本地节点 |
| 规则来源 | 规则来源 |
| 策略组 | 策略组 |
| 分流规则 | 分流规则 |
| 引擎平台 | 引擎平台 |
| 引擎默认配置 / 引擎平台配置 / 设备独立配置 | 基础配置(左侧树选作用域) |
| 拓展模块 | 拓展模块 |
| 设备 | 设备管理 |
| 定时任务与自动构建发布 | 构建发布 → 自动运行配置 |
| 账号、PIN、备份、测速核心 | 系统设置 |
接口
全部接口在 /api/v1/**,写操作需要 X-CSRF-Token(登录时返回)和会话 Cookie。
BASE=https://magichub.top:8443
# 登录,取 csrf_token
CSRF=$(curl -s -X POST $BASE/api/v1/auth/login -H 'Content-Type: application/json' \
-d '{"username":"astral","password":"******"}' | python3 -c 'import json,sys;print(json.load(sys.stdin)["csrf_token"])')
# 下面所有请求都带上:-b cookie.txt -H "X-CSRF-Token: $CSRF"
curl -c cookie.txt -s -X POST $BASE/api/v1/auth/login -H 'Content-Type: application/json' \
-d '{"username":"astral","password":"******"}' > /dev/null
改配置的常用请求:
# 新增/更新分流规则
curl -b cookie.txt -X POST $BASE/api/v1/rules -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' \
-d '{"type":"DOMAIN-SUFFIX","value":"example.com","target":"🚀 默认代理","targets":["Stash-macOS"],"devices":["*"]}'
# 调整策略组
curl -b cookie.txt -X PUT $BASE/api/v1/groups/3 -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' -d '{"name":"🚀 默认代理","type":"select","use_sources":[1,2]}'
# 改某台设备的独立配置(读出生效值 → 改 → 写回)
curl -b cookie.txt -s "$BASE/api/v1/base-config?engine=stash&platform=ios&device_id=1" \
-H "X-CSRF-Token: $CSRF" > /tmp/layer.json
# 编辑 /tmp/layer.json 里的 "content"(YAML),再:
curl -b cookie.txt -X PUT $BASE/api/v1/base-config -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' \
-d '{"content":"mtproto:\n port: 5753\n secret: 0123456789abcdef0123456789abcdef\n"}' \
--get --data-urlencode 'engine=stash' --data-urlencode 'platform=ios' --data-urlencode 'device_id=1'
接口清单(122 个)见 docs/development/接口清单与安卓客户端说明.md。
直接改库
尽量别这么做。 真要改:
ssh archon@10.0.1.2
docker exec magicpanel python3 -c "
import sqlite3; c = sqlite3.connect('/app/data/magicpanel.db')
print(c.execute('SELECT id, name, engine, platform FROM targets').fetchall())
"
archon 是用户名,NAS 的主机名是 Altair;10.0.1.2 与 10.0.1.8 分别对应 NAS 与 Mac mini,
见环境与地址速查。
改完必须:
VACUUM或至少PRAGMA wal_checkpoint(TRUNCATE)(WAL 模式)。- 重新构建发布(快照里固化了旧数据)。
- 跑一次数据自检。
线上库结构由 server/app/db.py 的 SCHEMA + 迁移定义,改结构要走代码迁移,不要手动 ALTER TABLE。
改完怎么验证
1. 数据自检
scp scripts/check_data_consistency.py archon@10.0.1.2:/tmp/check_data.py
ssh archon@10.0.1.2 "docker cp /tmp/check_data.py magicpanel:/tmp/check_data.py && \
docker exec magicpanel python3 /tmp/check_data.py /app/data/magicpanel.db"
会检查:引用完整性、命名规范、冗余覆盖、结构键越权、兜底规则顺序与范围交集、无人引用的空组。
输出分两类:
数据不规范→ 必须修(部署会被拦下)提示(不阻断)→ 可选清理(如已停用且无人引用的规则集合)
2. 产物预览
不产生构建,先看产物对不对:
curl -b cookie.txt -X POST $BASE/api/v1/base-config/preview -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' -d '{"engine":"stash","platform":"ios","device_id":1}'
或者在「基础配置」页点「预览产物」。
3. 构建校验
curl -b cookie.txt -X POST $BASE/api/v1/builds -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' -d '{"note":"改了什么"}'
返回里 results 逐目标给出 ok / errors / warnings;Mihomo 目标还会跑 mihomo -t。
4. 拉真实订阅看
curl -s "$BASE/feed/<令牌>/config.yaml" | head -40
5. 代码改动另加
cd server && ../.venv/bin/python -m pytest tests -q
npm run build
改完怎么发布
配置改动(数据变了):
# 1. 创建构建
curl -b cookie.txt -X POST $BASE/api/v1/builds -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' -d '{"note":"说明这次改了什么"}'
# 2. 校验通过后发到测试
curl -b cookie.txt -X POST $BASE/api/v1/builds/<id>/publish-to-test -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' -d '{"reason":"说明"}'
# 3. 验证没问题再发生产
curl -b cookie.txt -X POST $BASE/api/v1/builds/<id>/publish-to-prod -H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' -d '{"reason":"说明"}'
代码改动:
DEPLOY_PROXY=http://10.0.1.8:7890 bash scripts/deploy.sh
DEPLOY_PROXY 指向 Mac mini 上的 Stash 混合端口。它注入到 NAS 端的构建过程,必须用内网地址 10.0.1.8。
部署脚本会跑测试、同步代码、重建容器、等健康检查、跑数据自检、验域名。代码改了但没重新构建发布,订阅内容不会变。
回滚:面板「构建发布 → 回滚至生产」;代码问题用 git revert + 重新部署。
改配置的禁忌
- 不要在配置层写那五个结构化键(
proxies、proxy-providers、proxy-groups、rule-providers、rules),会被硬拒。 - 不要在兜底规则后面加规则,那条规则永远不生效。
- 不要用超出引擎白名单的规则类型,客户端会加载失败。
- 不要给 Mihomo 设备加
mtproto,Mihomo 没有这个能力。 - 不要建两个同「引擎+平台」的引擎平台,写入会 409。
- 不要手动改线上数据库结构,走代码迁移。
- 不要把凭据写进仓库,
scripts/check_secrets.py会拦。 - 改引擎默认配置后要核对官方文档,
scripts/check_engine_defaults.py会逐键对账。 - 别把设备独立配置当完整配置写:它只记新增项,写全量会导致上层内容被当成”这一层特有”。
- 改完记得发布:配置不发布,客户端拿到的还是旧的。