Mafl 0.15.4 配置参数详解
Mafl v0.15.4 唯一配置文件 config.yml 逐参数实测:全局参数出厂默认值回读、卡片字段与 base/ip-api/openweathermap 三类型 options/secrets 结构、TCP 状态探测机制与端口缺省陷阱、WebSocket 热更新双路径生效链路,含未知键透传、tags 崩溃、本地图标 404 三项实测发现。
Mafl 0.15.4 配置参数详解
目标:逐参数讲清 Mafl v0.15.4 的唯一配置文件
config.yml——全局参数出厂默认值、服务卡片字段、三种服务类型(base/ip-api/openweathermap)的options/secrets结构、状态检查机制与配置生效链路;每个参数均给出实测配置与/api/settings、服务端 API 的核对回显,并沉淀「未知键静默透传」「tags 类型崩溃」「本地图标挂载 404」三项实测发现。本文接续 《Mafl 0.15.4 Docker Compose 部署指南》的部署成果,全部命令与回显已在 Docker Engine 29.9.2(Compose v5.6.1)环境实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64),Docker Engine 29.9.2(Compose v5.6.1)
- Mafl 版本:v0.15.4(镜像
hywax/mafl:v0.15.4,底座 Alpine 3.20.1 + Node.js v20.15.1,Nuxt 3.12.3 / Nitro 2.9.7) - 配置文件:宿主
/opt/mafl/mafl/config.yml↔ 实例/app/data/config.yml(挂载映射) - 访问形态:
http://127.0.0.1:8132/(宿主端口 8132 → 实例端口 3000) - 核对端点:
GET /api/settings(返回合并默认值后的生效配置,secrets字段被服务端剔除) - 编排目录:
/opt/mafl/(示例路径)
二、前置条件
- 已按 《Mafl 0.15.4 Docker Compose 部署指南》完成部署,
curl http://127.0.0.1:8132/api/health返回 200; - 具备
config.yml的编辑权限(配置即数据,改文件即改参数,无 GUI 设置后台); - 本文实测基线配置(含两个分组、四张卡片、全局标签):
title: Quzuo Home Page
lang: zh
theme: dark
checkUpdates: false
behaviour:
target: _self
tags:
- name: Infra
color: green
- name: Demo
color: blue
layout:
grid:
small: 1
medium: 2
large: 3
xlarge: 4
services:
Infrastructure:
- title: Mafl Panel
description: 面板实例自身(状态应为在线)
link: http://127.0.0.1:3000/
icon:
name: mdi:view-dashboard
wrap: true
color: '#3dbcf3'
status:
enabled: true
tags:
- Infra
Tools:
- title: Dead Service
description: 指向未监听端口(状态应为离线)
link: http://127.0.0.1:3999/
icon:
name: mdi:power-plug-off
wrap: true
status:
enabled: true
interval: 30
tags:
- Demo
- title: Docs Site
description: 官方文档(无状态检查)
link: https://mafl.hywax.space/
icon:
name: simple-icons:mdbook
wrap: true
- title: My Exit IP
description: 服务端查询出口 IP(ip-api 类型)
type: ip-api
icon:
url: test.svg
background: '#eee'
tags:
- Demo
三、参数查看与修改方式
3.1 编辑 config.yml
Mafl 没有 --help、没有管理 CLI、没有设置页面——唯一的修改方式就是编辑 config.yml:
vi /opt/mafl/mafl/config.yml
3.2 回读生效配置(/api/settings)
改完文件后,最可靠的「参数现在到底是什么值」核对手段是回读服务端合并后的配置。出厂默认值会补齐你没写的字段:
curl -s http://127.0.0.1:8132/api/settings | python3 -m json.tool | head -20
{
"title": "Quzuo Home Page",
"lang": "zh",
"theme": "dark",
"checkUpdates": false,
"layout": {
"grid": {
"small": 1,
"medium": 2,
"large": 3,
"xlarge": 4
}
},
"behaviour": {
"target": "_self"
},
输出节选(实测首尾)。把文件临时改成缺省形态(只留 title 与 services)重启后回读,可看到全部出厂默认值:
{"title":"Mafl Home Page","lang":"en","theme":"system","checkUpdates":true,"layout":{"grid":{"small":2,"medium":2,"large":3,"xlarge":4}},"behaviour":{"target":"_blank"},"tags":[],"services":[]}
⚠️ 注意:该响应里
services: []且带"error"字段时说明配置加载失败(见第九章排障),空数组不代表你写了空服务。
3.3 配置生效链路(两条路径,实测)
路径 A:浏览器页面打开时热更新。 Mafl 的配置文件监听器注册在 WebSocket 会话建立之后——有活跃页面(peer)在线时,保存 config.yml 秒级生效,无需重启。实测用 Node 内置 WebSocket 模拟一个在线页面:
docker exec mafl-v0154-web node --experimental-websocket -e '
const ws=new WebSocket("ws://localhost:3000/api/websocket");
ws.onopen=()=>console.log("WS OPEN");
ws.onmessage=e=>console.log("RECV",e.data);
setTimeout(()=>process.exit(0),12000);' &
sed -i 's/title: Quzuo Home Page WS/title: Quzuo Home Page WS2/' /opt/mafl/mafl/config.yml
WS OPEN
RECV {"event":"config:update"}
服务端日志同步出现:
mafl-v0154-web | Peer connected #1 ([::1]:50412)
mafl-v0154-web | Set "main" config
页面标题随即变为新值(实测回显):
curl -s http://127.0.0.1:8132/ | grep -oE "<title>[^<]*</title>"
<title>Quzuo Home Page WS2</title>
路径 B:无页面在线时必须重启。 实测:没有任何浏览器连接时修改 title,等待 10 秒以上页面不变、日志无 Set "main" config;执行 docker compose restart 后新值生效。生产上以路径 B 为准,路径 A 视为「开着配置页编辑时的便利特性」。
四、参数总览
全局参数(默认值经缺省配置回读实测核对):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | Mafl Home Page | 页面标题(浏览器标签页与顶栏) |
lang | string | en | 界面语言:en/ru/zh/hi/es/ar/pl/fr/de/gr/nl |
theme | string | system | 主题:system/light/dark/deep/sepia/bluer |
checkUpdates | boolean | true | 页面底部新版本提示横幅(不自动升级) |
behaviour.target | string | _blank | 卡片全局跳转方式,可被卡片级 target 覆盖 |
layout.grid | object | small 2 / medium 2 / large 3 / xlarge 4 | 四档屏幕断点的网格列数,取值 1-12,可只写一档 |
tags | array | [] | 全局标签定义(name+color),v0.10.0 引入 |
services | array 或 map | [](缺失则报错) | 卡片扁平列表或「组名: 列表」分组映射 |
服务卡片参数(三种类型通用):
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | 无 | 卡片标题 |
description | string | 无 | 标题下方副标题 |
link | string | 无 | 点击跳转地址,同时是状态探测目标 |
target | string | 继承 behaviour.target | 本卡片跳转方式(优先级更高) |
icon.name | string | 无 | Iconify 图标名(集合名:图标名) |
icon.url | string | 无 | 本地图标文件名(见 9.4 实测限制) |
icon.wrap | boolean | 无 | 图标是否加衬底 |
icon.color / icon.background | string | 无 | 图标色 / 衬底色(十六进制需引号) |
status.enabled | boolean | false | 开启 TCP 状态灯 |
status.animation | boolean | true | 状态灯动画 |
status.interval | number | 60 | 状态刷新间隔(秒) |
tags | array | [] | 引用全局标签名,或内联 {name,color} |
type | string | base | 服务类型:base/ip-api/openweathermap |
options | map | 无 | 类型专属参数(如天气经纬度) |
secrets | map | 无 | 类型专属密钥(服务端使用,绝不下发) |
五、全局参数详解
5.1 title
页面标题。实测 title: Quzuo Home Page 渲染为 <title>Quzuo Home Page</title>(回显见 3.3)。缺省时回读值为 Mafl Home Page。
5.2 lang
界面语言,支持 11 种:en、ru、zh、hi、es、ar、pl、fr、de、gr、nl。实测 lang: zh 后服务端渲染中文界面;未设置时服务端按浏览器语言自动协商(实测无 cookie 首次响应会下发 set-cookie: i18n_redirected=en)。中文用户建议显式写 lang: zh,避免自动协商漂移。
5.3 theme
内置六主题:system(跟随系统,默认)、light、dark、deep、sepia、bluer。实测 theme: dark 在 /api/settings 回显 "theme": "dark",SSR HTML 即带主题标记渲染。
5.4 checkUpdates
新版本横幅开关,默认 true。开启时服务端周期性检查 GitHub Release,发现新版在页面底部提示,不会自动更新;官方文档建议自动升级场景使用 watchtower。生产建议 checkUpdates: false 关闭外呼、由运维手动升级(见 《Mafl 0.15.4 日常运维手册》篇升级章节)。
5.5 behaviour.target
全局跳转方式,取值 _blank/_self/_parent/_top(浏览器语义),默认 _blank。实测 behaviour.target: _self 回显生效;卡片级 target 字段优先级高于全局(官方文档明示,schema 中卡片 target 独立存在)。
5.6 layout.grid
v0.14.0 引入的响应式列数,四档断点 small/medium/large/xlarge,各档取值范围 1-12,可只写一档其余自动。实测写全四档 1/2/3/4 回显一致;缺省为 2/2/3/4。
5.7 tags
全局标签表,卡片按名引用。实测:
tags:
- name: Infra
color: green
卡片写 tags: [Infra](字符串列表)即可关联;服务端把字符串名解析回完整标签对象(含颜色),未定义的名字按 {name: 原名, color: "blue"} 兜底(实测未知标签名不报错)。标签类型必须是数组——写成字符串直接崩溃,见 9.2。
六、服务卡片参数详解
6.1 title / description / link
三件套构成卡片主体:标题、副标题、跳转链接。link 同时被状态检查复用为探测目标(第八章)。三者都是 schema 可选字段——全拼错也不报错(见 9.3 未知键透传),配置后务必用 /api/settings 回读核对。
6.2 icon
四种图标来源(官方文档):Iconify 名(mdi:view-dashboard、simple-icons:mdbook 等 20 万+图标集)、Emoji、外部 URL、本地文件名。实测 Iconify 名与 wrap/color/background 组合均正常回显:
icon:
name: mdi:view-dashboard
wrap: true
color: '#3dbcf3'
icon.url: test.svg 的本地挂载形态在 v0.15.4 实测不可用(404,机制与结论见 9.4)。
6.3 status
status:
enabled: true
interval: 30
enabled 默认 false(不开则无状态灯、API 响应无 ping 字段,实测见第八章);interval 默认 60 秒,官方明确不建议调小(服务多时探测压力大);animation 默认 true。
6.4 type / options / secrets
type 缺省为 base(不写即纯链接卡片)。options 承载类型专属参数、secrets 承载密钥。密钥安全性实测:含 secrets 的配置经 /api/settings 回读时该字段被服务端整体剔除(实测响应中检索不到 secrets 键),即天气 API Key 只存活在服务端进程内,浏览器不可见。
七、服务类型详解
7.1 base(默认)
纯链接卡片,即 6.1-6.3 的全部字段。状态探测响应实测(在线目标):
curl -s "http://127.0.0.1:8132/api/services/base?id=9263c3e0-9579-4ce4-acbf-fbb686e71ad9"
{"ping":{"status":true,"time":0},"data":{}}
7.2 ip-api
显示服务器出口 IP 信息(请求由服务端代发,浏览器不接触第三方 API)。配置:
- title: My Exit IP
type: ip-api
实测端点响应(服务端所在网络出口):
curl -s --max-time 20 "http://127.0.0.1:8132/api/services/ip-api?id=7589fa22-f00f-4b10-87d4-b9c6c7ef4885"
{"data":{"ip":"182.54.113.29","place":"Zhongwei, Ningxia","country":"cn"}}
不带 id 直接调用返回 400:{"statusCode":400,"statusMessage":"ID can not be null"}——所有 /api/services/* 端点都以卡片 UUID 为入参。
7.3 openweathermap
天气卡片,数据源 OpenWeatherMap。配置(官方文档字段 + 服务端 schema 核对):
- title: Weather
type: openweathermap
options:
lat: 51.5085
lon: -0.1257
units: metric
secrets:
apiKey: ${OWM_API_KEY}
options.lat/lon:必填经纬度(可从 latlong.net 获取);options.units:metric/imperial/standard,默认metric;secrets.apiKey:OpenWeatherMap 个人 API Key。属第三方密钥,按规范用${OWM_API_KEY}占位,注入方式:export OWM_API_KEY=<你的key>后由配置渲染工具写入,或直接写明文于受权限保护的config.yml(该文件仅服务端可读)。
实测无 Key 调用该端点返回 400(缺参即拒)。服务端对天气结果做缓存(defineCachedFunction,maxAge 1440 秒,按经纬度作缓存键),高频刷新页面不会放大对 OpenWeatherMap 的调用。
八、状态检查机制实测
状态灯的本质(服务端源码 @network-utils/tcp-ping 路径实测核对):对 link 解析出的主机 + 端口发起 1 次 TCP 连接,成功即在线。三个实测形态:
# 在线目标(127.0.0.1:3000 有监听)
curl -s "http://127.0.0.1:8132/api/services/base?id=$ID"
{"ping":{"status":true,"time":0},"data":{}}
# 离线目标(127.0.0.1:3999 无监听)
curl -s "http://127.0.0.1:8132/api/services/base?id=$ID2"
{"ping":{"status":false,"time":null},"data":{}}
# 未开启 status.enabled 的卡片
curl -s "http://127.0.0.1:8132/api/services/base?id=$ID3"
{"data":{}}
端口缺省陷阱:链接不带显式端口时探测端口 80(源码 url.port || "80"),https://example.com/ 探的是 80 不是 443——HTTPS 服务请写全端口(如 https://example.com:8443/),否则状态灯恒离线。这是 TCP 探测的固有精度边界:端口通 ≠ 应用健康。
九、配置容错与校验(实测发现)
9.1 缺 config.yml:进程存活但全站 500
挂载目录里没有 config.yml 时,启动日志 Error: Config not found,健康检查照常通过、页面全部 500(实测回显见部署篇 4.2)。配置加载失败不会让进程退出。
9.2 tags 类型错误:先于 schema 校验崩溃
tags: work # 错误:写成字符串
实测日志:
mafl-v0154-web | TypeError: tags.reduce is not a function
mafl-v0154-web | at createTagMap (file:///app/server/chunks/_/config.mjs:86:15)
页面 500,/api/settings 返回缺省配置并携带 "error":"tags.reduce is not a function" 字段——这个 error 字段是定位配置加载失败的第一现场。根因:标签映射构建发生在 zod 校验之前,tags 非数组直接抛原生 TypeError。
9.3 未知键静默透传:拼错不报错
services:
- titel: typo
实测:无报错、无告警,titel 原样进入 /api/settings 响应({"titel":"typo","id":"...","tags":[]}),页面渲染一张无标题空卡片。Mafl 的 zod schema 非严格模式,拼写错误只能靠回读自查,没有配置校验端点。
9.4 本地图标挂载 404(v0.15.4 实测限制)
官方文档声明挂载 /app/public/icons 后按文件名引用本地图标。实测在 compose 中加挂 ./icons/:/app/public/icons/、放入 test.svg、配置 icon.url: test.svg 并重建实例:
docker exec mafl-v0154-web ls -la /app/public/icons/
-rw-r--r-- 1 root root 113 Nov 2 18:11 test.svg
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8132/icons/test.svg
404
文件在实例内可见但不被服务。机制:Nitro 2.9.7 的静态资源路由表在构建期固化进服务端代码(实测 runtime.mjs 内逐条列出 /favicons/... 等出厂文件),运行时新增文件不注册路由;/favicons/favicon.ico(构建期已存在)实测 200 佐证。结论:v0.15.4 本地图标/自定义 favicon 挂载实际不可用,图标请用 Iconify 名、Emoji 或外部 URL 三种来源。
十、生产配置模板
适用场景:家庭实验室单节点服务器(16GB 内存 / NVMe SSD / 服务 10-30 个),面板仅内网访问:
title: Homelab
lang: zh
theme: system
checkUpdates: false
behaviour:
target: _blank
tags:
- name: core
color: green
- name: media
color: blue
- name: net
color: orange
layout:
grid:
small: 1
medium: 2
large: 3
xlarge: 4
services:
核心服务:
- title: NAS
description: Synology DS223
link: http://192.168.1.10:5000/
icon:
name: mdi:nas
wrap: true
status:
enabled: true
tags:
- core
- title: Router
description: Keenetic Peak
link: http://192.168.1.1/
icon:
name: mdi:router-wireless
wrap: true
status:
enabled: true
tags:
- net
媒体服务:
- title: Music
description: Navidrome
link: http://192.168.1.10:4533/
icon:
name: mdi:music-circle
wrap: true
status:
enabled: true
tags:
- media
- title: Weather
description: 本地天气
type: openweathermap
options:
lat: 38.9
lon: 121.6
units: metric
secrets:
apiKey: ${OWM_API_KEY}
要点:checkUpdates: false 断掉对 GitHub 的周期外呼;状态灯只对常驻服务开启、interval 保持默认 60 秒;HTTPS 服务显式写端口;secrets 用环境变量注入并收紧 config.yml 文件权限(chmod 600)。
十一、常见问题(FAQ)
Q1: 改了配置页面纹丝不动?
A: 无浏览器在线时热更新监听未激活,docker compose restart 即可(实测链路见 3.3)。
Q2: /api/settings 里出现 error 字段但进程没崩?
A: 配置加载失败被兜底为「缺省配置 + error 信息」,按 error 内容改文件。实测 tags.reduce is not a function 即此类(9.2)。
Q3: 卡片图标不显示?
A: 依次检查:Iconify 名格式必须 集合:图标(如 mdi:home);本地图标挂载在 v0.15.4 实际 404(9.4),改用 Iconify/Emoji/URL。
Q4: 状态灯与实际情况不符? A: TCP 探测只看端口,默认探 80(8.章端口陷阱);防火墙放行但应用未监听时也会显示在线。状态灯只作粗筛。
Q5: 天气卡片一直转圈?
A: 检查 secrets.apiKey 是否有效与 options.lat/lon 是否数值型;服务端缓存 1440 秒,改配置后旧值可能滞留到缓存过期。
十二、参考链接
- 官方配置文档:https://mafl.hywax.space/reference/configuration.html
- Base 服务文档:https://mafl.hywax.space/services/base.html
- OpenWeatherMap 服务文档:https://mafl.hywax.space/services/openweathermap.html
- 官方仓库:https://github.com/hywax/mafl
- 站内相关:《Mafl 0.15.4 Docker Compose 部署指南》、《Mafl 0.15.4 日常运维手册》、《Navidrome 0.64.2 Docker Compose 部署指南》(模板中 Music 卡片的实际部署)