Homepage 集成 Technitium DNS Server 监控 Widget 配置指南
本指南讲解如何在 Homepage(gethomepage.dev)中通过 technitium 类型 Widget 接入 Technitium DNS Server,将 DNS 服务的查询总量、缓存命中、递归解析、拦截/丢弃等核心统计以一目了然的小部件形式呈现在个人起始页上。读完本文,你将掌握 Widget 的完整配置语法、node 与 range 参数的语义、可展示字段清单与默认值,以及这些配置在源码层面如何被解析并调用 Technitium 的 Dashboard API。
Widget 是什么:一次快速配置概览
Technitium DNS Server 是一个自托管的 DNS 服务器,支持多节点集群、权威/递归/缓存/拦截等多种查询处理路径。Homepage 的 technitium Widget 会调用 Technitium 的 Dashboard 统计 API,拉取一段时间窗口内的查询统计数据并渲染为数值卡片。
在 Homepage 的 services.yaml 中,为某个服务配置 Widget 的最小示例(源自 docs/widgets/services/technitium.md)如下:
widget:
type: technitium
url: <url to dns server>
key: biglongapitoken
node: <node dns name or cluster> # optional, defaults to current node
range: LastDay # optional, defaults to LastHour
四个字段的职责:
| 字段 | 必填 | 说明 |
|---|---|---|
type |
是 | 固定为 technitium,用于在 src/widgets/widgets.js 的 Widget 注册表中匹配实现(见其中 technitium, 条目) |
url |
是 | Technitium DNS Server 的访问地址 |
key |
是 | 调用 API 所用的 Token |
node |
否 | 指定统计来自哪个集群节点,默认返回当前执行 API 的节点 |
range |
否 | 统计时间窗口,默认 LastHour |
可展示字段与默认值
Widget 允许配置 fields 来定制展示哪些统计项,最多 4 个,可选项为:
fields:
- totalQueries # 查询总数
- totalNoError # 成功(无错误)查询数
- totalServerFailure # 服务器故障数
- totalNxDomain # NXDOMAIN(域名不存在)数
- totalRefused # 被拒绝的查询数
- totalAuthoritative # 权威解析数
- totalRecursive # 递归解析数
- totalCached # 缓存命中数
- totalBlocked # 被拦截(如广告拦截)数
- totalDropped # 被丢弃的查询数
- totalClients # 活跃客户端数
若未配置 fields,默认展示以下 4 项:
fields:
- totalQueries
- totalAuthoritative
- totalCached
- totalServerFailure
这两个行为在组件源码中有明确体现:src/widgets/technitium/component.jsx 第 7 行定义了 MAX_ALLOWED_FIELDS = 4,第 9 行导出了 technitiumDefaultFields 数组;组件渲染时,若用户未提供 fields 则回退到默认 4 项,若超过 4 项则通过 widget.fields.slice(0, MAX_ALLOWED_FIELDS) 截断。
字段的展示标签来自 public/locales/en/common.json 中 technitium 一段的翻译映射(如 totalQueries → "Queries"、totalNoError → "Success"、totalBlocked → "Blocked"),因此在不同语言环境下会显示对应的本地化文案。
API Key 的获取
key 需要从 Technitium DNS Dashboard 中生成。需要注意:应该从专门的 API 专用用户(a special API specific user)生成,而不是使用管理员账号的 Token。在 Technitium 的管理界面中创建独立用户并为其签发 API Token,可以有效缩小权限暴露面,避免常规 Web 登录凭据被用于 API 调用。
Node 参数:决定统计来自哪个节点
node 决定 Widget 返回的是哪个集群节点的统计数据,取值有三种情况:
- 不填:返回 API 请求所执行的那台节点的统计数据(默认行为);
cluster:返回整个集群所有节点的聚合(aggregate)统计;- 节点域名:例如填写某个节点的域名,返回该特定节点的统计。
该参数在请求层面直接透传给 Technitium 的 Dashboard API。从源码看,组件在构造 API 参数时将其作为 node 查询参数传递(src/widgets/technitium/component.jsx 第 16-19 行):
const params = {
node: widget.node ?? "",
type: widget.range ?? "LastHour",
};
Range 参数:统计时间窗口
range 决定拉取多长历史窗口的统计数据,取值直接取自 Technitium 官方 API 文档(Dashboard API Calls)中定义的 "type" 字段,可选值为:
LastHour(默认)LastDayLastWeekLastMonthLastYear
例如,想查看最近 24 小时的 DNS 运行概况,可将 range 设为 LastDay,即本篇开头示例中的用法。
源码视角:Widget 如何调用 Technitium API
请求构造与响应映射
Widget 的 API 行为定义在 src/widgets/technitium/widget.js:
const widget = {
api: "{url}/api/{endpoint}?token={key}&utc=true",
proxyHandler: genericProxyHandler,
mappings: {
stats: {
endpoint: "dashboard/stats/get",
validate: ["response", "status"],
params: ["node", "type"],
map: (data) => asJson(data).response?.stats,
},
},
};
可以拆解出三条关键事实:
- 接口端点:实际请求的 URL 形如
{url}/api/dashboard/stats/get?token={key}&utc=true&node=...&type=...,即调用 Technitium 的dashboard/stats/get统计接口,并固定附加utc=true表示使用 UTC 时间。 - 参数透传:
params: ["node", "type"]声明了可透传的查询参数,正好对应配置文件中的node与range(range在请求层以type为名传递)。 - 响应提取:接口返回的 JSON 中,统计主体位于
response.stats字段,map函数将其提取出来交给前端渲染;validate声明了需要校验response与status字段,配合genericProxyHandler(src/utils/proxy/handlers/generic.js)完成代理与数据校验。
配置解析链路
配置项 node 与 range 在服务配置解析阶段被专门处理。在 src/utils/config/service-helpers.js 中,range 被列入 widgetData 的解构清单(第 431-432 行),并在第 668-671 行针对 technitium 类型做条件赋值:
if (type === "technitium") {
if (node !== undefined) widget.node = node;
if (range !== undefined) widget.range = range;
}
即:只有用户显式填写了 node 或 range,它们才会进入最终的 widget 配置对象;未填写时由组件层使用默认值(空字符串与 LastHour)。
数据渲染:数值与占比
组件拿到 stats 数据后,用统一翻译函数格式化数值,并为大多数指标计算占 totalQueries 的百分比(src/widgets/technitium/component.jsx 第 55-60 行的 toPercent 函数,通过 common.percent 翻译模板输出,最多保留两位小数)。因此界面上会呈现类似 50 (50) 的「数值 + 百分比」形式,便于直观判断成功率、失败率与缓存命中率;totalQueries 与 totalClients 则只显示绝对值。加载中状态会展示各字段的占位块,出错时则通过 Container 的错误态展示错误信息。
测试验证:行为有据可依
该 Widget 的行为由两层测试保障:
- src/widgets/technitium/widget.test.js 通过
expectWidgetConfigShape校验 widget 配置结构(端点、参数、映射等)符合框架约定; - src/widgets/technitium/component.test.jsx 验证了「未配置
fields时回退到 4 个默认字段并只渲染 4 个块」「配置自定义字段后按值渲染,且占比以括号形式附带」两个关键行为。
完整配置示例
将上述知识组合起来,一个面向多节点集群的完整配置如下:
- Technitium DNS:
icon: sh-technitium
href: http://dns.example.com:5380
widget:
type: technitium
url: http://dns.example.com:5380
key: biglongapitoken
node: cluster # 聚合所有节点统计
range: LastDay # 查看最近 24 小时
fields:
- totalQueries
- totalBlocked
- totalNoError
- totalServerFailure
若只关心单节点、使用默认时间窗口,也可以简化为只填 url 与 key 两项必填字段。相关配置文件的更多上下文可参考 docs/configs/services.md 与 src/skeleton/services.yaml,Widget 列表总览见 docs/widgets/services/index.md。
常见问题与注意事项
- 403 / Token 无效:确认
key来自 Technitium Dashboard 中专门签发的 API Token(建议使用 API 专用用户),而不是普通 Web 登录会话; - 统计不更新:
range仅支持文档列出的五个枚举值,非法值会被 Technitium 端拒绝;同时注意utc=true是固定附加参数,统计窗口按 UTC 计算; - 集群节点不匹配:
node填写的必须是 Technitium 集群中实际的节点域名,或使用字面量cluster获取聚合数据; - 字段不生效:
fields最多 4 项,超出部分会被源码自动截断;拼写需与允许字段清单完全一致,否则无法匹配对应统计项。
借助这个 Widget,你可以在 Homepage 起始页上一屏掌握自建 DNS 的查询负载、缓存效果与拦截情况,无需频繁登录 Technitium 管理面板即可完成日常巡检。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.21 K635- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python70
jforgamejforgame是一个一站式游戏服务器开发框架。包含游戏服务器开发所需要的各种组件,比如网关,socket服务端与客户端,自定义高效消息编解码,游戏热更新,游戏通用工具等等。包含游戏服,跨服,匹配服,后台管理系统等实现,同时提供大量业务案例以供学习。亦可用于其他socket应用,例如及时聊天等。Java161
fizz-gateway-nodeAn Aggregation API Gateway in Java . FizzGate 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。Java90
certd开源SSL证书管理工具;全自动证书申请、更新、续期;通配符证书,泛域名证书申请;证书自动化部署到阿里云、腾讯云、主机、群晖、宝塔;https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署JavaScript120
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python300