homepage v2.7.0 配置参数详解

讲清 homepage v2.7.0 五个 YAML 配置文件的职责、生效机制与全量参数:settings/services/bookmarks/widgets/docker 与环境变量占位符注入,附配置生效链核对、/api/validate 自检与坏 YAML 排障实录。

homepage自托管仪表盘2026/10/25

homepage v2.7.0 配置参数详解

‍‍​​‌​> 目标:系统讲清 homepage v2.7.0 的 YAML 配置体系——5 个配置文件的职责边界与生效机制、settings.yaml 全局参数、services.yaml 服务与 widget、bookmarks.yaml 书签、widgets.yaml 信息组件、docker.yaml Docker 集成,以及环境变量占位符注入机制;每个文件均给出实测配置与验证结果(配置生效链从服务端 API 逐项核对),并沉淀坏 YAML 容错与 /api/validate 配置自检的排障实录。本文接续《homepage v2.7.0 Docker Compose 部署指南》的部署成果。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64),Docker Engine 29.9.2(Compose v5.6.1)
  • homepage 版本:v2.7.0(官方镜像 ghcr.io/gethomepage/homepage,编排名 homepage-v2.7.0-stack)
  • 配置目录:宿主 /opt/homepage/config ↔ 应用 /app/config(部署篇的挂载映射)
  • 访问形态:http://homepage.example.com:8129(HTTP 直连,已开启密码门控,示例密码 q1w2e3r4);另有 https://homepage.example.com:8130(Caddy HTTPS 反代)
  • 同网络示例服务:homepage-demo-nginx(Nginx 示例容器,用于 Docker 集成与探针演示)
  • 本文 YAML 修改均在配置目录直接编辑保存,除 docker.yaml 外均免重启生效(生效机制见第二章)

二、配置体系总览

2.1 五个配置文件的职责

首次启动后配置目录共 5 个 YAML + 1 个日志目录(ls /opt/homepage/config 实测):

bookmarks.yaml
docker.yaml
kubernetes.yaml
logs
settings.yaml
services.yaml
widgets.yaml
文件职责改动生效方式
settings.yaml全局设置:标题/描述/主题/色板/语言/布局/搜索/页签/PWA/认证外链保存即生效
services.yaml服务分组与服务卡片,widget 挂载与探针保存即生效
bookmarks.yaml书签分组与书签项保存即生效
widgets.yaml页头信息组件(时间/搜索/天气等)保存即生效
docker.yamlDocker 实例接入(socket/HTTP API/TLS/socket proxy)需重启服务
kubernetes.yamlKubernetes 集群接入(同 docker.yaml 的 K8s 版)需重启服务

2.2 配置数据流(实测)

配置修改后如何到达浏览器——实测 homepage v2.7.0 的下发链路:

  1. 页面 SSR 时,配置以 JSON 形式注入 HTML 内的 __NEXT_DATA__ 脚本块:全局设置在 props.pageProps.initialSettings,服务/书签/信息组件以 props.pageProps.fallback 里的 /api/services、/api/bookmarks、/api/widgets 端点路径做键预取;
  2. 登录会话下这些 API 可直接访问,curl /api/services 返回服务分组完整 JSON;
  3. widget 实时数据由前端按需调用服务端代理端点(/api/widgets/*、/api/services/proxy),API Key 不出现在浏览器侧;
  4. 配置自检端点 /api/validate 返回所有配置文件的解析错误数组(无错时 [],见第八章案例 4)。

⚠️ 注意:官方文档部分链接提到的 /api/config 端点在 v2.7.0 并不存在(实测 404),核对配置生效请用 /api/services、/api/bookmarks 或解析页面 __NEXT_DATA__,不要按旧帖子的路径猜。

2.3 YAML 语法与文件骨架

所有配置文件都是「顶层为数组、元素为单键映射」的结构(分组名作键,组员作数组)。对 YAML 不熟的读者记住三条即可:① 缩进用空格且同级对齐;② 分组名后跟冒号,成员列表缩进一级再写 -;③ 含中文/特殊字符的值建议不加引号直接写,含 {{}} 占位符的值不要加引号(避免模板替换后类型漂移)。改完配置若页面异常,先跑 curl /api/validate(第八章案例 4)。

三、settings.yaml 全局参数

3.1 实测配置

title: 我的仪表盘
description: homepage 自托管服务导航与状态面板
language: zh-Hans
theme: dark
color: slate
headerStyle: boxedWidgets
target: _blank
layout:
  媒体服务:
    style: row
    columns: 3
  下载工具:
    style: row
    columns: 3
  系统工具:

生效验证(从页面 __NEXT_DATA__ 的 initialSettings 提取,实测输出):

title: 测试变量仪表盘
description: homepage 自托管服务导航与状态面板
theme: dark | color: slate | language: zh-Hans | headerStyle: boxedWidgets | target: _blank
layout: {"媒体服务": {"style": "row", "columns": 3}, "下载工具": {"style": "row", "columns": 3}, "系统工具": null}

💡 说明:title 显示为「测试变量仪表盘」而非「我的仪表盘」,正是因为环境变量占位符替换生效(title: "{{HOMEPAGE_VAR_DASHNAME}}",见第八章案例 3)——这同时证明了 settings.yaml 的模板渲染机制。layout 里 系统工具: 为空值时解析为 null,即「不指定布局选项、按默认渲染」,分组名仍会被识别。

3.2 常用参数表(实测值列为本环境实际取值)

参数类型默认说明本环境实测值
title字符串Homepage页面标题,支持 {{HOMEPAGE_VAR_*}} 占位符测试变量仪表盘(经变量注入)
description字符串无页面描述(SEO/PWA 用)homepage 自托管服务导航与状态面板
language字符串en界面语言,简体中文 zh-Hans、繁体 zh-Hant,全列表见官方文档zh-Hans
themedark / light跟随系统暗色写 dark,亮色写 lightdark
color22 种色板名slateslate/stone/gray/red/orange/amber/yellow/lime/green/emerald/teal/cyan/sky/blue/indigo/violet/purple/fuchsia/pink/rose/zinc/magentaslate
headerStyleunderlined / boxed / clean / boxedWidgetsunderlined页头信息组件的四种样式boxedWidgets
target_self / _blank_blank服务与书签链接的默认打开方式_blank
startUrl字符串无打开 PWA 时的起始页签未设置
backgroundImage字符串无背景图 URL,配合 backgroundOpacity/backgroundFilters未设置
favicon字符串无自定义 favicon 路径未设置
layout映射无按分组名定制布局,键为 services/bookmarks 的分组名见 3.1
tabs数组无多页签定义,服务里用分组名前缀 页签名/分组名 归属页签未设置
hideVersion布尔false隐藏页脚版本号未设置
statusStyledot / basicbasic服务状态角标样式未设置
useEqualHeights布尔false卡片等高未设置
quicklaunch映射无快捷搜索行为(hideEmptyServices、iconStyle 等),搜索框由 widgets.yaml 的 search 提供未设置
linkTarget/webSearch 等——其余低频参数见官方 Settings 文档—

3.3 layout 布局子参数

每个分组键下可用的布局选项(实测使用 style + columns):

子参数取值说明
stylerow / column该分组内卡片排列方向;row 时卡片横向铺开
columns数字列数(style 为 row 时生效),实测 columns: 3
icon图标路径分组标题左侧图标
header布尔是否隐藏分组标题
collapsed布尔初始折叠
iconsOnly布尔只显示图标不显示名称
servicesMax / bookmarksMax数字单列最大条数,超出换列
nestedGroups布尔启用嵌套分组渲染

四、services.yaml 服务与 widget

4.1 实测配置

- 媒体服务:
    - Jellyfin:
        icon: jellyfin.png
        href: http://192.168.146.128:8096/
        description: 电影与剧集媒体库
        ping: demo-app.internal
        siteMonitor: http://demo-app.internal/
    - Emby:
        icon: emby.png
        href: http://192.168.146.128:8097/
        description: 备用媒体服务
- 下载工具:
    - qBittorrent:
        icon: qbittorrent.png
        href: http://192.168.146.128:8080/
        description: BT/PT 下载器
- 系统工具:
    - 示例站点:
        icon: mdi-web
        href: http://demo-app.internal/
        description: Nginx 示例服务(容器状态演示)
        server: my-docker
        container: homepage-demo-nginx
        siteMonitor: http://demo-app.internal/

实测 /api/services 返回(截取「系统工具」组,「示例站点」完整条目):

{
 "name": "示例站点",
 "icon": "mdi-web",
 "href": "http://demo-app.internal/",
 "description": "Nginx 示例服务(容器状态演示)",
 "server": "my-docker",
 "container": "homepage-demo-nginx",
 "siteMonitor": "http://demo-app.internal/",
 "weight": 100,
 "type": "service",
 "widgets": []
}

4.2 服务级参数表

参数必填说明
href是点击卡片跳转的地址
icon建议图标名(内置图标库名称如 jellyfin.png、MDI 图标如 mdi-web),或本地路径 /icons/xxx.png,或完整 URL
description建议卡片描述文字
server否绑定 docker.yaml 里的 Docker 实例名,配合 container 显示容器状态
container否绑定的容器名,用于状态角标与资源统计
ping否ICMP 探针目标(主机名/IP),卡片角标显示真延迟;IPv4
siteMonitor否HTTP 探针目标(URL),用 HEAD 请求探测并显示响应时间与状态码
weight否组内排序权重,实测默认 100
target否覆盖全局 target
hide否隐藏卡片但保留数据(如只想看 widget:hide: [links, status])
widgets否挂载的服务 widget 数组(见 4.3),一个服务可挂多个

⚠️ 探针注意:ping 走 ICMP,容器内需具备相应能力,失败时角标会显示异常;siteMonitor 是 HTTP HEAD 探测,两者作用不同——前者测网络可达,后者测服务可用。实测中 demo-app.internal 两条探针路径均工作正常(容器同网络可解析)。

4.3 服务 widget 挂载(以官方示例为模板)

widget 挂在服务条目的 widget 键下(一个服务可挂多个时用 widgets 数组)。以官方 Emby 示例为例:

- Emby:
    icon: emby.png
    href: http://emby.host.or.ip/
    description: Movies & TV Shows
    widget:
      type: emby
      url: http://emby.host.or.ip
      key: {{HOMEPAGE_VAR_EMBY_KEY}}

widget 通用参数(全 widget 适用,取自官方文档):

参数说明
typewidget 类型名(100+,如 emby/plex/qbittorrent/sonarr/glances)
url服务 API 地址
keyAPI Key,建议用 {{HOMEPAGE_VAR_*}}/{{HOMEPAGE_FILE_*}} 占位符注入(见第七章)
fields显示字段筛选,如 [tracks, albums]
cache响应缓存秒数,减轻后端压力
refreshInterval前端刷新间隔毫秒数
headers自定义请求头(映射)
username/password部分 widget 用账号密码而非 key
method/mappingscustomapi widget 自定义请求

widget 的指标块支持阈值高亮 highlight(按数值/字符串规则把指标染成 good/warn/danger 三色,规则类型与操作符见《homepage 介绍与选型指南》4.1 的对比表)。homepage 对 widget 请求做服务端代理,key 不会下发到浏览器——这是它与「纯前端起始页」的本质安全差异。

五、bookmarks.yaml 书签

5.1 实测配置

- 开发:
    - GitHub:
        - abbr: GH
          href: https://github.com/
    - Docker Hub:
        - abbr: DH
          href: https://hub.docker.com/
- 常用:
    - Bilibili:
        - icon: bilibili.png
          href: https://www.bilibili.com/
          description: 视频平台

实测 /api/bookmarks 返回(节选):

[{"name": "开发", "bookmarks": [{"name": "GitHub", "abbr": "GH", "href": "https://github.com/"}, {"name": "Docker Hub", "abbr": "DH", "href": "https://hub.docker.com/"}]}, {"name": "常用", "bookmarks": [{"name": "Bilibili", "icon": "bilibili.png", "href": "https://www.bilibili.com/", ...

5.2 参数说明

书签结构与服务分组同构(分组 → 条目名 → 属性数组),但属性只有四个:

参数说明
abbr缩写字母(官方设计预期 2 个字母),无图标时渲染为字母块
icon图标,与 abbr 同时提供时图标优先
href跳转地址
description悬浮描述,缺省用链接主机名

书签分组同样受 settings.yaml 的 layout 控制(按分组名匹配),可与服务分组混合排版。

六、widgets.yaml 信息组件

6.1 实测配置

- datetime:
    text_size: xl
    format:
      dateStyle: long
      timeStyle: short
      hourCycle: h23
- search:
    provider: baidu
    target: _blank
- openmeteo:
    label: 当前天气
    latitude: 39.9042
    longitude: 116.4074
    timezone: Asia/Shanghai
    units: metric
    cache: 5

实测 /api/widgets 返回(节选,配置原样下发):

[{"datetime": {"text_size": "xl", "format": {...}}}, {"search": {"provider": "baidu", ...}}, {"openmeteo": {"label": "当前天气", "latitude": 39.9042, ...

6.2 常用信息组件

组件关键参数说明
datetimetext_size、format.dateStyle/timeStyle/hourCycle、locale时间日期;实测 hourCycle: h23 为 24 小时制
searchprovider(google/baidu/duckduckgo/bing 或 custom)、customUrl、target、suggestions快捷搜索框;custom 配合 customUrl 接任意搜索后端
openmeteolatitude、longitude、timezone、units、cache、label免 Key 天气源(Open-Meteo),实测北京坐标 39.9042/116.4074
openweathermapapiKey、latitude、longitude、units需要 API Key 的天气源(Key 走变量占位符)
glancesurl、username、password、points、metric系统信息(CPU/内存/磁盘/网络),对接 Glances 服务
greetingtext_size、text自定义问候语
logoicon、href站点 Logo
resourcescpu、memory、disk、cgroup本机/容器资源使用(Docker 场景)

信息组件数量多(天气、监控、DNS、加密货币等),全部列表见官方 Widgets 文档;组件顺序即 widgets.yaml 里的排列顺序。

七、docker.yaml 与环境变量注入

7.1 docker.yaml 接入方式

docker.yaml 定义 Docker 实例,一个 homepage 可同时接多台主机的 Docker。实测配置(本机 socket 接入):

my-docker:
  socket: /var/run/docker.sock

四种接入方式对比(按官方推荐顺序):

方式写法安全性适用
Docker TLShost: 192.168.0.101 + port: 2376 + 证书文件配置高远程主机标准 TLS 接入
Socket Proxyhost: http://10.89.58.3 + port: 2375(指向 socket-proxy)较高官方推荐替代 socket 直连的方案,配合 tecnomativa/docker-socket-proxy 只放行白名单 API
HTTP APIhost + port(裸 API)低内网可信环境
Socket 直连socket: /var/run/docker.sock中(需 root 或 docker 组)单机最简部署,本文实测方式

💡 实测佐证:挂载 socket 后在应用容器内以 Node HTTP over socket 请求 /containers/json 过滤 homepage-demo-nginx,实测返回 status 200 与容器 JSON——链路可达;settings.yaml/services.yaml 侧再用 server: my-docker + container: 容器名 绑定即可在卡片显示状态角标与资源统计。socket 直连要求容器以 root 或 docker 组运行(部署篇默认 root),生产建议换 Socket Proxy。

服务卡片绑定容器的配置在 services.yaml(第四章 server/container 参数);也可在 docker.yaml 实例下配 widgets: [resources] 让信息组件显示该实例的聚合资源。

7.2 Docker 标签自动发现(免 services.yaml)

给任何容器加 homepage 标签即可自动出现在仪表盘(对动态容器最省心,实测依据官方文档机制,标签示例):

docker run -d --name some-service \
  -l homepage.group=媒体服务 \
  -l homepage.name=Jellyfin \
  -l homepage.icon=jellyfin.png \
  -l homepage.href=http://192.168.146.128:8096/ \
  nginx:alpine

常用标签:homepage.group/name/icon/href/description/siteMonitor/ping/weight;widget 也能用标签表达:homepage.widget.type、homepage.widget.url、homepage.widget.key。发现机制同样支持 docker.yaml 的远程实例。

7.3 环境变量占位符(密钥注入标准做法)

配置文件里的 {{HOMEPAGE_VAR_XXX}} / {{HOMEPAGE_FILE_XXX}} 占位符由容器环境变量替换(机制与规则):

环境变量语义示例
HOMEPAGE_VAR_XXX变量注入:环境变量的值替换配置中的 {{HOMEPAGE_VAR_XXX}}HOMEPAGE_VAR_EMBY_KEY=xxxx ↔ key: {{HOMEPAGE_VAR_EMBY_KEY}}
HOMEPAGE_FILE_XXX文件注入:环境变量值是容器内文件路径,文件内容替换 {{HOMEPAGE_FILE_XXX}}HOMEPAGE_FILE_SECRETKEY=/app/config/secret_key.txt ↔ key: {{HOMEPAGE_FILE_SECRETKEY}}

命名规则:环境变量必须以 HOMEPAGE_VAR_ 或 HOMEPAGE_FILE_ 开头。密钥类凭据(第三方 API Key、OIDC Secret 等)一律走这两个占位符,不要明文写进 YAML——这样配置文件可以放心进版本库,真实凭据只在宿主机 .env 或 Docker secrets 里。完整实操见第八章案例 3。

八、实测案例

案例 1:全局设置与中文界面生效验证

目的:验证 settings.yaml 的主题/语言/布局参数真实生效,并掌握「配置生效核对」的标准方法。

操作:写入 3.1 的 settings.yaml 后刷新页面,从 __NEXT_DATA__ 提取 initialSettings:

curl -s -b cookies.txt http://homepage.example.com:8129/ \
  | python3 -c "
import json,sys,re
html = sys.stdin.read()
m = re.search(r'<script id=\"__NEXT_DATA__\" type=\"application/json\">(.*?)</script>', html, re.S)
s = json.loads(m.group(1))['props']['pageProps']['initialSettings']
print('title:', s.get('title'))
print('theme:', s.get('theme'), '| color:', s.get('color'), '| language:', s.get('language'))
print('layout:', json.dumps(s.get('layout'), ensure_ascii=False))
"

实测输出:

title: 测试变量仪表盘
theme: dark | color: slate | language: zh-Hans
layout: {"媒体服务": {"style": "row", "columns": 3}, "下载工具": {"style": "row", "columns": 3}, "系统工具": null}

结果:theme/color/language/layout 与配置文件逐项一致,界面切换为简体中文暗色 slate 主题;三个分组按 columns: 3 横向排列(系统工具 空配置按默认渲染)。后续任何配置核对都可以复用这条命令。

案例 2:服务分组与探针配置下发验证

目的:验证 services.yaml 的分组、探针与容器绑定字段被正确解析下发。

操作:写入 4.1 配置后请求服务 API:

curl -s -b cookies.txt http://homepage.example.com:8129/api/services | python3 -c "import json,sys; d=json.load(sys.stdin); print('groups:', [g['name'] for g in d])"

实测输出:

groups: ['媒体服务', '下载工具', '系统工具']

「示例站点」条目携带 server: my-docker、container: homepage-demo-nginx、siteMonitor(完整 JSON 见 4.1)。结果:三分组 4 服务全部下发;容器绑定与探针字段原样透传给前端,由前端经 /api/docker/statuses、/api/ping、/api/siteMonitor 拉取实时值——配置侧(本文职责)到此验证完毕。

案例 3:环境变量占位符注入(变量 + 文件两种形态)

目的:验证 {{HOMEPAGE_VAR_*}} 与 {{HOMEPAGE_FILE_*}} 两种注入形态,并复现文件路径配错时的报错。

操作 1(变量注入):编排文件加环境变量:

      HOMEPAGE_VAR_DASHNAME: 测试变量仪表盘
      HOMEPAGE_FILE_SECRETKEY: /app/config/secret_key.txt

settings.yaml 改为:

title: "{{HOMEPAGE_VAR_DASHNAME}}"

重建后页面标题实测渲染为 测试变量仪表盘(案例 1 的 initialSettings.title 输出即证据)。

操作 2(文件注入):把演示标记文件放到配置目录(内容为演示标记,非真实密钥):

echo "s3cr3t-marker-4217" > /opt/homepage/config/secret_key.txt

排障实录:若把该文件误放在宿主机编排目录(未挂载进容器),访问页面直接 500,日志核心报错(实测原文):

homepage-v2.7.0-web  | Error: ENOENT: no such file or directory, open '/app/config/secret_key.txt'
homepage-v2.7.0-web  |   code: 'ENOENT',

结果:文件移进 /opt/homepage/config/(即容器内 /app/config/)后页面恢复 200。结论:HOMEPAGE_FILE_* 的路径是容器内路径,文件必须落在挂载卷内;变量注入本身零故障。

案例 4:坏 YAML 容错行为与 /api/validate 自检

目的:摸清配置写坏后的故障表现,建立「改配置 → 自检」的操作习惯。

操作 1(制造坏配置):在 services.yaml 末尾追加一行未闭合的 坏行: [未闭合,观察:

  • 页面仍返回 HTTP 200,但服务区块静默消失(容错不崩页);
  • /api/services 返回 [];
  • 日志给出精确行列号(实测原文):
homepage-v2.7.0-web  | [2026-10-25T02:27:26.971Z] error: Failed to load services.yaml, please check for errors
homepage-v2.7.0-web  | [2026-10-25T02:27:26.972Z] error: YAMLException: deficient indentation (26:1)

操作 2(用自检端点定位):不刷新页面、直接问配置健康度:

curl -s -b cookies.txt http://homepage.example.com:8129/api/validate

实测输出(坏配置时):

[{"name":"YAMLException","config":"services.yaml","reason":"deficient indentation","mark":{"line":25}}]

修正缩进后再查,实测输出:

[]

结果:/api/validate 返回配置文件解析错误数组(含文件名、原因、行号),空数组即全部健康。结论:homepage 对坏配置的容错是「跳过该文件、页面不崩」,判断配置健康要用 /api/validate 与日志,不能只看页面。

九、注意事项

  1. 密钥不下发:widget 的 key 等凭据只留在服务端(代理请求机制),但仍应使用 {{HOMEPAGE_VAR_*}}/{{HOMEPAGE_FILE_*}} 占位符注入(第七章 7.3),避免凭据明文进配置文件与版本库。
  2. 生效范围:settings/services/bookmarks/widgets 四个文件保存即生效;docker.yaml/kubernetes.yaml 改动需 docker compose restart homepage;自定义图标目录新增文件后需重启。
  3. 探针取舍:ping 是 ICMP 真探针(容器内需 ICMP 能力),siteMonitor 是 HTTP HEAD;内网主机名解析依赖 Docker 网络内 DNS,跨主机请写 IP 或可解析域名。
  4. YAML 纪律:顶层是数组(- 分组名:),别写成映射;中文值不需要引号;改完先 curl /api/validate 再看页面(第八章案例 4 的教训)。
  5. API 端点心智:核对配置用 /api/services、/api/bookmarks、/api/validate;探活用免认证的 /api/healthcheck;不存在 /api/config 端点(实测 404)。
  6. 缓存与频率:widget 数据有服务端缓存,cache/refreshInterval 拉大可减轻后端压力;openmeteo 这类免费源务必设 cache(实测设 5 分钟)。

十、参考链接