Author SHA1 Message Date
panxiao81 f4aeca54bc 记录内置 API 与实现组件解耦原则 2026-09-20 19:42:35 +00:00
panxiao81 7eccbe5da5 补充 Ayatori 需求驱动的产品边界 2026-09-20 19:18:18 +00:00
panxiao81 05143b1963 记录 Ayatori 控制面架构边界 2026-09-20 19:02:07 +00:00
panxiao81 a6431ac506 记录 Nexus 制品仓库 POC 2026-09-18 19:10:51 +00:00
panxiao81 4f27e2c69e 迁移 DHCP 与 Samba 现场维护记录
docs / check (pull_request) Successful in 19s
2026-09-17 13:20:39 +00:00
panxiao81 1e24987e4f 在动态 Pod 内直接运行文档检查,避免依赖 Docker socket
docs / check (push) Successful in 19s
2026-09-16 18:52:03 +00:00
panxiao81 e394b2612d 添加文档自动检查、Actions 工作流与 PR 维护模板
docs / check (push) Failing after 0s
2026-09-16 18:50:57 +00:00
panxiao81 cf4430526a 整理任务导航与源码版本追溯并暂缓原仓库文档同步 2026-09-16 18:45:34 +00:00
panxiao81 b177741efb 补充基础设施使用入口并明确 IaC 配置优先规则 2026-09-16 18:41:38 +00:00
panxiao81 64ca735822 补充新服务的 DNS、证书与网关发布指南 2026-09-16 18:35:47 +00:00
panxiao81 38530404a6 补充文档转换、上下文检索与应用发信指南 2026-09-16 18:26:04 +00:00
panxiao81 a50c66960d 补充秘密投射、本地存储与集群 DNS 使用指南 2026-09-16 18:21:46 +00:00
panxiao81 e6cd82e606 补充网关与远程客户端指南并归档 codex-proxy 状态 2026-09-16 18:17:09 +00:00
panxiao81 c2c3a2d74b 补充共享 PostgreSQL 应用接入与使用指南 2026-09-16 18:09:16 +00:00
panxiao81 8f71414f5c 补充 OpenBao 与 NetBox 日常使用指南 2026-09-16 16:35:17 +00:00
panxiao81 1bf081672c 补充 zot 镜像发布与 SeaweedFS S3 客户端使用指南 2026-09-16 16:19:47 +00:00
panxiao81 71225289c9 更新动态 runner 启用阶段与总并发并调整入门 workflow 2026-09-16 16:16:46 +00:00
panxiao81 f19c568817 补充 Gitea Actions 与 Grafana 面向使用者的入门指南 2026-09-16 16:11:19 +00:00
panxiao81 2076deb40f 确认旧监控清理 PR #73 已合并并移除交付待办 2026-09-16 16:06:19 +00:00
panxiao81 f5bb60e2ac 同步旧监控清理分支已推送的交付状态 2026-09-16 15:53:51 +00:00
panxiao81 46aac5344b 结束首轮状态核实并分离后续文档完善事项 2026-09-16 15:52:01 +00:00
panxiao81 3b3c67c48a 记录旧监控配置与数据卷已按维护者要求删除 2026-09-16 15:50:53 +00:00
42 changed files with 2702 additions and 114 deletions
+20
View File
@@ -0,0 +1,20 @@
## 改了什么
说明具体问题、修改后的使用方法或事实;纯文字修正可简写。
## 依据
关联源码 commit/PR、ticket 或带日期的维护者说明。若来自未提交工作区,明确标注。
## 验证与范围
填写本地检查/CI 结果。现场是否查询、验证了什么、哪些示例未执行?
没有现场验证时,不因编辑文字而刷新 last_verified。
## 文档同步
- [ ] 涉及的服务页已更新;新增/退役服务已同步服务总览。
- [ ] 入口或设计变化已更新相关任务导航/架构约束(不适用可注明)。
- [ ] 已注明来源与尚未完成的部分,未包含实际凭据。
原仓库 README 同步目前暂缓,不是本 PR 的必做项。
+26
View File
@@ -0,0 +1,26 @@
name: docs
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
check:
runs-on: [self-hosted, pod]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install checker dependencies
run: |
python3 -m venv .venv
.venv/bin/python -m pip install --disable-pip-version-check -r requirements-docs.txt
- name: Test checker
run: .venv/bin/python -m unittest discover -s tests -v
- name: Check documentation
run: .venv/bin/python scripts/check_docs.py
- name: Check whitespace
run: git show --format= --check HEAD
+3
View File
@@ -6,3 +6,6 @@ node_modules/
.env
.env.*
!.env.example
.venv/
__pycache__/
*.pyc
+5 -1
View File
@@ -1,13 +1,16 @@
# 人与 AI 共用的知识库
先读 README.md,按任务从 services/index.md 和 architecture/constraints.md 查找资料,
先读 README.md,按 guides/task-index.md 定位所需服务,再读 services/index.md 和 architecture/constraints.md,
并检查 verification.md 中的相关冲突。不要求把整个仓库一次性放入上下文。
- 原仓库 README 同步已按维护者要求暂缓;当前优先维护 wiki,不将源码文档同步作为其他工作的前置步骤。
- 原仓库来源的固定版本与工作区差异见 sources.md;不能把基线链接当成未提交内容已经合并的证据。
- 正式知识写给人和 AI 共同阅读;本文件只放工作规则,不另存一份服务事实。
- 以中文维护正文、commit、PR;配置键、命令和上游专有名称保留原文。
- 区分设计、配置、部署记录与现场验证。没有访问现场,不得写“运行正常”。
- 查询服务或项目状态前先问维护者:哪些工作正在动态进行、由哪个 ticket 跟踪、哪些现状尚未记录。已有明确授权的范围无需重复询问;不能从一个项目扩大到其他项目或现场查询。
- 维护者指定 ticket 为依据时,先读正文和讨论,区分已完成阶段与开放的后续范围。issue open 不等于尚未部署,README 与 ticket 不同也不能立即认定为运行异常。
- Samba AD、OCI、Proxmox 已获维护者明确指定为 IaC 优先:以 Ansible/Terraform 代码为配置依据,README 为解释。此范围内读取仓库配置无需再次询问;现场查询仍按授权范围处理,不能把代码声明当作部署验收。
- 修改前读取对应源码 README/runbook;需要现场核实时先取得维护者对范围的确认。发现差异先记录来源,不能自行把计划升级为事实。
- 新增服务同时补用途、入口、登录方式、第一次使用示例、依赖和故障入口。
- 改变行为、入口、依赖、状态或恢复方法时,在同一任务更新对应文档与服务索引。
@@ -16,4 +19,5 @@
- 每项当前事实注明来源;last_verified 只在完成所述现场验证后更新,不随文字编辑刷新。
- 凭据只记录取得方式和受管位置,不复制实际密码、token、私钥、state 或含敏感值的输出。
- 不复制 apps/tailscale/helm.sh 的内容。迁移旧文档前先审查敏感内容,不能整库直接发布。
- 提交前运行 `python3 scripts/check_docs.py`;修改检查器时运行 `python3 -m unittest discover -s tests -v`。依赖与本地环境见 CONTRIBUTING.md。
- 遵守 CONTRIBUTING.md;不把临时检查日志和个人 agent memory 当成正式文档。
+54
View File
@@ -7,6 +7,9 @@
2026-09-16 维护者指定 SPIFFE/SPIRE 基本以 homelab-infra #34 的记录为依据;
本轮仅查该 ticket 及其直接引用的 runbook,没有查询现场。其他项目仍需先询问。
2026-09-16 维护者指定 Samba AD、OCI、Proxmox 优先 IaC、以代码为准。
可直接核对其仓库中的配置与任务,README 与代码不一致时优先解释代码;此授权不等于现场变更或验收。
稳定设计与使用方法放知识库,动态进度链接到 ticket。知识库只保留注明查阅日期的阶段摘要,
不复制维护第二份实时任务列表。issue open 可能表示后续阶段未完成,不能据此推断基础服务未部署。
@@ -49,3 +52,54 @@ accepted 不代表部署完成,implemented 必须附实现和验收依据。
使用普通 Markdown 链接、相对附件路径和文字说明;关键事实直接写入正文。
可选 Obsidian 编辑,个人布局、缓存、插件和同步配置不提交。对外分享前检查敏感内容。
提交前检查相对链接、服务目录覆盖,以及新增内容是否混淆计划和运行事实。
## 一次服务变更应更新哪里
| 变化 | 必须查看的文档 |
|---|---|
| 使用入口、认证、权限、客户端参数 | 对应 `services/` 页面;入口变化同时更新服务总览 |
| 新增或退役组件 | 服务页、`services/index.md`;任务入口变化再改 `guides/task-index.md` |
| 跨服务设计或边界 | `architecture/constraints.md` 及受影响指南 |
| 只有开发进度变化 | 原项目 ticket;wiki 仅在阶段摘要需要变化时更新并注明日期 |
| 取得新的验证结果 | 服务页说明日期与验证范围,据实更新 `last_verified` |
| 工作区来源已合并 | 核对实际内容后更新 `sources.md` 的固定链接及差异标记 |
先修改最接近事实的页面,再同步导航,避免把同一套操作复制到多份文档。
无需每次修改都更新首页、所有服务页或整个来源索引。
原仓库 README 同步按维护者要求暂缓,不阻塞 wiki 的维护。
PR 使用 [.gitea/PULL_REQUEST_TEMPLATE.md](.gitea/PULL_REQUEST_TEMPLATE.md),简述问题、最终变化、依据与验证。
直接提交也遵循相同的检查与证据规则,不为纯文案修改制造额外审批。
## 本地与 CI 检查
需要 Python 3.10 或更新版本;首次在 wiki 根目录准备环境:
```bash
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements-docs.txt
.venv/bin/python -m unittest discover -s tests -v
.venv/bin/python scripts/check_docs.py
git diff --check
```
依赖版本固定在 [requirements-docs.txt](requirements-docs.txt)。安装依赖需要网络,检查器本身离线运行。
Gitea 工作流 [.gitea/workflows/docs.yml](.gitea/workflows/docs.yml) 在 main push、PR 和手动触发时运行,
使用 `[self-hosted, pod]` 的 Python 虚拟环境;无需业务秘密或集群权限。
不设置 job `container`:此次 Pod runner 日志确认没有 Docker socket,额外启动 job 容器会在检查前失败。
CI 获取 checkout action 和依赖仍需要对应网络可用。
检查范围:
- Markdown 的相对文件链接、图片、引用式链接及本地标题锚点;不探测远端 URL。
- frontmatter 的类型、重复键、状态枚举、日期与 `live-verified` 必须有验证日期的约束。
- `services/` 下的服务页必须有完整状态字段,并由服务总览链接;总览及外部消费者范围页除外。
- 已有 frontmatter 的其他页面校验 title 和审阅日期;`templates/` 允许日期占位为 null。
标题锚点按常见 Gitea/GitHub 规则处理中文、字母、数字、连字符和重复标题。
需要特殊字符锚点时可声明 HTML `id`,不要依赖 Obsidian 插件或非标准 heading 属性。
代码块和行内代码里的路径是示例或说明,不当链接执行或检查;源码路径的存在性由 `sources.md` 的明确核对维护。
检查错误带文件与行号,但不打印原始 frontmatter 内容。
检查器不证明命令正确、外链可达、事实最新或服务健康,也不自动获取凭据或执行文档中的示例。
+15 -16
View File
@@ -4,20 +4,17 @@
## 从这里开始
- [服务总览](services/index.md):有什么、有什么用、在哪里、状态依据是什么。
- [SPIFFE/SPIRE](services/spire.md):按 #34 整理的阶段状态、使用与 runbook 入口。
- [PostgreSQL Tenant Operator](services/postgresql-tenant-operator.md):计划在共享 PostgreSQL 上提供的 DBaaS 中间层。
- [Gitea Dynamic Runner](services/gitea-dynamic-runner.md):原 microVM runner,现支持 Pod/VM 两种一次性执行环境。
- [NATS](services/nats.md):已部署的集群共享消息服务,目前仅 Dynamic Runner 消费。
- [旧 VictoriaMetrics 栈](services/victoriametrics-legacy.md):运行栈已停用,历史数据卷保留。
- [LAN DNS](services/lan-dns.md):Blocky 主 DNS、路由器上游与备用、Samba AD 域 DNS 的现状。
- [Authelia](services/authelia.md):active 的唯一主 OIDC broker 与登录入口。
- [待核实与文档缺口](verification.md):互相矛盾的记录、缺少使用说明的服务、下一步核实方法。
- [架构约束](architecture/constraints.md):修改环境前必须遵守的设计及原始依据。
- [workload-sts 设计历史](architecture/workload-sts-history.md):已归档的早期身份方案及 SPIRE 替代决策。
- [文档维护规则](CONTRIBUTING.md):人和 AI 如何共同维护知识。
- [服务文档模板](templates/service.md):新服务必须同时提供使用说明。
- [AI 工作入口](AGENTS.md):新上下文按任务查找资料。
- [按任务查找文档](guides/task-index.md):接入服务、写 CI、查日志、取秘密或接续 AI 任务。
- [服务总览](services/index.md):组件、用途、入口和状态依据。
- [发布新服务](guides/publish-service.md):LAN DNS、证书、HTTPRoute、认证与 GitOps。
- [架构约束](architecture/constraints.md):修改环境前必须遵守的设计。
- [来源追溯](sources.md):固定源码版本,以及与工作区的差异。
- [文档维护规则](CONTRIBUTING.md)、[服务模板](templates/service.md)、[AI 工作入口](AGENTS.md):如何共同维护知识。
- [首轮状态对齐记录](verification.md):已完成的澄清与历史处置。
- [文档完善清单](documentation-backlog.md):已补指南与暂缓事项。
设计历史与范围外项目见[workload-sts](architecture/workload-sts-history.md)、
[旧监控栈](services/victoriametrics-legacy.md)及[外部消费者](services/external-consumers.md)。
## 当前证据边界
@@ -25,11 +22,13 @@
`ebe0ec154dab557598075b5cf6d3629c3c23fe2a`。该工作区包含未提交修改和未跟踪文件。
后续按维护者提供的线索补读了 SPIFFE/SPIRE #34 与 runbook、workload-sts 归档决策、
PostgreSQL Tenant Operator 的 README 与架构文档,以及 Gitea Dynamic Runner README。
具体来源和查阅范围见各页;其余条目仍以初轮工作区证据为限。
具体来源和查阅范围见各页;后续使用指南已按对应源码和上游接口文档逐项补充。
未补充的状态仍以初轮证据为限;来源文件与已提交版本的比较见[来源追溯](sources.md)。
LAN DNS 已按维护者于 2026-09-16 提供的现状更新,未查询现场。
Authelia 同日由维护者明确为 active、唯一的主 OIDC broker,已同步到服务总览。
后续状态查询先向维护者确认动态工作与资料来源,授权范围内不重复询问。
初轮没有查询运行环境;后续仅对旧 VictoriaMetrics 栈做了维护者明确授权的有限只读检查,
初轮没有查询运行环境;后续对旧 VictoriaMetrics 栈做了维护者明确授权的有限只读检查,
随后按明确要求删除旧配置和数据卷,
检查范围和结果见对应页面。“文档记录已部署”不等于今天已验证健康。
本库中的入口地址来自原有记录,也尚未逐一验证可达性。
+41
View File
@@ -0,0 +1,41 @@
---
title: Ayatori 控制面边界
last_reviewed: 2026-09-20
---
# Ayatori 控制面边界
Ayatori 是规划和早期实现中的 homelab 基础设施控制平面。它使用 kube-apiserver、etcd、CRD
和 Kubernetes API machinery 作为版本化 API 与状态协调平面,主要复用对象并发控制、
list/watch、informer、RBAC、admission、审计和 API 版本机制,而不是复用 Kubernetes 的容器
编排产品边界。
Ayatori controller-manager 负责领域资源的调度、生命周期、故障恢复、垃圾回收和后端收敛。
这部分职责近似 Kubernetes 的 controller-manager,但面向 VM、LB、数据库、对象存储、任务、
托管 Kubernetes 和人工操作等 Ayatori 领域。
Kubernetes workload 集群只是与 OpenSandbox、Proxmox 等并列的 backend/executor,可能位于
远端,也可能在某个部署 profile 中不存在。除 Flux、Ayatori controllers 等管理组件的部署外,
领域 API 不得默认依赖同集群 Pod、Job、Service、NetworkPolicy、namespace 共置或 owner
reference;跨后端能力必须由领域 API 和 adapter 契约明确表达。
Kubernetes 内置资源也只是可选择复用的 API contract,不绑定其传统实现组件。例如 Ayatori
可以让 Compute Agent 更新 `core/v1 Node` 和 Lease,并由自有 controller 调度 VM,而不部署
kubelet、Pod、CRI 或 kube-scheduler。每个复用资源都必须单独明确 producer、consumer、
ownership、采用字段和有意舍弃的上游语义。
当前选择继续使用 kube-apiserver + CRD。generic-apiserver 或聚合 API Server 不会替代领域
controller,只会让项目额外接管资源服务端、watch、RBAC、API 兼容和存储迁移责任。只有 CRD
或 kube-apiserver 的限制形成经过验证的阻碍时,才重新评估自建 API Server。
Ayatori 不按传统私有云产品目录建设。当前已确认的首要管理缺口是 Database、LoadBalancer 与
Bucket/Object Storage;VirtualMachine 同样具有明确价值,但需要组合 Proxmox API、节点受限
Agent/CLI 和人工任务。当前 Job controller 是控制循环与 adapter 的验证切片,长期只可能收敛为
内部 Run 能力,不构成 FaaS、Cloud Run 或应用托管承诺。KaaS 只有出现实际需求时才评估,不是
产品路线的必达终点。
详细设计以 Ayatori 仓库的
[ADR-0001](https://git.ddupan.top/panxiao81/ayatori/src/branch/main/docs/decisions/0001-kubernetes-api-machinery.md)
、[ADR-0006](https://git.ddupan.top/panxiao81/ayatori/src/branch/main/docs/decisions/0006-demand-driven-resource-scope.md)
和[总体架构](https://git.ddupan.top/panxiao81/ayatori/src/branch/main/docs/architecture/overview.md)为准。
本页记录跨 homelab 的稳定边界,不表示 Ayatori 已部署或达到生产可用状态。
+7 -2
View File
@@ -1,10 +1,15 @@
# 架构约束索引
审阅日期:2026-09-16。以下是现有仓库明确记录的约束摘要,不是本轮新增的架构决策。
来源路径相对于 homelab-infra;修改时必须读原文和对应代码,冲突进入[核实清单](../verification.md)。
审阅日期:2026-09-20。以下是现有仓库明确记录的约束摘要;Ayatori 条目来自其独立项目的
已接受设计,其余来源路径相对于 homelab-infra。修改时必须读原文和对应代码,新出现的差异
先向维护者确认;[首轮状态对齐](../verification.md)已完成。
| 约束 | 原因与边界 | 来源 |
|---|---|---|
| Ayatori 复用 Kubernetes API machinery,不复用其容器编排产品边界 | kube-apiserver/etcd 提供 API、watch、RBAC 与状态协调;领域调度、生命周期、恢复和 GC 属于 Ayatori controllers;Kubernetes workload 只是可替换 backend | [Ayatori 控制面边界](ayatori-control-plane.md) |
| Kubernetes 内置资源不绑定上游实现组件 | 可由 Ayatori Agent/controller 实现和消费 Node、Lease 等 API;使用 Node 不推导必须部署 kubelet、Pod 或 kube-scheduler | [Ayatori 控制面边界](ayatori-control-plane.md) |
| Ayatori 只为已验证的管理缺口新增北向资源 | 当前优先 Database、LoadBalancer、Bucket/Object Storage;VM 价值已确认但南向较重;Run 是内部切片,KaaS 按需,FaaS/PaaS 默认不做 | [Ayatori 控制面边界](ayatori-control-plane.md) |
| Samba AD、OCI、Proxmox 优先 IaC,以代码为准 | Ansible/Terraform 声明及任务优先于旧 README;声明不等于已验证部署 | 维护者于 2026-09-16 明确、各服务使用指南 |
| 服务独立部署,Terraform root/state 按服务隔离 | 避免认证和变更影响范围绑在一起 | `AGENTS.md`、`CLAUDE.md` |
| OpenBao 恢复不能依赖 k3s 或读取自己内部的恢复凭据 | 先恢复信任根,再恢复消费者 | `infrastructure/openbao/README.md`、`CLAUDE.md` |
| Terraform 管 API 配置,Ansible 管主机及不能安全纳管的密钥材料 | 不可读回秘密和根密钥不能靠反复重建实现收敛 | `infrastructure/openbao/README.md` |
+52
View File
@@ -0,0 +1,52 @@
# 文档完善清单
本轮待核实事项已于 2026-09-16 收尾。以下是后续写作工作,不是未解决的状态核实任务,
也不代表所有相关项目都已部署或经过现场验收。需要补充事实时仍先向维护者对齐范围。
## 已补充使用指南
- [Gitea / Actions](services/gitea.md):登录、建仓库、最小 CI、runner 选择和常见问题。
- [Grafana](services/grafana.md):内存看板、指标查询、日志搜索和数据源用途。
- [zot](services/zot.md):拉取、发布授权、workflow 身份职责与后端数据恢复边界。
- [SeaweedFS](services/seaweedfs.md):S3 入口、专用凭据、列举与上传下载示例。
- [OpenBao](services/openbao.md):人的登录、按权限取密及机器身份边界。
- [NetBox](services/netbox.md):浏览设备与 IPAM,明确 Git 来源与评估用途。
- [共享 PostgreSQL](services/shared-postgresql.md):应用接入、连接检查与共享实例维护边界。
- [LiteLLM](services/litellm-gateway.md):模型请求、认证边界与独立数据库依赖。
- [Tailscale](services/tailscale.md):客户端接入、子网路由和 operator Service 的区别。
- [ps3netsrv](services/ps3netsrv.md)、[vlmcsd](services/vlmcsd.md):客户端使用与配置入口。
- [External Secrets](services/external-secrets.md)、[OpenEBS](services/openebs.md):应用秘密与 PVC 消费示例。
- [k3s DNS](services/k3s-dns.md):Pod 解析路径、配置意图与排障入口。
- [Marker](services/marker.md)、[OpenViking](services/openviking.md):转换与导入、等待、检索、读取示例。
- [SMTP relay](services/smtp-relay.md):应用配置、测试邮件与投递边界。
- [发布新服务](guides/publish-service.md):LAN DNS、证书、Envoy 路由、认证与 GitOps 的完整路径。
- [Samba AD](services/samba-ad.md)、[OCI](services/oci.md)、[Proxmox](services/proxmox.md):已有资料中的日常管理路径,动态状态未重查。
以上依据源码文档和上游说明整理,示例未在本轮执行,不作为现场验收记录。
## 后续使用说明
本轮列出的使用指南已补齐。后续以实际接入任务补充细节,不自动启动全量现场检查。
Samba AD、OCI、Proxmox 已按维护者指定采用 IaC 优先、以代码为准,并核对关键配置入口;未查询现场。
codex-proxy 已按维护者“应该是退役的”的说明移至归档范围,不再补新接入指南。
LiteLLM、Tailscale、ps3netsrv、vlmcsd 与 k3s 的 wiki 指南已补;源码目录仍缺根 README,配置入口已在各页列出。
## 来源与导航
- 已新增[按任务查找](guides/task-index.md),首页改为任务入口与服务总览。
- 已核对 62 个主要来源文件,提供[固定版本与工作区差异](sources.md)。
- 仍有差异或未收录的来源,等内容合并后再补对应版本;不自动提交原仓库工作区。
## 持续维护
- 已提供离线文档检查器、Gitea Actions 工作流与检查器测试。
- 已补 PR 模板及服务变更到文档的对应规则,见 [CONTRIBUTING](CONTRIBUTING.md)。
- Backstage 展示与 OpenViking 自动索引仍是独立后续工作,本轮未接入。
## 原仓库文档同步(按维护者要求暂缓)
- 源码仓库中 Authelia OIDC、LAN DNS、SPIRE 的旧说明后续与知识库结论同步。
- cert-manager / Envoy Gateway README 的 DNS 修改入口仍写旧变量,待同步为受管 records.yml 流程。
- Proxmox README 的早期身份方案与 runner bootstrap 描述待与当前 SPIFFE 原则对齐;Samba README 的通用示例域名/地址待清理。
上述项目仅保留记录,本轮不修改原仓库文档。
+166
View File
@@ -0,0 +1,166 @@
---
title: 为新服务配置 LAN HTTPS 入口
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# 为新服务配置 LAN HTTPS 入口
普通 LAN Web 服务使用 `your-app.ad.ddupan.top`,复用共享 Envoy Gateway 和通配符证书。
本指南串联应用 Service、路由、DNS、认证与 GitOps;示例不会自动创建任何对象。
本轮只读仓库与上游资料,未查询现场、签发证书或发布服务。
## 接入前明确应用参数
准备应用 namespace、Service 名称与 **Service port**、域名、访问人群及认证方式。
先让应用及其 Service 在集群内可用;需要秘密或持久存储时,分别参考
[External Secrets](../services/external-secrets.md) 和 [OpenEBS](../services/openebs.md)。
本例约定 namespace 和 Service 均为 `your-app`,Service port 为 `8080`。
这些都是占位值,须替换为实际配置。HTTPRoute 不负责部署应用、创建 namespace 或授予应用权限。
## 1. 复用现有证书与 listener
共享入口为 `envoy-gateway-system/eg`,普通 LAN 域名绑定 `https` listener。
其证书 Secret 为 `envoy-gateway-system/wildcard-ad-ddupan-top-tls`,由 cert-manager 管理。
| 域名场景 | 接入选择 |
|---|---|
| `your-app.ad.ddupan.top` | 复用 `https` listener 与通配符证书 |
| `auth.ddupan.top`、`git.ddupan.top` | 已有各自的 `https-auth`、`https-git` listener |
| 更深的域名或其他域 | 单独设计证书 SAN 与匹配的 listener,不能套用本例 |
TLS 通配符只覆盖一层子域。证书包含 `ad.ddupan.top` SAN 也不表示现有 listener 会接收这个 apex;
证书名称和 listener hostname 是两个需要同时满足的条件。
新 LAN 服务不需要复制私钥、创建第二个 Gateway 或重新安装 cert-manager。
现有通配符通过 `ClusterIssuer/letsencrypt` 与 Cloudflare DNS-01 签发。
DNS-01 不要求业务端口对公网开放;自检需保留现有公共递归 resolver 设置,避免内部 AD 视图看不到公开 TXT。
详见 [cert-manager DNS-01](https://cert-manager.io/docs/configuration/acme/dns01/)。
`bao-acme` 是内部 CA 的另一个选择,客户端需信任内部 CA;它不是无需配套调整的通配符替代品。
## 2. 在应用 namespace 声明 HTTPRoute
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: your-app
namespace: your-app
spec:
parentRefs:
- name: eg
namespace: envoy-gateway-system
sectionName: https
hostnames:
- your-app.ad.ddupan.top
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: your-app
port: 8080
```
本例后端 Service 与路由同 namespace;`8080` 必须是 Service 暴露的端口,不直接照搬容器端口。
跨 namespace 后端引用还需目标 namespace 的 ReferenceGrant,不能只增加一个 namespace 字段就认为授权完成。
共享 Gateway 的 `allowedRoutes` 允许其他 namespace 挂载路由,但这不等于应用已经得到用户认证保护。
需要 HTTP→HTTPS 跳转时,为同一 hostname 增加独立 HTTPRoute,绑定 `sectionName: http`,
使用 `RequestRedirect` 的 `scheme: https`、`port: 443` 和适当状态码,不配置业务 backend。
HTTPS 路由本身不会自动生成跳转。规则语义参考
[Gateway API 跳转指南](https://gateway-api.sigs.k8s.io/guides/user-guides/http-redirect-rewrite/)。
保留 HTTP listener 的 ACME 用途,不为单个应用替换整个 listener。
## 3. 在受管 DNS 清单增加名称
工作区的声明入口为 `infrastructure/dns/records.yml`,在 `homelab_dns.samba.records`
现有列表中增加以下 RRset,不能用这个片段覆盖原列表:
```yaml
- zone: ad.ddupan.top
name: your-app
type: A
values:
- 192.168.10.127
```
该地址来自共享 Envoy Gateway 的现有记录。Samba Ansible 的 `provision-dc.yml` 已引用该清单,
DNS task 消费 `homelab_dns.samba.records`;旧 README 中增加 `samba_ad_extra_a_records` 的步骤不再作为本页入口。
相关 DNS 清单与任务存在工作区改动,正式合并来源仍需补全,不能认定任意远端 checkout 都已包含它们。
维护者先审查针对 DNS 的 Ansible check/diff,再按既有流程应用。受管 RRset 的 exact 语义可能移除同名同类型的其他值,
因此应检查完整记录集合;不要遍历清理 Samba 自动生成的 AD/Kerberos 记录。
[LAN DNS](../services/lan-dns.md) 与 [Pod DNS](../services/k3s-dns.md) 的路径不同,
新增名称后分别检查所需视图。LAN 已使用 Blocky,不采用旧 DNS README 中“尚未成为正式 resolver”的历史表述。
## 4. 按应用选择认证
| 应用类型 | 接入方式 |
|---|---|
| 已支持 OIDC 的 Web 应用 | 按应用文档接入 Authelia,配置 client、回调地址与应用内权限 |
| 信任反向代理身份头的应用 | 配套 Envoy SecurityPolicy、Authelia 规则及阻止绕过网关的网络策略 |
| API、Git、机器客户端 | 使用服务支持的认证协议,避免浏览器登录跳转截获协议请求 |
Gitea 使用原生登录/OIDC 和 Git token,因此其路由没有套用 NetBox 的 forward-auth。
SPIFFE workload 接入按[机器身份原则](../services/spire.md)设计,服务自行授权;
HTTPS 证书和 HTTPRoute 都不会自动替代业务认证。
forward-auth 的现有参考为 `apps/netbox/securitypolicy.yaml` 与 `networkpolicy.yaml`,另需协调:
- `apps/authelia/referencegrant-extauth.yaml`:目标 namespace 授权新的 SecurityPolicy 来源。
- `apps/authelia/values.yaml`:目标域名及访问群组规则。
- 应用配置:信任哪些身份头,以及如何映射用户权限。
复制前逐项替换 route 名、namespace、Pod selector 和端口。现有 Authelia Service port 是 `80`,
不是容器 `9091`;`headersToBackend` 位于 `extAuth.http`,并由可信结果覆盖客户端同名头。
保留 `failOpen: false`,同时限制直接访问后端的路径。NetworkPolicy 的 probe 例外与节点地址需按应用核对,
不能机械复制 NetBox 的节点白名单。
## 5. 纳入部署入口并验收
将路由和配套策略加入应用 Kustomization 或 chart values,并确认应用由哪个 Flux Kustomization 管理。
只新建 YAML 文件不会使它自动部署。独立新应用还需 namespace 与集群 reconciliation 入口,
按 `clusters/homelab/README.md` 审查;不要为接入一个应用开启全局 prune。
先本地渲染并检查 diff,合并后由已有 GitOps 流程交付。获得现场检查授权后,分层验证:
1. Flux 已同步目标 revision;后端 Service 有可用 endpoint。
2. Gateway listener 可用,HTTPRoute 对目标 parent 的 `Accepted`、`ResolvedRefs` 为 True。
3. 从相应客户端解析新名称,并检查证书名称与信任链。
4. 验证登录、应用权限及需要支持的 API/机器客户端,不能只检查首页 200。
若需分开验证入口与 DNS,可在已授权的客户端使用以下诊断请求,域名仍保留在 TLS SNI 与 Host 中:
```bash
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' \
--resolve your-app.ad.ddupan.top:443:192.168.10.127 \
https://your-app.ad.ddupan.top/
```
该命令绕过客户端 DNS,不是 DNS 验收;不加 `-k` 绕过证书校验。
响应是否符合预期取决于应用,受保护页面可能返回登录跳转。
## LAN 入口与公网发布的边界
本指南只完成 LAN HTTPS 路径。公开可信证书不意味着服务已开放公网。
公网发布还需单独审查 Cloudflare DNS、Tunnel 路由、访问控制与应用外部 URL,
入口为 `infrastructure/cloudflared/terraform/README.md`;不要从已有域名复制 Tunnel 设置就宣称完成发布。
## 来源与维护
homelab-infra:`platform/cert-manager/README.md`、`certificate-wildcard-ad.yaml`,
`platform/envoy-gateway/README.md`、`gateway.yaml`,`infrastructure/dns/`,
`infrastructure/samba-ad/ansible/`,`apps/netbox/`,`apps/authelia/referencegrant-extauth.yaml`,
`apps/gitea/httproute.yaml` 与 `clusters/homelab/README.md`。
`apps/http-echo/httproute.yaml` 是已排除出 Kustomization 的历史 Contour 示例,
`archive/traefik/` 也不是当前接入模板;不要因文件存在就直接应用。
上述源码 README 的旧描述尚待同步,本页按实际所读配置与维护者已经确认的结论整理。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#publish-service)。
+58
View File
@@ -0,0 +1,58 @@
---
title: 按任务查找文档
last_reviewed: 2026-09-20
---
# 按任务查找文档
先找任务,再读相关服务页;不必一次读取整个仓库。
需要环境清单时看[服务总览](../services/index.md),准备变更时先读[架构约束](../architecture/constraints.md)。
| 要做什么 | 先读 | 需要时再读 |
|---|---|---|
| 设计或实现 Ayatori 控制面能力 | [Ayatori 控制面边界](../architecture/ayatori-control-plane.md) | Ayatori 仓库 ADR、对应领域 API 与 adapter 文档 |
| 发布新的 LAN Web 服务 | [发布新服务](publish-service.md) | [DNS](../services/lan-dns.md)、[Authelia](../services/authelia.md) |
| 写 CI 或选择 Pod/VM runner | [Gitea / Actions](../services/gitea.md) | [Dynamic Runner](../services/gitea-dynamic-runner.md)、[SPIFFE](../services/spire.md) |
| 为 CI 缓存 Ansible/Go 依赖 | [Nexus POC](../services/nexus.md) | [Dynamic Runner](../services/gitea-dynamic-runner.md)、[OpenBao](../services/openbao.md) |
| 拉取或发布容器镜像 | [zot](../services/zot.md) | [SPIFFE](../services/spire.md);S3 后端维护才读 SeaweedFS |
| 使用 S3 对象存储 | [SeaweedFS](../services/seaweedfs.md) | [OpenBao](../services/openbao.md) |
| 给应用分配数据库 | [共享 PostgreSQL](../services/shared-postgresql.md) | [计划中的 DBaaS](../services/postgresql-tenant-operator.md) |
| 给应用提供秘密或存储 | [External Secrets](../services/external-secrets.md)、[OpenEBS](../services/openebs.md) | [OpenBao](../services/openbao.md) |
| 排查内存、日志或追踪 | [Grafana](../services/grafana.md) | 对应服务源码 runbook |
| 排查域名解析 | [LAN DNS](../services/lan-dns.md)或[Pod DNS](../services/k3s-dns.md) | [Tailscale](../services/tailscale.md),如果请求来自远程客户端 |
| 排查登录或域权限 | [Authelia](../services/authelia.md)、[Samba AD](../services/samba-ad.md) | 具体应用的权限说明 |
| 为 workload 提供机器身份 | [SPIFFE](../services/spire.md) | 目标服务的 token 与权限规则;进度回到 #34 |
| 使用消息队列 | [NATS](../services/nats.md) | consumer 项目自己的协议与队列文档 |
| 调用模型或处理文档 | [LiteLLM](../services/litellm-gateway.md)、[Marker](../services/marker.md) | [OpenViking](../services/openviking.md),如果需要检索 |
| 让应用发送邮件 | [SMTP relay](../services/smtp-relay.md) | 消费者的发信配置 |
| 远程访问或查看网络资产 | [Tailscale](../services/tailscale.md)、[NetBox](../services/netbox.md) | NetBox 的权威来源是 Git,不能代替运行状态 |
| 管理云主机或虚拟机 | [OCI](../services/oci.md)、[Proxmox](../services/proxmox.md) | 对应 IaC 和网络/HA runbook |
| 使用 PS3 内容或 KMS 服务 | [ps3netsrv](../services/ps3netsrv.md)、[vlmcsd](../services/vlmcsd.md) | 各自客户端配置 |
## 给 AI 接续一个任务
提供目标、目标服务、已经授权的操作范围,以及你掌握但尚未写入文档的变化。
一个简短的任务交接可以这样写:
```text
目标:为某个新应用增加 LAN HTTPS 入口。
入口文档:guides/publish-service.md。
已有条件:应用 namespace、Service 名称与端口、计划域名。
本次范围:先准备配置与文档 PR;尚未授权现场部署。
动态背景:相关 ticket / PR,或维护者最新说明。
完成条件:配置可审阅,检查通过,说明来源与未执行的验证。
```
这个例子的范围仅用于演示,不能覆盖具体任务已经获得的授权。
Samba AD、OCI、Proxmox 已明确以 IaC 为准,可直接核对其代码;其他动态项目按既定规则对齐来源。
身份设计、配置声明、历史实施记录和本次现场证据应分别表达。
## 找到资料后如何判断是否足够
服务页中的 `last_reviewed` 表示文档审阅时间,`last_verified` 才表示对应现场验证时间。
查阅[来源追溯](../sources.md)可定位固定源码版本,并看到它与工作区是否一致。
索引中的“内容一致”只确认文件,不确认服务健康。
检索、转换或 AI 摘要用于定位原文;结论仍应关联到源码、维护者说明或 ticket。
工作完成后,将持久使用方法写入服务页,将一次变化留在 commit/PR,动态进度回到原项目 ticket。
原仓库 README 同步目前按维护者要求暂缓,不将其列为每次任务的前置条件。
+3
View File
@@ -0,0 +1,3 @@
markdown-it-py==3.0.0
mdurl==0.1.2
PyYAML==6.0.1
+221
View File
@@ -0,0 +1,221 @@
#!/usr/bin/env python3
"""离线检查 wiki 的元数据、链接、标题锚点与服务索引。"""
from __future__ import annotations
import argparse
from datetime import date
from html.parser import HTMLParser
from pathlib import Path
import re
import subprocess
import sys
import unicodedata
from urllib.parse import unquote, urlsplit
from markdown_it import MarkdownIt
import yaml
LIFECYCLES = {"planned", "experimental", "active", "retired", "unknown"}
EVIDENCE = {"configuration", "documented", "live-verified"}
# These two pages are navigation/scope descriptions, not individual services.
SERVICE_INDEXES = {"services/index.md", "services/external-consumers.md"}
class UniqueLoader(yaml.SafeLoader):
pass
def unique_mapping(loader, node):
result = {}
for key_node, value_node in node.value:
key = loader.construct_object(key_node)
if not isinstance(key, str):
raise ValueError("frontmatter 键必须是字符串")
if key in result:
raise ValueError(f"重复 frontmatter 键:{key}")
result[key] = loader.construct_object(value_node)
return result
UniqueLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, unique_mapping)
def split_frontmatter(text):
lines = text.splitlines(keepends=True)
if not lines or lines[0].strip() != "---":
return None, text
for i in range(1, len(lines)):
if lines[i].strip() == "---":
metadata = yaml.load("".join(lines[1:i]), Loader=UniqueLoader)
if not isinstance(metadata, dict):
raise ValueError("frontmatter 必须是映射")
# Preserve line positions for diagnostics.
return metadata, "\n" * (i + 1) + "".join(lines[i + 1:])
raise ValueError("frontmatter 缺少结束分隔符")
def as_date(value):
if type(value) is date:
return value
if isinstance(value, str) and re.fullmatch(r"\d{4}-\d{2}-\d{2}", value):
return date.fromisoformat(value)
raise ValueError("必须是 YYYY-MM-DD 日期")
def metadata_errors(meta, required=False, template=False):
if meta is None:
return ["服务页缺少 frontmatter"] if required else []
errors = []
keys = {"title", "last_reviewed"}
if required:
keys |= {"lifecycle", "evidence", "last_verified"}
for key in sorted(keys - meta.keys()):
errors.append(f"缺少字段 {key}")
if not isinstance(meta.get("title"), str) or not meta["title"].strip():
errors.append("title 必须是非空字符串")
for key, choices in [("lifecycle", LIFECYCLES), ("evidence", EVIDENCE)]:
if key in meta and (not isinstance(meta[key], str) or meta[key] not in choices):
errors.append(f"{key} 不在允许值中")
dates = {}
for key in ["last_reviewed", "last_verified"]:
if key not in meta:
continue
if meta[key] is None:
if key == "last_reviewed" and not template:
errors.append("last_reviewed 不得为 null")
continue
try:
dates[key] = as_date(meta[key])
except (ValueError, TypeError):
errors.append(f"{key} 必须是 YYYY-MM-DD 日期或允许的 null")
if meta.get("evidence") == "live-verified" and "last_verified" not in dates:
errors.append("live-verified 必须提供 last_verified 日期")
if len(dates) == 2 and dates["last_verified"] > dates["last_reviewed"]:
errors.append("last_verified 不能晚于 last_reviewed")
if "sources" in meta and (not isinstance(meta["sources"], list) or
any(not isinstance(x, str) or not x.strip() for x in meta["sources"])):
errors.append("sources 必须是非空字符串组成的列表(可为空列表)")
return errors
def slug(text):
# Common Gitea/GitHub heading form; keep CJK, words, spaces and hyphens.
return "".join(c for c in text.lower() if c in " -_" or
unicodedata.category(c)[0] in "LN").replace(" ", "-")
class HTMLLinks(HTMLParser):
def __init__(self):
super().__init__()
self.links = []
self.anchors = set()
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
for key in ["href", "src"]:
if attrs.get(key):
self.links.append(attrs[key])
if attrs.get("id"):
self.anchors.add(attrs["id"])
if tag == "a" and attrs.get("name"):
self.anchors.add(attrs["name"])
def parse_body(body):
tokens = MarkdownIt("commonmark").enable("table").parse(body)
anchors, links = set(), []
for i, token in enumerate(tokens):
if token.type == "heading_open":
inline = tokens[i + 1]
text = "".join(t.content for t in inline.children or []
if t.type in {"text", "code_inline", "image"})
base = slug(text)
candidate, suffix = base, 0
while candidate in anchors:
suffix += 1
candidate = f"{base}-{suffix}"
anchors.add(candidate)
def visit(t, line):
line = t.map[0] + 1 if t.map else line
if t.type in {"link_open", "image"}:
url = t.attrGet("href" if t.type == "link_open" else "src")
if url is not None:
links.append((line, url))
if t.type in {"html_inline", "html_block"}:
html = HTMLLinks()
html.feed(t.content)
anchors.update(html.anchors)
links.extend((line, u) for u in html.links)
for child in t.children or []:
visit(child, line)
visit(token, 1)
return anchors, links
def check(root, files):
root = root.resolve()
errors, documents = [], {}
for relative in files:
path = root / relative
try:
if not path.resolve().is_relative_to(root):
raise ValueError("文件指向仓库外部")
meta, body = split_frontmatter(path.read_text(encoding="utf-8"))
required = relative.startswith("services/") and relative not in SERVICE_INDEXES
errors.extend(f"{relative}:1: {e}" for e in metadata_errors(
meta, required=required, template=relative.startswith("templates/")))
documents[relative] = parse_body(body)
except (ValueError, OSError, yaml.YAMLError) as exc:
# Do not print YAML source lines: malformed frontmatter may contain secrets.
errors.append(f"{relative}:1: 无法解析文件或 frontmatter({type(exc).__name__})")
indexed = set()
for relative, (_, links) in documents.items():
for line, url in links:
prefix = f"{relative}:{line}: "
try:
parsed = urlsplit(url)
except ValueError:
errors.append(prefix + "URL 格式无效")
continue
if parsed.scheme in {"http", "https", "mailto", "tel", "data"} or parsed.netloc:
continue
if parsed.scheme or parsed.path.startswith("/"):
errors.append(prefix + "链接必须使用仓库内相对路径或网页 URL")
continue
target = ((root / relative).parent / unquote(parsed.path)).resolve() if parsed.path else root / relative
if not target.is_relative_to(root):
errors.append(prefix + "链接越出仓库")
continue
if not target.exists():
errors.append(prefix + f"目标不存在:{unquote(parsed.path)}")
continue
dest = target.relative_to(root).as_posix()
if relative == "services/index.md":
indexed.add(dest)
anchor = unquote(parsed.fragment)
if anchor and dest in documents and anchor not in documents[dest][0]:
errors.append(prefix + f"标题锚点不存在:{dest}#{anchor}")
for relative in documents:
if relative.startswith("services/") and relative not in SERVICE_INDEXES and relative not in indexed:
errors.append(f"{relative}:1: 服务页未被 services/index.md 链接")
return errors
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1])
args = parser.parse_args()
output = subprocess.check_output(
["git", "-C", str(args.root), "ls-files", "--cached", "--others", "--exclude-standard", "-z"])
files = sorted({p for p in output.decode().split("\0") if p.endswith(".md")})
errors = check(args.root, files)
if errors:
print("\n".join(errors), file=sys.stderr)
return 1
print(f"文档检查通过:{len(files)} 个 Markdown 文件;未联网或执行文档示例。")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+87
View File
@@ -0,0 +1,87 @@
---
title: External Secrets 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# External Secrets Operator
ESO 将 [OpenBao](openbao.md) 中的秘密投射为 Kubernetes Secret,供应用消费。
本页依据 homelab-infra 工作区 `platform/external-secrets/README.md`、
`clustersecretstore.yaml`、`externalsecrets.yaml` 与 `kustomization.yaml` 整理,未查询现场。
其中 `externalsecrets.yaml` 含未提交修改,不代表这些修改已部署。
## 应用如何获得秘密
现有 `ClusterSecretStore/openbao` 指向 `https://bao.ad.ddupan.top:8200` 的 KV v2 mount `kv`。
ESO 使用 `external-secrets` namespace 中同名 ServiceAccount 的短期 JWT,
通过 OpenBao 的 Kubernetes auth 与 `external-secrets` role 登录。
这是已记录的认证方式,不能因 SPIFFE 是整体身份设计就宣称 ESO 已迁移到 SPIFFE。
接入前由维护者确认应用 namespace、OpenBao 路径、字段、目标 Secret 名称和授权范围。
先准备 OpenBao 中的真实值,再提交只含引用的 ExternalSecret;凭据本身不进 Git。
共享 ClusterSecretStore 不意味着任意 namespace 都应有权引用所有秘密,新增引用需要审查来源与消费者权限。
## 最小字段投射示例
以下是待按应用替换的模板:`your-app` namespace 须已存在,
OpenBao 的 `kv/k8s/your-app` 须已包含 `password` 字段且允许 ESO 读取。
本轮仅展示模板,没有创建这些对象。
```yaml
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: your-app-credentials
namespace: your-app
spec:
refreshInterval: 1h
secretStoreRef:
name: openbao
kind: ClusterSecretStore
target:
name: your-app-credentials
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: k8s/your-app
property: password
```
`remoteRef.key` 相对于 store 的 `kv` mount,不把 API 的 `data/` 层写进这个例子。
字段映射语义见 [ESO Vault provider](https://external-secrets.io/latest/provider/hashicorp-vault/);
这里沿用现有 `vault` provider 配置,不因上游出现其他 provider 就修改认证实现。
应用在同一 namespace 的容器配置中引用生成结果,例如:
```yaml
env:
- name: APP_PASSWORD
valueFrom:
secretKeyRef:
name: your-app-credentials
key: password
```
这是容器配置片段,需放入应用自己的 manifest,不能独立 apply。
采用环境变量消费时,Secret 刷新不会更新已启动进程的环境变量,轮换须配合应用重启或既有滚动流程。
## 同步与维护边界
受权检查时,先查看 ExternalSecret 的同步状态与事件,再确认目标 Secret 的名称和键是否满足应用引用;
不通过输出 Secret YAML 或解码真实值来证明接入成功。
引用缺失先检查 namespace、路径和字段;认证失败检查 store 的 ServiceAccount、OpenBao role/policy 与 TLS。
`creationPolicy: Owner` 使 ESO 管理目标 Secret 的所有权,删除 ExternalSecret 可能连带删除目标 Secret,
不能将它当作无影响的临时配置。不要手工覆盖 ESO 生成的副本。
源码 README 明确区分 Helm release 接管与 secret delivery 对象接管,当前目录 Kustomization
只列 Helm 相关资源,没有列入 `clustersecretstore.yaml` 和 `externalsecrets.yaml`。
新增引用先确定由哪个 GitOps/部署入口管理;把文件改好不等于 Flux 已经应用。
部署和接管细节回到 `platform/external-secrets/README.md`。
依赖包括 OpenBao、Kubernetes TokenReview、集群 DNS 与 ESO controller。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#external-secrets)。
+15 -1
View File
@@ -17,9 +17,23 @@ microVM;每个环境只执行一个 job,结束后销毁环境及本地状态
更名由维护者提供;以下组件与接口说明依据 2026-09-16 查阅的项目 README。
维护者进一步明确:**项目正在积极开发,具体启用范围和实现进度以该项目文档为准。**
本页保留用途、设计原则和该次 README 的摘要,不另行维护部署范围或消息队列参数清单。
本页保留用途、设计原则和该次 README 的摘要,仅补充维护者明确提供的阶段与容量,不复制维护完整部署范围或消息队列参数清单。
本轮未查询现场,不将设计接口视为已完成的上线验收。
## 当前开发与启用阶段
维护者于 2026-09-16 补充:开发接近完成,动态 `pod` 已上线测试,`vm` 正在工作;
纯 `self-hosted` 的旧常驻 runner 准备退役。
| 执行环境 | workflow labels | 系统总并发量 | 阶段 |
|---|---|---:|---|
| Pod | `[self-hosted, pod]` | 4 | 已上线测试 |
| VM | `[self-hosted, vm]` | 1 | 正在工作,具体进度以项目文档为准 |
并发量是对应环境在系统中的总容量,不按仓库或 workflow 分别分配一份额度。
本页记录维护者提供的阶段与容量,不将“上线测试”写成完整正式验收;
旧常驻 runner 也尚未标记为已退役。后续变化继续以项目文档为准。
## workflow 如何选择执行环境
README 定义两种稳定接口,在 workflow 的 job 中选择:
+84
View File
@@ -0,0 +1,84 @@
---
title: Gitea 与 Actions 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# Gitea 与 Actions
Gitea 托管 homelab 的代码、文档、issue 和 PR;Actions 执行仓库声明的 CI workflow。
入口为 <https://git.ddupan.top>,人类登录使用 [Authelia](authelia.md)。
本页依据现有服务 README、runner README、仓库 workflow 和官方使用文档整理。
本轮没有重新验证登录或运行示例;下面的操作是使用指南,不是本轮执行记录。
## 登录并找到项目
1. 打开 Gitea,选择已配置的 Authelia/OIDC 登录入口。
2. 在 Authelia 完成认证,返回 Gitea;应用权限由 Gitea 账号和仓库授权决定。
3. 打开目标仓库:Code 看源码,Issues 看动态工作,Pull Requests 看待合并改动,Actions 看 CI。
登录成功但看不到仓库时,先确认当前账号与仓库权限;OIDC 登录本身不会赋予所有项目的管理权。
已有账号应沿用原账号关联,遇到关联问题交由管理员处理,不另建同名账号规避。
## 创建与修改仓库
通过页面的 New Repository 创建仓库,选择所属用户或组织、名称及可见性。
仓库里的 Clone 按钮提供当前准确的 HTTPS/SSH 地址,复制该地址到 Git 客户端即可。
浏览器的 OIDC 会话不直接充当 Git 命令行凭据;客户端使用自己的凭据管理或已登记 SSH key。
日常修改先建分支、提交并推送,再开 PR 合并到 main。PR 应说明最终行为与验证结果,
不要把本机未提交的其他工作一并带入。基础设施仓库默认以中文维护 commit、PR 和文档。
## 第一个 CI workflow
在可信的测试仓库中启用 Repository Actions,再添加 `.gitea/workflows/hello.yaml`:
```yaml
name: Hello
on: [push]
jobs:
hello:
runs-on: [self-hosted, pod]
steps:
- name: Check execution
run: echo 'homelab CI is running'
```
推送该文件后,进入 Actions,打开本次运行和 hello job。
预期看到输出 `homelab CI is running` 且 job 成功;示例不需要检出源码或读取秘密。
若仓库设置没有 Actions 开关,先确认自己的管理权限。
workflow 路径、启用方式与事件规则见 [Gitea 官方入门](https://docs.gitea.com/usage/actions/quickstart/)。
维护者于 2026-09-16 说明:动态 `pod` 已上线测试,系统总并发量为 4;
纯 `self-hosted` runner 准备退役,新 workflow 使用明确的动态环境 labels。
本例据此采用 `[self-hosted, pod]`,本轮未实际运行示例。
若任务排队,除 runner 在线状态和 labels 外,也要考虑系统并发容量,不能把入队当作执行成功。
## 选择 runner
| 需求 | 使用入口 |
|---|---|
| 动态 Pod:已上线测试 | `[self-hosted, pod]`;系统总并发 4,不是每个仓库各有 4 个名额 |
| 动态 VM:正在工作 | `[self-hosted, vm]`;系统总并发 1,具体可用范围和进度以项目文档为准 |
| 旧常驻 runner:准备退役 | 纯 `self-hosted`,不再作为新 workflow 的默认示例;已有 workflow 需按需求迁移到明确的 Pod/VM 接口 |
上述阶段与容量由维护者于 2026-09-16 提供。实现与后续变化见
[Dynamic Runner](gitea-dynamic-runner.md) 及其项目文档。
常驻 runner 使用 privileged DinD,README 明确限定可信 workflow;不要为不可信代码开放它。
动态 runner 提供环境及获取自身 SPIFFE 身份的能力;登录下游、请求 token 和凭据清理由 workflow 负责。
## 遇到问题先看哪里
- 没有触发:看 Actions 是否启用、文件是否位于正确路径、事件是否匹配此次推送。
- 一直排队:看仓库可用 runner、在线状态和 labels;动态 runner 的问题回到其项目文档。
- job 失败:打开具体 step 的日志,从第一个失败步骤排查,不只看最终退出码。
- Git 命令失败但网页能登录:分别检查 Git 使用的身份、凭据方式和仓库权限。
服务部署与升级恢复以 homelab-infra `apps/gitea/README.md` 为入口;常驻 runner 以
`platform/gitea-runner/README.md` 为入口。本页不复制 token、密码或部署命令。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#gitea)。
+84
View File
@@ -0,0 +1,84 @@
---
title: Grafana 与可观测性使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# Grafana 与可观测性
从 <https://grafana.ad.ddupan.top> 查看 homelab 的指标、日志和追踪。
使用 Authelia OIDC 登录;远程访问需要到 LAN 的路由及内网 DNS。
本页依据现有 observability README、Grafana 数据源配置、内存看板 JSON 和 exporter 说明整理,
部分来源仍在源码工作区、尚未提交。本轮未打开网页或执行查询;以下结果描述是使用预期。
## 先看主机内存与 Swap
1. 打开 [Homelab 内存与 Swap](https://grafana.ad.ddupan.top/d/homelab-memory)。
2. 时间范围选择最近 1 小时,需要定位问题时改成问题发生的具体时段。
3. 先看“主机物理内存”“Swap 使用量”“Swap 换页速率”,再看程序/虚拟机 PSS 和 Pod working set。
4. 对比异常发生前后的曲线,记录时间与相关程序或 Pod,便于继续查日志。
看板来源为 `platform/observability/grafana/dashboards/homelab-memory.json`。
PSS、RSS、Pod working set 和 ZFS ARC 是不同统计口径,不应直接相加。
“没有数据”表示当前查询没有返回匹配样本,不等于数值为零。
## 自己查一条指标
进入 Explore,选择 **VictoriaMetrics** 数据源,时间范围设为最近 1 小时,
在 Code 模式输入以下看板已有的表达式,再执行查询:
```promql
node_memory_MemTotal_bytes{job="node-exporter"}
- node_memory_MemAvailable_bytes{job="node-exporter"}
```
它计算主机已用内存,单位为字节。预期按采集目标返回曲线;有多个目标时,
查看返回标签后选择相应 instance,避免把多台机器当作一台解读。
该环境特意限定 `job="node-exporter"`,避免旧 docker-hosts 抓取同端口导致重复统计。
如需查看 Swap 换出活动,可使用看板已有查询:
```promql
rate(node_vmstat_pswpout{job="node-exporter"}[5m])
```
单位是 pages/s,不是 bytes/s。查询入口与编辑器行为见
[Grafana Prometheus 查询文档](https://grafana.com/docs/grafana/latest/datasources/prometheus/query-editor/)。
## 找一段日志
1. 进入 Explore,切换到 **VictoriaLogs** 数据源,设定最近 15 分钟。
2. 输入 `* | limit 20` 执行查询,展开一条结果,观察这套采集实际提供的字段。
3. 用真实出现的 namespace、Pod 或应用字段收窄范围;不要预先假定字段名。
4. 要找错误消息,可先输入 `error | limit 50`;有结果后按实际字段进一步筛选。
VictoriaLogs 使用 LogsQL。上述 limit 限制返回数量,不保证返回的是最新若干条。
关键字没有结果时可以放宽时间范围并回到第一步,区分“没有该关键字”与“没有采集数据”。
语法依据见 [VictoriaLogs 查询说明](https://docs.victoriametrics.com/victorialogs/querying/)。
## 三个数据源的分工
| 数据源 | 用途 |
|---|---|
| VictoriaMetrics | Prometheus 兼容指标查询,例如内存、CPU、采集健康 |
| VictoriaLogs | LogsQL 日志查询 |
| VictoriaTraces | Jaeger 兼容追踪查询;应用需要先接入追踪,不能仅凭数据源存在认为所有服务都有 trace |
数据源名称来自 `platform/observability/grafana/values.yaml`。
## 出问题时与维护入口
- 域名打不开:先区分内网 DNS、到 LAN 的路由和浏览器证书错误。
- 登录后无权限:检查 Grafana 的账号/角色授权,Authelia 登录不等于管理员权限。
- 看板空白:检查时间范围、数据源和筛选条件,再区分缺少采集与查询失败。
- 指标与日志不一致:先对齐时间和目标实例,再判断是否为采集范围不同。
部署、采集与恢复入口为 homelab-infra `platform/observability/README.md`;
内存指标解释见 `platform/observability/metrics/exporters/README.md`。
看板配置由 Git/ConfigMap 管理,网页临时调整不作为持久配置的权威来源。
旧 Compose 栈与数据已[清理](victoriametrics-legacy.md),不要再使用旧实例作为排障入口。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#grafana)。
+34 -30
View File
@@ -1,13 +1,14 @@
# 服务总览
审阅日期:2026-09-16。以下覆盖源码工作区 apps/、platform/、infrastructure/ 的一级组件,以及集群入口。
**除旧 VictoriaMetrics Compose 已获授权做有限现场检查外,其余条目未在本轮现场验证。**
审阅日期:2026-09-18。以下覆盖源码工作区 apps/、platform/、infrastructure/ 的一级组件,以及集群入口。
**除旧 VictoriaMetrics Compose 已获授权检查并清理外,其余条目未在本轮现场验证。**
状态栏区分维护者说明、文档、ticket、配置与现场证据,不提供持续的实时健康判断。
SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护者说明更新,
独立项目按指定 README 收录。其余条目仍为初轮工作区盘点,查询前先向维护者对齐。
来源路径相对于 [homelab-infra](https://git.ddupan.top/panxiao81/homelab-infra);包含未提交内容,见首页证据边界。
入口按来源记录列出,访问范围和可达性仍需验证。缺口详情见[待核实清单](../verification.md)。
入口按已有来源记录列出,未记录的内容保持未知,不自动生成现场核实任务。
本轮状态对齐已[完成](../verification.md);后续写作见[文档完善清单](../documentation-backlog.md)。
## 应用
@@ -15,35 +16,34 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
|---|---|---|---|---|---|
| [authelia](authelia.md) | 唯一主 OIDC broker、统一登录 | `auth.ddupan.top` | active;维护者于 2026-09-16 明确已在工作 | 维护者说明、`apps/authelia/` | 同步源码 README 中过时的 OIDC 阶段说明 |
| [blocky](lan-dns.md) | LAN 主 DNS、广告过滤、分流 | `192.168.10.127:53` | 维护者说明已作为 DHCP 主 DNS,上游为路由器 | 维护者 2026-09-16 说明、`apps/blocky/README.md` | 无需逐台确认主机;旧源码说明待同步 |
| codex-proxy | 代理服务,具体接口待确认 | `待核实` | 仅发现配置 | `apps/codex-proxy/docker-compose.yml` | 缺 README 与使用说明 |
| gitea | 代码托管与 Actions | `git.ddupan.top` | 记录已部署 | `apps/gitea/README.md` | 补首次使用与 runner 选择 |
| [gitea](gitea.md) | 代码托管与 Actions | `git.ddupan.top` | 记录已部署 | `apps/gitea/README.md` | 已有登录、最小 CI 与 runner 选择指南 |
| http-echo | Flux 部署与漂移修复 canary | `集群内` | 记录已验证 | `apps/http-echo/README.md` | 已有验证步骤 |
| litellm-gateway | 模型 API 网关,实际消费者待确认 | `待核实` | 仅发现配置 | `apps/litellm-gateway/docker-compose.yml` | 缺 README 与接入说明 |
| marker | GPU 文档转换 API | `集群内端口 8001` | 配置与部署指南;上线待核实 | `apps/marker/README.md` | 缺 API 使用例子 |
| [litellm-gateway](litellm-gateway.md) | 模型 API 网关,实际消费者未记录 | `宿主 TCP 4000;地址未记录` | 仅发现配置 | `apps/litellm-gateway/docker-compose.yml` | 已有参数、请求示例与依赖说明 |
| [marker](marker.md) | GPU 文档转换 API | `集群内端口 8001` | 配置与部署指南;未附上线记录 | `apps/marker/README.md` | 已有转换示例;部署镜像仍为占位符 |
| netboot | PXE 与系统安装 | `192.168.10.127` | 有部署及使用记录 | `apps/netboot/README.md` | 已有客户端启动说明 |
| netbox | 网络资产与地址管理评估 | `netbox.ad.ddupan.top` | 记录已部署;评估用途 | `apps/netbox/README.md` | 补面向浏览者的使用路径 |
| openviking | 上下文检索服务 | `记录端口 1933 / 8020` | 配置与部署指南;上线待核实 | `apps/openviking/README.md` | 缺导入、查询的完整例子 |
| ps3netsrv | PS3 网络内容服务 | `待核实` | Docker 运维文档记录运行 | `apps/ps3netsrv/docker-compose.yml` | 缺客户端使用与挂载说明 |
| seaweedfs | S3 对象存储 | `s3.ad.ddupan.top` | zot 文档记录已使用 | `apps/seaweedfs/README.md` | 补客户端接入、备份与恢复 |
| shared-postgresql | 共享 PostgreSQL / CNPG | `shared-db namespace` | 历史迁移记录已完成 | `apps/shared-postgresql/migration.md` | 缺服务首页、租户接入说明 |
| smtp-relay | 应用经 Microsoft 365 发信 | `smtp-relay.smtp-relay.svc.cluster.local:25` | 有配置与测试指南;上线待核实 | `apps/smtp-relay/README.md` | 核实发信链路与消费者 |
| tailscale | 远程网络与子网路由 | `Tailscale 网络` | 有配置;本轮未读敏感安装脚本 | `apps/tailscale/subnet-routes.sh` | 缺 README、路由与客户端说明 |
| victoriametrics | 旧 Compose 监控栈 | `待核实` | 文档称被平台栈替代;残留待查 | `apps/victoriametrics/compose.yaml` | 明确退役或现存职责 |
| vlmcsd | KMS 兼容服务,使用范围待确认 | `待核实` | 仅发现配置 | `apps/vlmcsd/compose.yaml` | 缺 README 与状态说明 |
| zot | OCI 镜像与制品仓库 | `zot.ad.ddupan.top / zot-push.ad.ddupan.top` | 文档记录 9 月 16 日验收 | `apps/zot/README.md` | 已有拉取示例;长期 CI 发布仍待接入 |
| [netbox](netbox.md) | 网络资产与地址管理评估 | `netbox.ad.ddupan.top` | 记录已部署;评估用途 | `apps/netbox/README.md` | 已有浏览与 Git 修改入口指南 |
| [nexus](nexus.md) | CI 包代理与统一制品仓库 POC | `nexus.ad.ddupan.top` | 仅有未提交配置,尚未部署验证 | `apps/nexus/README.md` | 先验收 Ansible/Go,再补 OCI 声明式管理与 BuildKit 测试 |
| [openviking](openviking.md) | 上下文检索服务 | `记录端口 1933 / 8020` | 配置与部署指南;未附上线记录 | `apps/openviking/README.md` | 已有导入、任务查询、检索与原文读取指南 |
| [ps3netsrv](ps3netsrv.md) | PS3 网络内容服务 | `宿主 TCP 38008;地址未记录` | Docker 运维文档记录运行 | `apps/ps3netsrv/docker-compose.yml` | 已有客户端与内容目录指南 |
| [seaweedfs](seaweedfs.md) | S3 对象存储 | `s3.ad.ddupan.top` | zot 文档记录已使用 | `apps/seaweedfs/README.md` | 已有客户端读写指南与备份边界说明 |
| [shared-postgresql](shared-postgresql.md) | 共享 PostgreSQL / CNPG | `shared-db namespace` | 历史迁移记录已完成 | `apps/shared-postgresql/migration.md` | 已有连接、应用接入与共享资源边界指南 |
| [smtp-relay](smtp-relay.md) | 应用经 Microsoft 365 发信 | `smtp-relay.smtp-relay.svc.cluster.local:25` | 有配置与测试指南;未附上线记录 | `apps/smtp-relay/README.md` | 已有应用参数、测试邮件与投递边界指南 |
| [tailscale](tailscale.md) | 远程网络与子网路由 | `Tailscale 网络` | 有配置;本轮未读敏感安装脚本 | `apps/tailscale/subnet-routes.sh` | 已有远程访问与路由边界指南 |
| [vlmcsd](vlmcsd.md) | KMS 兼容服务,使用范围未记录 | `宿主 TCP 1688;地址未记录` | 仅发现配置 | `apps/vlmcsd/compose.yaml` | 已有协议入口与客户端指南;未查询现场 |
| [zot](zot.md) | OCI 镜像与制品仓库 | `zot.ad.ddupan.top / zot-push.ad.ddupan.top` | 文档记录 9 月 16 日验收 | `apps/zot/README.md` | 已有拉取与发布模板;实际 publisher 授权以项目配置为准 |
## 平台
| 组件 | 用途 | 记录入口 | 状态依据 | 来源 | 文档缺口 / 下一步 |
|---|---|---|---|---|---|
| cert-manager | 签发与续期 TLS 证书 | `ClusterIssuer API` | 记录已接管 Flux | `platform/cert-manager/README.md` | 已有签发和验证说明 |
| envoy-gateway | LAN HTTP 入口与认证集成 | `192.168.10.127:443` | 记录已接管 Flux | `platform/envoy-gateway/README.md` | 已有服务接入说明 |
| external-secrets | OpenBao 到 Kubernetes 的秘密投射 | `Kubernetes API` | Helm 记录已接管;对象范围需区分 | `platform/external-secrets/README.md` | 补新增秘密引用的使用流程 |
| gitea-runner | 可信 Gitea Actions 任务执行 | `Gitea Actions` | 记录已接管 Flux | `platform/gitea-runner/README.md` | 补 workflow label 与使用限制 |
| k3s | 集群 CoreDNS 定制 | `集群内 DNS` | 仅发现 DNS 配置 | `platform/k3s/Corefile.desired` | 缺组件 README |
| [cert-manager](../guides/publish-service.md) | 签发与续期 TLS 证书 | `ClusterIssuer API` | 记录已接管 Flux | `platform/cert-manager/README.md` | 已有新服务证书复用与接入指南 |
| [envoy-gateway](../guides/publish-service.md) | LAN HTTP 入口与认证集成 | `192.168.10.127:443` | 记录已接管 Flux | `platform/envoy-gateway/README.md` | 已有 DNS、路由、认证与发布路径指南 |
| [external-secrets](external-secrets.md) | OpenBao 到 Kubernetes 的秘密投射 | `Kubernetes API` | Helm 记录已接管;对象范围需区分 | `platform/external-secrets/README.md` | 已有字段投射示例与 ownership 边界 |
| gitea-runner | 旧常驻 Gitea Actions runner | 纯 `self-hosted` | 维护者说明准备退役,尚未标为已退役 | `platform/gitea-runner/README.md`、维护者说明 | 新 workflow 改用 [动态 Pod/VM](gitea-dynamic-runner.md) 的明确 labels |
| [k3s DNS](k3s-dns.md) | 集群 CoreDNS 定制 | `集群内 DNS` | 仅发现 DNS 配置 | `platform/k3s/Corefile.desired` | 已有集群 DNS 使用与配置边界说明 |
| [nats](nats.md) | 集群共享消息与 JetStream 队列 | `nats.ad.ddupan.top:4222` | 已部署;维护者说明目前唯一消费者为 Dynamic Runner | 维护者 2026-09-16 说明、`platform/nats/README.md` | runner 消息队列约定以独立项目文档为准 |
| observability | Grafana、指标、日志和追踪 | `grafana.ad.ddupan.top` | 记录已接管 Flux;9 月 16 日变更入口 | `platform/observability/README.md` | 补看板和查询使用指南 |
| openebs | k3s 本地 ZFS 持久卷 | `localpv-zfs-ceph StorageClass` | 记录已接管 Flux | `platform/openebs/README.md` | 已有运维检查;补 PVC 使用边界 |
| [observability / Grafana](grafana.md) | Grafana、指标、日志和追踪 | `grafana.ad.ddupan.top` | 记录已接管 Flux;9 月 16 日变更入口 | `platform/observability/README.md` | 已有看板、指标与日志查询指南 |
| [openebs](openebs.md) | k3s 本地 ZFS 持久卷 | `localpv-zfs-ceph StorageClass` | 记录已接管 Flux | `platform/openebs/README.md` | 已有 PVC 示例、绑定与数据回收边界 |
| [spire](spire.md) | 跨基础设施的统一机器身份入口 | `Workload API / spire-oidc.ad.ddupan.top` | #34 记录基础设施与最小 OpenBao PoC 已完成;后续集成进行中 | [#34](https://git.ddupan.top/panxiao81/homelab-infra/issues/34)、[RUNBOOK](https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/platform/spire/RUNBOOK.md) | 已有接入指南;动态任务以 ticket 为准 |
## 基础设施
@@ -52,14 +52,14 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
|---|---|---|---|---|---|
| cloudflared | 公网 Tunnel 与 DNS | `Cloudflare 边缘配置` | 有现有资源接管记录 | `infrastructure/cloudflared/terraform/README.md` | 明确配置权威位置与服务发布流程 |
| [dns](lan-dns.md) | 跨视图 DNS 声明 | `records.yml` | LAN 角色已按维护者说明对齐;声明接管范围未重查 | `infrastructure/dns/README.md`、维护者说明 | 同步旧描述;补新增记录流程 |
| docker | 宿主 Docker 网络管理 | `laptop` | 记录已迁移地址池 | `infrastructure/docker/README.md` | 已有 DN42 与挂载路径约束 |
| docker | 宿主 Docker 网络管理 | `laptop` | 记录已迁移地址池 | [架构约束](../architecture/constraints.md) 与 IaC | Docker bridge 使用 `172.28.0.0/16`,避免 DN42 |
| kata-lab | Kata VM 试验环境 | `历史 VMID 147` | 记录 9 月 14 日已销毁 | `infrastructure/kata-lab/README.md` | 保留验证历史,勿当现役 VM |
| kata-lxc-lab | LXC 内 Kata worker 试验 | `pve2 / 记录地址 192.168.10.128` | 记录 PoC 验证;非正式生产服务 | `infrastructure/kata-lxc-lab/README.md` | 明确与 microVM runner 的职责 |
| microvm-runner(历史目录名) | 动态 runner 的 homelab 基础设施记录 | 当前项目接口见 [Dynamic Runner](gitea-dynamic-runner.md) | 独立项目已更名并扩展到 Pod/VM,正在积极开发 | `infrastructure/microvm-runner/README.md`、独立项目文档 | 具体启用范围和实现进度以独立项目文档为准 |
| oci | 云主机、网络与站点互联 | `OCI ap-osaka-1` | 有恢复、接管与网络实施记录 | `infrastructure/oci/README.md` | 补跨站点使用入口 |
| openbao | 秘密管理与内部 CA | `bao.ad.ddupan.top` | 有部署与接管记录 | `infrastructure/openbao/README.md` | 补日常使用和恢复入口 |
| proxmox | PVE、虚拟化与主机基础设施 | `PVE 管理入口` | 已有基础设施;README 混有设计设想 | `infrastructure/proxmox/README.md` | 分离当前环境与 workload identity 设想 |
| samba-ad | AD 身份、域 DNS 与域成员管理 | `dc1 / 192.168.10.5` | 有部署记录;维护者说明 DNS 部分已完成 | `infrastructure/samba-ad/README.md`、[LAN DNS](lan-dns.md) | 补入域和日常管理入口 |
| [oci](oci.md) | 云主机、网络与站点互联 | `OCI ap-osaka-1` | 有恢复、接管与网络实施记录 | `infrastructure/oci/README.md` | 已有登录、站点网络与维护入口 |
| [openbao](openbao.md) | 秘密管理与内部 CA | `bao.ad.ddupan.top` | 有部署与接管记录 | `infrastructure/openbao/README.md` | 已有登录、取密与运维入口指南 |
| [proxmox](proxmox.md) | PVE、虚拟化与主机基础设施 | `PVE 管理入口` | 已有基础设施 | `infrastructure/proxmox/ansible/` 与 `README-ha.md` | 已有管理入口;身份与 runner 设计见独立项目 |
| [samba-ad](samba-ad.md) | AD 身份、域 DNS 与域成员管理 | `dc1 / 192.168.10.5` | 有部署记录;维护者说明 DNS 部分已完成 | `infrastructure/samba-ad/README.md`、[LAN DNS](lan-dns.md) | 已有入域、目录浏览与日常管理入口 |
## 集群
@@ -69,6 +69,10 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
## 计划、归档与范围外
- codex-proxy:维护者于 2026-09-16 表述为“应该是退役的”,按退役方向归档;源码目录仍保留,未确认现场清理情况,不再作为新接入对象。
- [旧 VictoriaMetrics Compose](victoriametrics-legacy.md):旧配置和三个数据卷已于 2026-09-16 按维护者要求删除;现役监控在 platform/observability。
- [e5renew、research-auto](external-consumers.md):GitHub 上的外部消费者,不属于 homelab 基础设施;仅保留归属入口。
- [Gitea Dynamic Runner](gitea-dynamic-runner.md):正在积极开发的动态 Pod/VM runner,原名 gitea-microvm-runner;具体启用范围、调度和队列约定以项目文档为准。
- [PostgreSQL Tenant Operator](postgresql-tenant-operator.md):计划中的 DBaaS 中间层,管理共享实例中的数据库与账号;README 记录为 API 骨架阶段,不代表服务已上线。
@@ -79,4 +83,4 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
- `docs/superpowers/`:已退役工作流,记录已完成的 CNPG/ZFS 迁移。
- `docs/cicd.md`、`docs/homelab-gitops-redesign.md`:部分实施设计,不代表所有阶段都上线。
- `docs/gitea-upgrade-plan.md`:包含已完成升级记录,现状以服务 README 和现场为准。
- 仓库外服务与独立源码仓库见[盘点盲区](../verification.md#盘点盲区)。
- 仓库外服务与独立源码仓库见[已确认的归属与范围](../verification.md#已确认的归属与范围)。
+66
View File
@@ -0,0 +1,66 @@
---
title: k3s 集群 DNS 使用说明
lifecycle: unknown
evidence: configuration
last_reviewed: 2026-09-16
last_verified: null
---
# k3s 集群 DNS
本页说明 Pod 的 DNS 使用路径,依据 homelab-infra `platform/k3s/Corefile.desired` 与
`coredns-custom.yaml`。这些文件是配置意图与历史故障处理记录,未现场确认是否与运行配置完全一致。
LAN 主机通过 DHCP 使用 Blocky/路由器的现状见 [LAN DNS](lan-dns.md),不能据此推导所有 Pod 的转发链。
## 应用如何使用
Pod 通常通过 Kubernetes DNS 解析 Service。跨 namespace 使用完整地址,例如
`shared-postgresql-rw.shared-db.svc.cluster.local`;同 namespace 的短名称按 Pod DNS 搜索域处理。
这类集群内部名称不是远程客户端的公共入口。
集群内访问 Authelia 或 Gitea 时继续使用 `auth.ddupan.top`、`git.ddupan.top` 的原有 URL,
避免把 OIDC issuer、证书名称或 Git remote 改成 IP 来绕过解析问题。
受权排障时,可在已有且具备 `nslookup` 的应用容器中执行以下只读查询:
```bash
nslookup kubernetes.default.svc.cluster.local.
nslookup dc1.ad.ddupan.top.
nslookup auth.ddupan.top.
nslookup git.ddupan.top.
```
末尾的点表示绝对域名,用于减少搜索域扩展对诊断的干扰。
四个查询分别覆盖集群 Service、AD 域和两个分流入口;本轮没有执行,也没有为此创建调试 Pod。
DNS 成功只证明解析路径,不证明应用认证和业务请求成功。
## 文件中声明的分流
| 名称范围 | 配置意图 |
|---|---|
| `cluster.local` 与集群反向记录 | CoreDNS Kubernetes 插件处理 |
| `ad.ddupan.top` | 直接转发 Samba AD DNS `192.168.10.5` |
| `auth.ddupan.top`、`git.ddupan.top` | A 记录返回 Envoy LAN 地址 `192.168.10.127`;AAAA 返回无数据 |
| `lab.ddupan.top`、`tail7e769.ts.net` | 本地返回 NXDOMAIN,阻止历史搜索域排列请求继续转发 |
| 其余请求 | 默认 Corefile 转发至 `/etc/resolv.conf` |
最后一项的实际上游由运行环境的 resolver 文件决定。本轮没有读取现场文件,
不能将源码注释中的历史路由器上游描述当成今天所有节点的 resolver 配置。
对被本地拒绝的后缀新增用途前,应审查这一历史规则,而不是直接在外部 DNS 增加记录后假定 Pod 能解析。
## 缓存和修改入口
`Corefile.desired` 的默认 server block 配置 `cache 30` 与 `serve_stale 1h immediate`,
允许在该规则覆盖范围内暂用过期缓存条目;其他独立 server block 不自动继承这条缓存规则。
因此修改 DNS 记录后,缓存结果可能与权威记录暂时不同。
语义见 [CoreDNS cache](https://coredns.io/plugins/cache/)。
`coredns-custom.yaml` 声明 `kube-system/coredns-custom`,由 Corefile 的 custom import 使用。
`Corefile.desired` 的文件名本身不证明它已由 Flux 管理或已经应用。
变更前先确认该对象的管理入口,再审查影响范围;不要整份替换 CoreDNS 配置来修一个域名。
故障定位先区分集群 Service 解析、AD 转发、固定分流、默认上游和客户端搜索域。
依赖包括 CoreDNS、Kubernetes API、网络、Samba AD DNS 及默认上游;
Authelia/Gitea 的业务可达性还依赖 Envoy 和各自后端。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#k3s-dns)。
+16 -2
View File
@@ -45,16 +45,30 @@ Samba AD → 保留域 DNS 职责,相关配置已完成
主机通过 DHCP 自动获取 DNS 配置:主 DNS 为 Blocky,副 DNS 为路由器。
当前知识库以此作为 LAN 客户端配置口径,无需另行进行主机覆盖盘点。
## NEC IX DHCP 地址池
2026-09-14 将主 LAN 动态池从 `192.168.10.10–250` 收窄为
`192.168.10.128–250`,并为 Buffalo AP(`d4:2c:46:09:07:b0`)固定分配
`192.168.10.10`。`.251–.254` 保留,尚未分配;不能因为扫描无响应就将其用于新设备。
DHCP 下发网关 `192.168.10.1`、主 DNS `192.168.10.127`、备用 DNS
`192.168.10.1`,租期为 4 小时。
地址池修改会清空 NEC IX 当前租约表,但终端可能继续使用旧地址直到续租。
变更后 Kata LXC 实验节点已续租为 `.128`;迁移其他动态客户端前应先检查活动任务,
并在续租后分别验证主机网络和其内部 k3s 等服务。地址池及预留段的声明同时维护在
`apps/netbox/terraform/topology.yml`。
回滚时不能直接恢复整份路由器配置;应先确认 `.10–.127` 没有静态占用,再在 DHCP
profile 中恢复原范围并移除 AP 固定绑定,保存后重新核对租约、DNS 和 NetBox 声明。
## 维护入口与待补充范围
以下路径相对于 homelab-infra,保留部署与操作细节的原有归属:
- `apps/blocky/README.md`:Blocky 部署、分流和检查方法。
- `infrastructure/samba-ad/README.md`:域 DNS 与 Samba 配置。
- `infrastructure/samba-ad/router-dhcp-nec-ix.md`:路由器 DHCP 记录。
- `infrastructure/samba-ad/router-dns-nec-ix.md`:路由器 DNS 记录。
- `infrastructure/dns/README.md`、`records.yml`:跨视图 DNS 声明与所有权。
本次只更新知识库;原工作区中“Blocky 未成为正式 resolver”的旧描述尚待同步。
路由器自身的更上游和 AD/DN42 条件转发明细未在本次补充,也不因此自动产生核查任务。
需要进一步查询时,先向维护者确认当前工作和范围,不因旧文档差异直接发起现场检查。
+70
View File
@@ -0,0 +1,70 @@
---
title: LiteLLM 网关使用指南
lifecycle: unknown
evidence: configuration
last_reviewed: 2026-09-16
last_verified: null
---
# LiteLLM gateway
为客户端提供模型 API 代理。维护者于 2026-09-16 表示没有需要补充的动态改动或退役事项;
本页依据 `apps/litellm-gateway/docker-compose.yml` 与 `config.yaml` 整理,不代表已验证运行状态。
## 接入参数
Compose 映射宿主 TCP `4000` 到网关 `4000`,没有在这些文件中记录统一访问域名。
先由维护者提供实际 base URL、客户端认证要求及可用模型;不能把宿主端口自动当成公网入口。
网关客户端的认证与网关访问上游模型的认证是两层配置,不能把服务端认证文件交给消费者。
配置中的模型别名包括 `chatgpt/gpt-5.4` 和 `hf/google/embeddinggemma-300m` 等,
分别面向聊天和 embedding;这里只表示路由声明,不保证上游账号有权限或模型当下可用。
完整别名以 `config.yaml` 为准。不要因名字含有 codex,就把这个网关与已退役的 codex-proxy 混为一体。
## 第一次聊天请求
在已获授权的客户端环境中,将 `LITELLM_BASE_URL` 设置为维护者提供的 API 根地址,
`LITELLM_MODEL` 设置为获准使用的聊天模型别名。
如果该入口要求 Bearer key,通过既有秘密注入方式提供 `LITELLM_API_KEY`;是否需要 key 以实际接入约定为准。
下面使用 Python 标准库,token 不放在命令行中;请求会调用上游模型并消耗对应配额。
```python
import json
import os
import urllib.request
base = os.environ["LITELLM_BASE_URL"].rstrip("/")
headers = {"Content-Type": "application/json"}
key = os.environ.get("LITELLM_API_KEY")
if key:
headers["Authorization"] = "Bearer " + key
payload = {
"model": os.environ["LITELLM_MODEL"],
"messages": [{"role": "user", "content": "Reply with OK."}],
}
request = urllib.request.Request(
base + "/chat/completions",
data=json.dumps(payload).encode(),
headers=headers,
method="POST",
)
with urllib.request.urlopen(request, timeout=60) as response:
result = json.load(response)
print(result["choices"][0]["message"]["content"])
```
预期收到模型回复。接口结构参考 [LiteLLM 客户端文档](https://docs.litellm.ai/docs/proxy/user_keys),
本轮没有执行请求。该示例面向聊天模型,不能直接拿 embedding 模型替换。
## 依赖与排障
这套 Compose 包含独立的 PostgreSQL 16 和 Prometheus,数据库卷为 `postgres_data`,
指标卷为 `prometheus_data`;这里的数据库不是[集群共享 PostgreSQL](shared-postgresql.md)。
Compose 还挂载配置文件及宿主 `auth.json`,后者属于上游认证材料,不进入 wiki、日志或 AI 上下文。
镜像配置使用 `dev` 标签,接入行为需与实际部署版本相符,不能仅凭最新上游文档认定功能已启用。
连接失败先核对宿主与端口;401/403 需区分网关认证和上游认证;模型错误先核对别名及上游权限;
超时或限额错误再检查上游响应。不要通过打印认证文件或完整带鉴权请求排障。
部署来源为 homelab-infra `apps/litellm-gateway/`;消费者清单与备份情况未在所读文件中记录。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#litellm-gateway)。
+65
View File
@@ -0,0 +1,65 @@
---
title: Marker 文档转换指南
lifecycle: unknown
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# Marker
Marker 用 GPU 将 PDF 转为 Markdown 等格式。本页依据 homelab-infra `apps/marker/README.md`、
Dockerfile 与 Kubernetes manifests,以及下列上游 API 源码整理,未查询运行环境。
源码 Deployment 仍使用 `<your-registry>/marker:latest` 占位符,不能据此认定服务已经上线。
## 使用前提与入口
先由维护者完成镜像构建、部署与可达性确认,再使用集群内入口
`http://marker.default.svc.cluster.local:8001`。所读配置没有记录外部域名或客户端认证流程。
普通应用无需重新执行 README 中的部署步骤。
镜像未固定 `marker-pdf` 版本,示例必须与实际部署的 `/docs` 接口说明核对。
上游当前 `marker_server` 默认绑定 `127.0.0.1`,而本地配置只传 `--port`;
如果所构建版本也如此,维护者需设置 `--host 0.0.0.0` 才能供 Service 访问。
这是部署前检查点,本轮未修改 manifest 或判定现场故障。
## 转换一个 PDF
在能访问该 Service 的客户端,准备一份适合测试的 `sample.pdf`,设置 `MARKER_BASE_URL`
为已确认的入口。上传会处理文件并占用 GPU,先以单个小文件串行验证:
```bash
curl --fail --silent --show-error \
-F '[email protected];type=application/pdf' \
-F 'output_format=markdown' \
"${MARKER_BASE_URL:?请设置已确认的入口}/marker/upload" \
-o marker-result.json
```
检查转换是否成功,再将 Markdown 保存到本地:
```python
import json
from pathlib import Path
result = json.loads(Path("marker-result.json").read_text())
if result.get("success") is not True:
raise SystemExit("转换失败,请检查返回的 error 字段")
Path("sample.md").write_text(result["output"])
```
接口和返回结构依据 [Marker server 源码](https://github.com/datalab-to/marker/blob/master/marker/scripts/server.py)。
HTTP 成功不等于转换成功,需要检查 `success`。返回还可能包含图片数据;仅写出 `output`
不会将图片自动保存为独立附件。需要完整图文时应按实际版本返回的图片字段另行保存并核对引用。
## 资源与文档边界
本地 README 的目标是适配 4 GB 显存,保持单副本、单 worker,并避免并发转换。
显存不足时先缩小测试文件或处理范围,不直接增加副本或并发。
Pod 没有业务 PVC,消费者应保存转换结果,不能将容器临时目录当文档库。
转换结果需要复核表格、代码、顺序及遗漏,再写入知识库;转换工具不确认文档事实或当前服务状态。
连接失败检查部署入口与监听地址,转换失败检查文件、模型加载及 GPU 资源。
依赖为 Kubernetes、GPU 设备支持、模型与临时磁盘;部署维护入口为 `apps/marker/README.md`。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#marker)。
+59
View File
@@ -0,0 +1,59 @@
---
title: NetBox 使用指南
lifecycle: experimental
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# NetBox
NetBox 用于浏览网络设备、接口与 IP 地址关系,目前是已部署的评估环境。
权威拓扑保存在 homelab-infra 的 `apps/netbox/terraform/topology.yml`,NetBox 是它的派生镜像。
已有配置生成试验,不代表真实网络已由 NetBox 自动驱动。
本页依据工作区 `apps/netbox/README.md` 及相关设计记录整理;本轮没有登录或查询现场。
## 打开与登录
在能访问 LAN 的环境打开 [NetBox](https://netbox.ad.ddupan.top),通过 Authelia 登录并完成二次认证。
源码记录入口访问限制为 AD 的 `netbox-admins` 组;有 AD 账号本身并不足以获得访问权限。
这里使用网关的 Authelia **forward-auth**,NetBox 接收经网关认证的用户与组信息。
NetBox 没有独立的 OIDC client;不要因 Authelia 是主 OIDC broker 就替它配置另一套 OIDC 登录。
正常使用从域名入口进入,不能绕过网关或自行构造 Remote-User 等身份头。
## 第一次浏览设备与地址
1. 在 Devices 列表中搜索要了解的设备,打开详情,查看角色、主要地址与 Interfaces。
2. 从接口查看关联的 IP 地址;有连接记录时,再沿关联对象查看另一端。
3. 在 IPAM 的 Prefixes 中搜索目标网段,例如源拓扑记录中的 `192.168.10.0/24`。
4. 查看该前缀下的地址记录,再打开地址详情,确认其关联接口和设备。
这条路径用于回答“这个地址记录给谁、接口属于哪台设备”等问题。
NetBox 中的地址状态来自资产记录,不会自动证明主机在线、地址当前无占用或 DHCP 已下发。
排查实时故障仍需相应运行证据;AI 查询现场前须按本库规则先与维护者对齐范围。
对象概念可参考 [NetBox IPAM 文档](https://netbox.readthedocs.io/en/stable/features/ipam/)。
## 发现记录需要修改时
先在 Git 中修改 `apps/netbox/terraform/topology.yml`,由维护者按该目录 README
审查 Terraform plan 并同步镜像;不要把 UI 编辑作为持久修改入口。
镜像中的手工改动可能与下次同步冲突;从拓扑文件移除对象也可能在 plan 中产生删除,需审查影响。
资产记录不保存 Wi-Fi 密码等秘密,凭据由 [OpenBao](openbao.md) 等既有秘密管理流程提供。
面向 VyOS OSPF 与 Samba AD DNS 的生成脚本属于评估成果,运行生成器与实际应用网络配置是不同步骤;
看到 NetBox 记录更新,不能宣称路由、DNS 或 DHCP 已同步。
## 遇到问题先看哪里
- 无法访问域名:检查 LAN DNS、路由及共享 Envoy 入口。
- 登录后被拒绝:核对 Authelia 访问规则及 AD 组;不要通过直接访问后端绕过认证。
- 记录缺失或不一致:对照 Git 拓扑和上一次同步记录,区分来源缺失与镜像尚未同步。
- 数据库或应用异常:转到部署 README,检查对应依赖和恢复流程。
部署、依赖、认证边界、拓扑同步与配置生成细节见 homelab-infra `apps/netbox/README.md`。
应用使用数据库与 Redis,登录链路依赖 LAN DNS、Envoy、Authelia 和 Samba AD。
本地管理员属于故障恢复入口,日常浏览不使用该路径。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#netbox)。
+97
View File
@@ -0,0 +1,97 @@
---
title: Nexus Repository POC
lifecycle: experimental
evidence: configuration
last_reviewed: 2026-09-18
last_verified: null
sources: []
---
# Nexus Repository POC
Nexus Repository Community Edition POC 计划为一次性 CI runner 提供共享的 Ansible Galaxy、
Go Modules 与 OCI/BuildKit 缓存,减少每个 job 从公网重新下载依赖的时间。当前只有未提交的
GitOps 与 Terraform 配置,尚未部署、初始化或完成端到端验证;现役 zot 保持不变。
## 从哪里使用
- 计划入口:`https://nexus.ad.ddupan.top`,仅 LAN。
- 人类管理:POC 首次使用本地管理员;后续正式化优先使用 Samba AD LDAP。Community
Edition 不提供原生 OIDC/SAML,因此不能把 Authelia OIDC 写成已支持入口。
- CI 读取:目标是对 public/group repository 开放 LAN 匿名只读。
- CI 发布:目标是少量按信任边界划分的本地 service account,凭据由 OpenBao 保存;
当前 POC 尚未创建 publisher 或授予写权限。
不能在整个入口套用 Authelia browser forward-auth:`ansible-galaxy`、Go 和 OCI 客户端
不会完成浏览器登录。若以后给 UI 单独加 RUT/forward-auth,必须使用与 package API 分离
且不可绕过的入口,并先完成 Header 信任边界审计。
## 第一次使用
部署与 Terraform 初始化完成后,Ansible 客户端将 Galaxy server 指向:
```ini
[galaxy]
server_list = nexus
[galaxy_server.nexus]
url = https://nexus.ad.ddupan.top/repository/ansible-public/
```
然后在已有 `collections/requirements.yml` 的项目中运行:
```bash
ansible-galaxy collection install -r collections/requirements.yml \
-p .ansible/collections
```
预期首次请求从上游获取 collection,第二次在全新 runner 中由 Nexus 返回已缓存内容。
该预期尚未现场验证;验证时同时记录冷/热耗时和 Nexus 日志,不能只看命令退出码。
Go POC 使用:
```bash
GOPROXY=https://nexus.ad.ddupan.top/repository/go-public/ go mod download
```
私有 module 的 `GOPRIVATE`、认证和 fallback 需由实际 workflow 明确配置,不能把内部 module
路径意外发送到公共 proxy。
## POC 限制
- 单副本、50 GiB OpenEBS RWO PVC,资源上限 2 CPU / 4 GiB。
- 当前使用 embedded H2,仅用于 POC;正式保存唯一制品前迁移至外部 PostgreSQL。
- 当前没有独立备份或恢复验收,PVC 不能被视为备份。
- Terraform provider 已声明 Ansible 与 Go proxy/group;provider 1.17.0 尚未暴露 Nexus
3.94 新增的原生 OCI repository resource。
- OCI 必须在补齐声明式 REST/provider 管理后再测试,不保留仅通过 UI 创建的长期配置。
- BuildKit registry cache 有待单独验证,普通 OCI image push 成功不能替代该测试。
## 出问题时
先检查 Flux、Pod、PVC、Route 与最近日志:
```bash
kubectl -n flux-system get kustomization nexus
kubectl -n nexus get pod,pvc,service,httproute
kubectl -n nexus logs deployment/nexus --tail=100
```
首次启动可能持续数分钟。PVC 未 Bound 时先查 OpenEBS;Route 未 Accepted/ResolvedRefs 时查
Gateway parentRef 与 Service;公网依赖获取失败时区分 Nexus 本身、LAN DNS 和已知不稳定
WAN,不以重建 PVC 作为排障手段。
## 运维入口
实现入口为 homelab-infra 工作区中尚未提交的 `apps/nexus/` 与
`clusters/homelab/apps/nexus.yaml`。DNS 期望记录位于 `infrastructure/dns/records.yml`。
源码 README 维护部署、初始化、Terraform、验收与恢复边界。
部署依赖 Envoy Gateway、OpenEBS 和 LAN DNS;Terraform 管理依赖 Nexus 初始化后的受限管理
账号及 OpenBao 注入凭据。现阶段不依赖共享 PostgreSQL,正式化时才建立独立数据库与 role。
## 当前状态与证据
2026-09-18 已准备未提交的 Kubernetes、Flux、DNS 与 Terraform POC 配置,并完成本地渲染和
schema 检查后方可交付;未访问现场、未部署 Nexus、未申请凭据,也未修改或迁移 zot。
后续状态必须以合并记录、Flux 状态和客户端冷/热缓存验收分别更新,不能仅凭本页推断上线。
+71
View File
@@ -0,0 +1,71 @@
---
title: OCI 登录与维护入口
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# OCI 云上基础设施
OCI 部分由独立 Terraform root 管理云 API 资源,实例内的软件与网络配置由 Ansible 管理。
本页仅提取 homelab-infra 工作区 `infrastructure/oci/README.md` 与 `ansible/README.md`
中已有的使用路径,不查询云资源、SSH、WireGuard 或 BGP 状态。
已核对 Terraform 的 OCI backend、provider profile 与两台实例的 `prevent_destroy` 声明。
README 有工作区修改,Ansible/Terraform 目录包含尚未提交内容;正式版本来源仍需补全。
维护者于 2026-09-16 明确:本组件优先 IaC,以代码为准。Ansible/Terraform 的声明及任务
是配置依据,README 负责解释;代码存在不等于本轮已验证部署结果。
## 第一次登录
源码记录大阪区域 `ap-osaka-1`,提供两个 DNS 登录入口:
```bash
ssh [email protected]
ssh [email protected]
```
选择自己获准访问的实例,用既有 SSH agent/key 登录;不复制私钥或禁用 host-key 校验。
以上名称对应直连公网 A 记录,不能当成 Cloudflare HTTP 代理入口。
实际权限、主机密钥与登录成功情况本轮未验证;首次使用从维护者取得可信主机信息。
DNS 记录的声明源为 `infrastructure/dns/records.yml`。
源 README 记录 DNS 尚未纳入 OCI Terraform state,公网 IP 变更时需协调更新记录,
不能认为修改实例就自动完成 DNS 同步。
## 访问家中网络与 DN42
站点网络细节统一查阅 `infrastructure/oci/ansible/README.md`,其中包含 VyOS、OCI AMD、
WireGuard、BGP 和 DN42 的地址、过滤与检查步骤。本页不维护第二份邻居或路由实时清单。
使用已有网络的应用无需自行创建 WireGuard peer 或修改 BGP。
遇到私网不可达,先区分 DNS、目标服务、路由、隧道与过滤;隧道握手成功不代表业务前缀已安装。
内部家中/OCI 业务前缀不得通告给外部 DN42 邻居,不能为临时接通扩大所有前缀的 export 规则。
Docker 地址池还须避开 DN42 `172.20.0.0/14`,相关记录见 `infrastructure/docker/README.md`。
## 管理变更走哪个入口
| 修改内容 | 原有管理入口 |
|---|---|
| 实例、VCN、NSG、云路由等 API 对象 | `infrastructure/oci/terraform/` |
| 主机/路由器软件、隧道及 BGP 配置 | `infrastructure/oci/ansible/` |
| DNS 名称 | `infrastructure/dns/records.yml` 与所属 DNS 后端 |
Terraform 使用 OCI Object Storage 的既有远端 state,认证依赖本机 OCI profile。
新 checkout 按源 README 准备受限 metadata 输入后才能 plan,不能复制 wiki 中不存在的“通用 tfvars”。
恢复目录的 state 副本不作为日常 backend,也不能上传覆盖远端对象。
维护者审查 plan 或 Ansible check/diff 后再实施对应变更;plan/state/metadata 可能包含秘密,不进 Git 或公开文档。
保留实例 `prevent_destroy`,遇到替换计划先查原因,不能为了让 apply 通过直接移除保护。
所读 README 的历史配额与免费机型检查不是持续费用保证,新增资源时另行核对。
## 恢复与依赖
实例登录依赖 DNS、公网路径、SSH 授权与主机;站点访问另依赖家中路由器、云端网络规则和路由协议。
云 API 状态正常与客户机内部服务正常是不同层面的证据。
恢复设计和接管历史见 `infrastructure/oci/README.md`,网络维护及私钥边界见 `ansible/README.md`。
不把旧 state 恢复步骤、迁移收尾 playbook 或历史验证命令当作每次登录前要执行的初始化。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#oci)。
+88
View File
@@ -0,0 +1,88 @@
---
title: OpenBao 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# OpenBao
OpenBao 提供秘密管理与内部 CA,部署在 Kubernetes 之外的独立主机上。
日常使用是以自己的身份登录,按已有 policy 读取秘密或申请短期凭据。
本页依据 homelab-infra 工作区 `infrastructure/openbao/README.md` 整理,
CLI 语法参考下列官方文档。本轮未登录服务、读取秘密或验证现场。
## 人的登录入口
前提是客户端能解析并访问内部域名,已安装 `bao` CLI,且账号具备相应 OIDC 授权。
```bash
export BAO_ADDR=https://bao.ad.ddupan.top:8200
bao login -method=oidc -no-print
```
按提示通过浏览器进入 Authelia,完成登录和二次认证。
使用域名进行 TLS 校验,不用 IP 地址代替,也不关闭证书校验。
`-no-print` 避免显示 token,但成功登录后仍会把它存入本机 token helper,供后续命令使用。
因此应在自己的受控会话中登录。参见 [OpenBao login](https://openbao.org/docs/commands/login/)。
登录成功后,只查看当前会话的权限与有效期:
```bash
bao token lookup -field=policies
bao token lookup -field=ttl
```
这两个命令不打印完整 token;字段选项见
[token lookup](https://openbao.org/docs/commands/token/lookup/)。能登录不代表能读取任意秘密。
## 按授权路径读取一个字段
先由服务所有者提供准确的 mount、秘密路径和字段名。
下例 `YOUR_AUTHORIZED_PATH` 是占位符,须替换为 `kv` mount 下已授权且存在的路径;
`password` 也应替换为实际字段名。命令仅适合已获相应权限的会话。
```bash
set +x
APP_PASSWORD="$(bao kv get -mount=kv -field=password YOUR_AUTHORIZED_PATH)"
# 在当前会话中交给实际消费者;不要 echo,也不要放入命令行参数或日志。
unset APP_PASSWORD
```
示例只演示接收字段后清除变量,不会配置任何应用;接入脚本还应检查命令失败并停止后续操作。
`kv get` 会处理 KV 引擎的 API 路径,CLI 的相对路径无需自行插入 `data/`。
参见 [OpenBao kv get](https://openbao.org/docs/commands/kv/get/)。
Kubernetes 应用通常消费 ESO 投射的 Secret。修改秘密应通过其受管来源及对应服务的轮换流程,
不能只编辑 ESO 生成的副本。不要把完整秘密内容粘贴到 AI 上下文、issue 或 wiki。
## 机器身份的使用边界
| 调用者 | 本库已记录的认证路径 |
|---|---|
| 人 | Authelia OIDC 登录 |
| laptop 本地 AI agent | 独立客户端证书,cert auth role 为 `local-agent` |
| SPIFFE workload | 按 [SPIRE 接入说明](spire.md) 与对应 OpenBao role 配置换取 token |
源码记录的本地 agent 证书与私钥由 Ansible 安装在 `/etc/homelab-agent/openbao/`,
不要复制到仓库或 workflow。其 token TTL 为 15 分钟、最长 1 小时;权限包括受限的 SSH 签名、
自身证书续期及 `kv/agents/local/*`,明确不包含 `kv/k8s/*`。
证书注册、登录与续期按源码 README 操作,不能从 SPIFFE 的整体设计推断该路径已迁移。
SPIFFE 验证机器身份,OpenBao 自己签发 token 并维护 policy。
Dynamic Runner 提供执行环境和 workload 身份,具体向 OpenBao 请求什么 token 由 workflow 决定。
## 权限申请与故障入口
申请权限时提供调用者身份、准确路径、所需动作、有效期及用途,由维护者调整受管 role/policy。
遇到拒绝访问先核对上述信息及会话有效期,不用管理员 token 代替应用身份。
连接失败时先区分内部 DNS、网络、TLS 与认证问题;OIDC 回调问题需结合客户端浏览器所在位置排查。
部署、PKI、SSH 签名、本地 agent 身份和恢复细节见 homelab-infra
`infrastructure/openbao/README.md`。服务依赖主机持久存储及 Raft 数据,人的登录还依赖 Authelia。
根密钥与恢复身份不应依赖 Kubernetes 或只能由 OpenBao 自身解密的秘密;
日常登录成功不等于已完成备份或灾难恢复验收。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#openbao)。
+78
View File
@@ -0,0 +1,78 @@
---
title: OpenEBS PVC 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# OpenEBS 本地持久存储
应用通过 PVC 申请持久存储。homelab 使用的 StorageClass 为 `localpv-zfs-ceph`,
provisioner 为 `zfs.csi.openebs.io`,底层来自宿主 `data/ceph` ZFS pool/dataset。
名称中的 `ceph` 不代表它提供 Ceph 分布式存储能力。
本页依据 homelab-infra `platform/openebs/README.md` 与 `storageclasses.yaml` 整理,
未查询 PVC、宿主存储或现场容量。源码 README 的历史消费者列表包含已退役项目,
当前服务归属以[服务总览](index.md)为准,不照抄为现役卷清单。
## 为应用声明 PVC
先确定容量、namespace、备份需求及应用调度约束。
以下在应用已有 namespace 中申请 1 GiB,容量和名称需按实际用途替换:
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: your-app-data
namespace: your-app
spec:
accessModes:
- ReadWriteOnce
storageClassName: localpv-zfs-ceph
resources:
requests:
storage: 1Gi
```
在应用 Pod spec 中引用该 PVC,容器再用 `volumeMounts` 挂载:
```yaml
volumes:
- name: data
persistentVolumeClaim:
claimName: your-app-data
```
```yaml
volumeMounts:
- name: data
mountPath: /var/lib/your-app
```
后两段分别是 Pod 与容器配置片段,不是独立 Kubernetes 对象。
应用与 PVC 必须位于同一 namespace;挂载路径及文件权限以应用要求为准。
把声明纳入应用既有的 GitOps/部署入口,本轮未创建或挂载 PVC。
## 等待绑定与节点约束
StorageClass 配置 `WaitForFirstConsumer`,PVC 在没有可调度消费者时保持 Pending 不一定是故障。
检查时结合消费 Pod 的调度事件、StorageClass、节点与存储池容量,不能通过删除重建业务 PVC 试错。
此为节点本地存储,数据可用性依赖对应宿主;应用不能假设跨节点重调度后自动获得同一份数据。
绑定与回收语义参见 [Kubernetes StorageClass 文档](https://kubernetes.io/docs/concepts/storage/storage-classes/)。
## 扩容、删除与恢复
配置允许卷扩容,但扩容需要按 CSI、文件系统和应用要求确认结果;不要将其理解为支持任意缩容。
默认 `reclaimPolicy: Delete`:删除 PVC 可能触发其 PV 与底层数据删除,
实际处理还应检查该 PV 自身的回收策略。应用退役前需明确数据保留或删除决定。
本地持久卷不是独立备份,也不自动提供多副本高可用。
为数据库等应用选择备份和恢复方式时,需考虑应用一致性及宿主故障,而不只看 PVC 是否 Bound。
运维与 break-glass 入口为 `platform/openebs/README.md`。
StorageClass 独立于 Helm release 管理;不要通过卸载 chart、删除 CRD 或业务卷验证升级。
依赖包括 OpenEBS ZFS CSI、宿主 ZFS、文件系统与 Kubernetes 调度。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#openebs)。
+102
View File
@@ -0,0 +1,102 @@
---
title: OpenViking 导入与查询指南
lifecycle: unknown
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# OpenViking
OpenViking 为文档和 agent 上下文提供导入与检索能力。
本页依据 homelab-infra `apps/openviking/README.md`、Compose 和上游接口文档整理,未访问实例。
仓库提供部署方案,未据此断言服务已上线或 wiki 已自动同步到索引。
## 入口与数据位置
| 用途 | Compose 默认值 |
|---|---|
| HTTP API | 宿主端口 `1933` |
| Console/UI | 宿主端口 `8020` |
| embedding endpoint | 宿主回环地址 `127.0.0.1:8081` |
| 持久数据与配置 | `./data` |
| embedding 模型缓存 | `./models` |
这些端口可被环境配置覆盖,实际宿主地址、客户端 key 与权限由维护者提供。
服务端 VLM 使用 `openai-codex` provider,本地 embedding 服务使用 llama.cpp CUDA 镜像;
客户端 API key 与服务端模型认证不是同一份凭据,不将服务端 OAuth 数据交给检索客户端。
当前镜像标签为 `latest`,接口需与实际部署版本核对。
## 导入、等待、查询与读取
先设置 `OPENVIKING_BASE_URL` 为已授权的 API 根地址;入口需要 key 时,通过既有秘密注入方式
提供 `OPENVIKING_API_KEY`。以下 Python 标准库片段共用同一会话;只处理一份公开上游 README,
会写入索引并触发模型处理。本轮没有执行导入或请求。
```python
import json
import os
import urllib.parse
import urllib.request
base = os.environ["OPENVIKING_BASE_URL"].rstrip("/")
headers = {"Content-Type": "application/json"}
if os.environ.get("OPENVIKING_API_KEY"):
headers["X-API-Key"] = os.environ["OPENVIKING_API_KEY"]
def request(path, payload=None):
data = None if payload is None else json.dumps(payload).encode()
req = urllib.request.Request(base + path, data=data, headers=headers)
with urllib.request.urlopen(req, timeout=120) as response:
return json.load(response)
result = request("/api/v1/resources", {
"path": "https://raw.githubusercontent.com/volcengine/OpenViking/refs/heads/main/README.md"
})
print(json.dumps(result, ensure_ascii=False, indent=2))
```
从返回数据取得 `task_id` 与资源 URI。`accepted` 只表示已接收,随后用同一会话查询任务:
```python
task_id = "REPLACE_WITH_RETURNED_TASK_ID"
print(request("/api/v1/tasks/" + urllib.parse.quote(task_id, safe="")))
```
任务到达 `completed` 后再搜索;`failed` 或 `cancelled` 应先处理原因,不能当作入库成功。
避免因请求超时直接反复导入同一来源。参见上游
[资源 API](https://github.com/volcengine/OpenViking/blob/main/docs/en/api/02-resources.md) 和
[任务 API](https://github.com/volcengine/OpenViking/blob/main/docs/zh/api/17-tasks.md)。
```python
print(request("/api/v1/search/find", {
"query": "What is OpenViking?", "limit": 5
}))
```
从搜索结果中选择一个文件 URI,读取正文:
```python
uri = "REPLACE_WITH_RETURNED_FILE_URI"
query = urllib.parse.urlencode({"uri": uri})
print(request("/api/v1/content/read?" + query))
```
检索和读取方式见[上游检索文档](https://github.com/volcengine/OpenViking/blob/main/docs/en/api/06-retrieval.md)。
返回目录时先查看其概览或子项再选文件,不把任意目录 URI 当正文文件使用。
HTTP 成功之外,还要检查各次响应中的应用状态与错误信息;响应封装以部署版本为准。
## 人与 AI 如何使用检索结果
检索结果用于定位资料,最终结论回到原始 Markdown、源码 README 或 ticket 核对日期与证据。
本 wiki 的 Git 仓库仍是正式文档来源;索引不是自动获得权威性的另一份状态记录。
尚未建立本库自动导入、增量更新或删除同步的已验证流程,不能把旧索引结果当作当前事实。
导入前明确资料范围及模型处理边界。不要将凭据、Terraform state 或含秘密的整个工作目录批量导入。
本地 embedding 不意味着所有语义处理都在本地完成,VLM 仍使用 README 所述的上游认证路径。
连接失败核对宿主端口;导入失败区分来源可达性与解析;任务卡住或结果缺失再查看 VLM、embedding
与队列处理。数据在 `./data`,模型缓存可重新下载,两者不能按同一种可丢弃缓存处理。
部署、模型初始化与认证维护回到 `apps/openviking/README.md`。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#openviking)。
+1
View File
@@ -21,6 +21,7 @@ homelab 资源有限,为每个应用维护一套数据库会浪费资源。绝
计划自行实现这个中间层,让下游通过统一接口申请可消费的数据库,降低共享实例的管理成本。
这段现状和设计动机由维护者于 2026-09-16 提供;本轮没有查询数据库或集群。
现有实例的日常接入见[共享 PostgreSQL 使用指南](shared-postgresql.md)。
现有实例的源码入口为 homelab-infra 的 `apps/shared-postgresql/`。
## 当前进度
+78
View File
@@ -0,0 +1,78 @@
---
title: Proxmox 日常管理入口
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# Proxmox
Proxmox 承载 VM/LXC 与相应主机、网络和存储资源。
本页依据 homelab-infra 工作区 `infrastructure/proxmox/README.md`、`README-ha.md`
及已有 DNS 名称整理使用入口,不检查集群成员、VM、HA 或存储现场状态。
源码 README 尚未跟踪,HA 文档有工作区修改;配置已进一步核对 `auth.yml`、`site.yml`、
`ha.yml` 与对应 role defaults,不将文档中的历史阶段备注当作当前配置。
维护者于 2026-09-16 明确:本组件优先 IaC,以代码为准。Ansible/Terraform 的声明及任务
是配置依据,README 负责解释;代码存在不等于本轮已验证部署结果。
## 打开管理界面
DNS 清单记录 `pve1.ad.ddupan.top`、`pve2.ad.ddupan.top`、`pve3.ad.ddupan.top`。
Proxmox 默认 HTTPS 管理端口是 `8006`,因此可按维护者确认的节点尝试:
```text
https://pve1.ad.ddupan.top:8006/
```
这是节点名与上游默认端口组合出的入口示例,未验证可达性或证书配置。
端口与节点代理行为见 [Proxmox pveproxy 文档](https://github.com/proxmox/pve-docs/blob/master/pveproxy.adoc)。
`pve_auth` role 声明 `ad` realm,通过 LDAPS 连接 `dc1.ad.ddupan.top:636`,启用证书校验;
域用户按此配置选择 `ad` realm,实际可用权限取决于账号同步及 ACL。`auth.yml` 独立管理该配置。
`pve_acme` role 使用 OpenBao 内部 CA 为节点域名签证书,浏览器需具有相应 CA 信任。
这些是代码声明,不是新的登录验证;不能因 Authelia 是 Web SSO 主入口就推断 PVE 已接入 OIDC。
## 第一次定位一台虚拟机
1. 登录后在资源树中找到目标 VM/LXC,核对名称、VMID 和所在节点。
2. 查看 Summary 与任务记录,区分 guest 状态、节点状态和最近操作结果。
3. 查看 Hardware/Resources 与网络、磁盘配置,确认对应的业务服务。
4. 需要 guest 内部诊断时,再按授权使用 Console 或该 guest 的 SSH 入口。
VMID 可能被复用,不能仅凭一个旧 VMID 判断当前对象归属。
控制台可打开也不等于客户机网络、存储和业务健康。
启动、关闭、迁移、克隆及删除都是独立变更,不作为“查看状态”的附带动作。
## 持久配置与短命 VM 的职责
源目录使用 Ansible 管理节点软件、内核、网络、LINSTOR/DRBD 与 watchdog 等主机配置。
VM 和集群对象的具体管理工具以对应目录为准,不把迁移到 Terraform 的设想写成全部完成。
UI 中临时改动需回写对应受管来源,避免后续自动化覆盖。
动态 CI VM 的使用接口见 [Gitea Dynamic Runner](gitea-dynamic-runner.md),
其生命周期由 runner controller 负责,不能逐台登记进长期 Terraform state。
每个动态 Pod/VM 应独立取得 SPIFFE 身份;workflow 决定登录与请求 token。
源码 README 的 SDN-backed identity 和 AppRole bootstrap 段落属于早期设计记录,
不作为当前统一身份原则或最新 runner 实现的依据。
## 网络、HA 与存储边界
现有设计记录中的 VLAN/VNet 分段不能直接证明 guest 的机器身份;
IP、MAC、VMID 的自报值不能代替可信身份验证。
修改 bridge、SDN 或路由 guest 时,先明确承载哪些业务与管理路径,不能只看当前登录是否仍连通。
`README-ha.md` 记录了 VyOS guest 的 HA 和 watchdog 工作。它描述的是故障后重新启动的路径,
不应承诺无中断切换,也不能推断其他 guest 全部启用 HA。
`pve_ha` role 的资源默认值只列 `vm:100`,`ha.yml` 独立于节点基线 `site.yml`,
避免基线维护顺带改变 HA/fencing 行为。watchdog 的实际选择还需结合 inventory 覆盖与任务实现;
本轮不从旧 README 的 softdog 标题推断当前现场状态。
PVE 主机存储、DRBD 副本和 k3s 的 [OpenEBS](openebs.md) 是不同管理层,
不能互相替代容量、冗余或恢复验证。快照和副本也不能自动证明具备独立备份。
故障入口依次为目标任务日志、guest、宿主节点、存储和集群网络;
涉及 quorum、fencing 或 watchdog 的处理先读 `README-ha.md`,不要套用普通单机重启排障。
长期配置入口为 `infrastructure/proxmox/ansible/`,并按实际变更选择对应 playbook。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#proxmox)。
+49
View File
@@ -0,0 +1,49 @@
---
title: ps3netsrv 使用指南
lifecycle: unknown
evidence: configuration
last_reviewed: 2026-09-16
last_verified: null
---
# ps3netsrv
为 PS3 客户端通过网络读取游戏内容提供服务。
维护者于 2026-09-16 表示没有需补充的动态事项;本页依据工作区
`apps/ps3netsrv/docker-compose.yml` 整理。该文件有未提交修改,以此处注明的工作区为来源。
本轮没有查询容器、磁盘内容或客户端状态。
## 入口与内容目录
| 项目 | 配置记录 |
|---|---|
| 镜像 | `shawly/ps3netsrv:latest` |
| TCP 端口 | 宿主 `38008` → 容器 `38008` |
| 宿主内容目录 | `/mnt/pool/games/ps3` |
| 容器内目录 | `/games`,当前映射为读写 |
所读 Compose 没有指定客户端应使用的宿主 IP 或域名,接入时由维护者提供实际地址。
这不是浏览器 HTTP 服务,也不能将路径挂载成功等同于客户端已发现内容。
## 第一次从 PS3 浏览内容
1. 确认目标内容已放入宿主映射目录,且容器配置的用户具有读取权限。
2. 按客户端要求组织子目录,例如 ISO 内容位于 `PS3ISO/`,目录形式内容位于 `GAMES/`。
3. 在 webMAN MOD 的网络内容设置中填入服务器地址和端口 `38008`,启用对应网络内容扫描。
4. 刷新内容列表,选择一个条目挂载并读取,确认整个客户端路径。
目录结构见 [容器项目说明](https://github.com/shawly/docker-ps3netsrv),客户端操作见
[webMAN MOD PS3 NET Server](https://github.com/aldostools/webMAN-MOD/wiki/~-PS3-NET-Server)。
本轮未执行以上步骤;具体客户端版本的菜单名称可能不同。
## 排障与维护边界
- 无法连接:核对实际宿主地址、TCP 端口和客户端到宿主的网络。
- 列表为空:核对宿主目录、子目录结构、文件权限与客户端扫描设置。
- 发现内容但读取失败:核对文件可读性及客户端格式支持,再看服务日志。
Compose 的 `USER_ID` / `GROUP_ID` 控制容器读文件时的身份;调整前核对宿主所有权,
不要为排障递归修改整个存储池的权限。挂载目录属于内容数据,重建容器不会替代数据备份。
依赖为 Docker、宿主存储、网络和相容客户端;本页不修改容器或数据目录。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#ps3netsrv)。
+93
View File
@@ -0,0 +1,93 @@
---
title: Samba AD 日常使用入口
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# Samba Active Directory
Samba AD 提供人的目录身份、Kerberos、LDAP、域 DNS 和组策略;
[Authelia](authelia.md) 在此之上提供 Web 登录,[SPIFFE](spire.md) 负责 workload 身份。
AD 组成员资格与每个服务最终授予的权限仍需分别配置。
本页根据 homelab-infra 工作区 `infrastructure/samba-ad/README.md` 整理。
已核对 Ansible 的域变量、`join-windows.yml`、`join-member.yml` 与 member role 任务。
这些来源含未提交修改;没有查询域成员、用户或现场配置。
DNS 的已确认口径见 [LAN DNS](lan-dns.md),不重新盘点主机。
维护者于 2026-09-16 明确:本组件优先 IaC,以代码为准。Ansible/Terraform 的声明及任务
是配置依据,README 负责解释;代码存在不等于本轮已验证部署结果。
## 域与管理入口
| 项目 | 已有资料中的值 |
|---|---|
| DNS domain | `ad.ddupan.top` |
| Kerberos realm | `AD.DDUPAN.TOP` |
| NetBIOS domain | `DDUPAN` |
| 域控 | `dc1.ad.ddupan.top` / `192.168.10.5` |
| 图形管理 | Windows 管理机上的 RSAT:AD Users & Computers、GPMC、DNS |
管理机地址与登录身份由维护者提供。日常 Web 登录从对应应用进入 Authelia,
无需登录域控,也不向普通应用交付 Domain Administrator 凭据。
## 入域之前与入域路径
入域设备需要准确时间、域控连通性和能找到 AD SRV 记录的 DNS 路径。
不能直接照抄源 README 通用示例中的 `10.10.10.10`、`ad.example.com` 或 `EXAMPLE`。
也不要为入域统一改写所有 LAN 主机 DNS;按该设备的域解析需求配置,保留既有 LAN 设计。
Windows 管理机按 `infrastructure/samba-ad/ansible/` 的 inventory 与 `join-windows.yml`
管理,先核对目标主机、WinRM 与所用账号,再由维护者执行入域流程。
README 的手工命令用于解释角色行为,不是重新建域的日常操作步骤。
Linux 的 `join-member.yml` 面向 Samba member fileserver:它配置 winbind、NSS、SMB 与域解析,
明确不安装 `libpam-winbind`。因此文件服务器入域成功不等于已经启用 Linux 系统域账号登录。
修改前阅读角色对现有 `smb.conf`、共享与 UID/GID 映射的处理,不能将普通客户端套成文件服务器。
## 第一次查看用户与组
在已获管理授权的域控会话中,可使用以下只读命令;`YOUR_GROUP` 替换为目标组:
```bash
sudo samba-tool user list
sudo samba-tool group listmembers YOUR_GROUP
```
也可在 RSAT 的 AD Users & Computers 中查找用户,打开其组成员关系。
命令语义见 [Samba samba-tool 手册](https://www.samba.org/samba/docs/current/man-html/samba-tool.8.html)。
输出含账号信息,按任务范围使用,不把完整人员目录复制进公开 wiki。
本轮没有执行这些命令。
新增用户、组、权限或重置密码会改变目录状态,按现有 Ansible 声明或维护流程实施,
避免 UI 临时改动与下一次配置同步互相覆盖。密码通过受控交互或秘密管理提供,不写进命令示例。
应用权限排障先核对 AD 组,再核对 Authelia 策略与应用内映射。
## 故障与维护边界
入域失败先区分 DNS/SRV、时间、连通性与账号权限;已有成员认证异常再看信任关系及 winbind。
### Laptop 上的 Winbind RPC 子进程堆积
2026-09-14,`laptop` 的 `winbind.service` 下曾堆积 1677 个 `rpcd_lsad`。现场日志同时显示
SAMR/LSARPC pipe 断连,以及 AppArmor `samba-rpcd` profile 拒绝
`/run/samba/ncalrpc/np/samr` 和 `lsarpc` 的写访问。仅重启 winbind 会暂时释放内存,
但拒绝仍会触发新的 worker,因此不应把重启视为根治。
已在 `/etc/apparmor.d/local/samba-rpcd` 精确允许这两个 pipe 的 `rw` 权限,重载 profile
并重启 winbind。修复后 `wbinfo -t` 及域/BUILTIN 名称查询通过,短期复测没有新增拒绝;
该结论只适用于 laptop 的 Samba member,不应套用到 `dc1`。
复发时先采集 `free -h`、`pgrep -xc rpcd_lsad`、winbind cgroup 内存、内核 AppArmor
拒绝和 Samba 日志,再决定是否重启。不要关闭 AppArmor 或放宽整个目录;出现新路径时
应按审计日志逐项分析。此规则仍应纳入 `samba_member` Ansible role,避免主机重建后丢失。
静态 DNS 声明入口为 `infrastructure/dns/records.yml`,只管理明确列出的 RRset,
不清理 Samba 自动维护的域控制器 locator、Kerberos 等记录。
新服务 DNS 接入见[发布新服务](../guides/publish-service.md)。
域备份、第二域控和恢复方案回到源码 README;有备份命令不代表已建立定时异机备份或演练过恢复。
域控身份数据库与应用数据不同,不能通过重跑建域、清空数据库来排查普通登录失败。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#samba-ad)。
+87
View File
@@ -0,0 +1,87 @@
---
title: SeaweedFS S3 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# SeaweedFS 对象存储
SeaweedFS 为应用提供 S3 兼容对象存储,zot Registry 是它的消费者之一。
普通应用使用自己的 bucket 和 S3 身份;容器镜像通过 [zot](zot.md) 发布与拉取。
本页依据 homelab-infra 工作区 `apps/seaweedfs/README.md` 和 `apps/zot/README.md` 整理,
客户端语法参考 AWS CLI 官方文档。本轮未查询现场或读写对象。
## 连接入口与身份
| 场景 | endpoint |
|---|---|
| LAN 客户端的 HTTPS S3 入口 | `https://s3.ad.ddupan.top` |
| Kubernetes 集群内 Service | `http://seaweedfs-s3.seaweedfs.svc.cluster.local:8333` |
首次接入先明确自己的 bucket、需要的 Read/Write/List 等权限及凭据获取方式。
当前所读配置使用静态 S3 AK/SK,由 OpenBao 管理;SeaweedFS OIDC/STS 尚未接入。
zot 前端的 SPIFFE 登录不代表通用 S3 客户端已经能用 SPIFFE 换取 S3 凭据。
应用使用专属身份,不复用 zot 或 Terraform 的存储凭据。
Kubernetes Secret 是 ESO 生成的消费副本,身份或凭据变更应修改受管来源,不能手工改副本。
## 用 AWS CLI 查看自己的对象
前提:已安装 AWS CLI,并由既有授权流程将本应用的凭据注入当前进程环境
(`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`),或配置受保护的专用 CLI profile。
不要把实际 AK/SK 复制到命令示例、仓库或日志中。
将下例 bucket 替换为自己的已授权 bucket,先只读列出少量对象:
```bash
aws --endpoint-url https://s3.ad.ddupan.top s3api list-objects-v2 \
--bucket YOUR_APP_BUCKET --max-items 10 --no-cli-pager
```
预期返回对象信息或空 bucket 的结果。只具有指定 bucket 权限的身份,不必拥有列举所有 bucket 的权限;
因此不以全局 `aws s3 ls` 是否成功作为接入的唯一标准。
`--max-items` 控制返回条数,具体行为见
[AWS CLI list-objects-v2](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-objects-v2.html)。
## 上传和下载一个测试文件
仅在自己的测试 bucket/prefix 以及具备写权限时操作。替换占位符,并使用尚未占用的 key:
```bash
aws --endpoint-url https://s3.ad.ddupan.top s3 cp ./hello.txt \
s3://YOUR_APP_BUCKET/YOUR_UNUSED_TEST_KEY
aws --endpoint-url https://s3.ad.ddupan.top s3 cp \
s3://YOUR_APP_BUCKET/YOUR_UNUSED_TEST_KEY ./hello.downloaded.txt
cmp ./hello.txt ./hello.downloaded.txt
```
本地先准备 `hello.txt`。预期上传与下载成功,`cmp` 无输出且退出码为 0。
这会在目标 bucket 留下测试对象,是否清理由该 bucket 的所有者决定。
语法参考 [AWS CLI cp](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html)。
上游 S3 客户端文档用于解释命令,不代表 SeaweedFS 实现了全部 AWS S3 功能。
## zot 数据与维护边界
zot 专用数据位于 `zot` bucket 的 `registry/` 前缀,由 Registry 管理 OCI layout。
不要把普通文件直接写入该前缀,也不要用 S3 客户端手工删除镜像内部对象。
zot 的 S3 身份只允许相应 bucket 的 Read/Write/List/Tagging,不能访问 `tfstate`。
其凭据唯一来源为 OpenBao `kv/k8s/zot-s3`,由 ESO 同步给 zot 和 SeaweedFS;
基础 S3 身份配置在 `kv/k8s/seaweedfs-s3`,两份配置的合成及轮换见源码 README。
轮换不仅是改一个值,还需协调服务端重新加载和消费者更新,避免两端配置不一致。
## 遇到问题先看哪里
- 域名或连接失败:确认当前使用的是 LAN endpoint 还是仅集群内可达的 Service。
- 访问被拒绝:核对使用的应用身份、bucket/key 与所需动作权限,不直接扩大为管理员权限。
- 签名或凭据错误:核对凭据来源、同步情况和客户端配置;不要打印 AK/SK 排障。
- Registry 不可用:区分 zot 的 SPIFFE 客户端认证与它到 S3 的后端认证。
部署与配置来源:homelab-infra `apps/seaweedfs/README.md`、`apps/zot/README.md`。
单一存储系统内的数据副本不等于独立备份;zot 源文档尚未记录已建立独立异机/离线备份。
其他应用的数据保留与恢复策略应由各自用途明确,不能从“已接入 S3”推断已经完成备份。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#seaweedfs)。
+82
View File
@@ -0,0 +1,82 @@
---
title: 共享 PostgreSQL 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# 共享 PostgreSQL
集群内的多个服务共用一套 PostgreSQL,避免为每个应用维护独立数据库实例造成资源浪费。
共享实例已经在使用;计划中的 [PostgreSQL Tenant Operator](postgresql-tenant-operator.md)
将负责简化 database、role 和凭据的管理,目前不能把该计划当成已上线的自助申请入口。
共享使用的现状来自维护者于 2026-09-16 的说明。连接入口与部署配置来自 homelab-infra
工作区 `apps/shared-postgresql/`;本轮未连接数据库或查询 Kubernetes。
## 连接入口
| 使用场景 | 来源中记录的地址 |
|---|---|
| 集群内现有应用的兼容入口 | `shared-postgresql.shared-db.svc.cluster.local:5432` |
| CNPG 读写入口 | `shared-postgresql-rw.shared-db.svc.cluster.local:5432` |
| Tailscale 暴露所用的 Kubernetes Service | `shared-postgresql-tailscale`,namespace `shared-db` |
兼容 Service 的配置选择 CNPG primary。应用应使用 Service 地址,不固定到某个 Pod IP。
表中的 `.svc.cluster.local` 是集群内 DNS 地址;不能直接当作集群外客户端的可达地址。
Tailscale Service 配置存在不等于已经确认外部地址和访问权限,集群外接入须由维护者提供实际入口。
## 新应用接入前准备什么
向维护者说明应用名称、所需 database/role、扩展、连接数预期、网络来源及凭据消费方式。
由维护者按现有管理流程建立并授权,再提供连接参数和秘密引用;本页不提供尚未上线的 Tenant CR 示例。
应用使用自己的数据库与账号,不复用其他应用或实例管理员的凭据。
已有应用的秘密来源以各自 README 和配置为准,不能假定所有历史凭据已统一迁移到同一种流程。
使用 [OpenBao](openbao.md) 与 ESO 的应用,应消费受管秘密,不能直接修改 ESO 生成的副本。
连接 TLS 的要求及 CA 材料也应作为接入参数交付,不通过关闭校验解决连接问题。
## 第一次连接:确认目标数据库与身份
在已能访问集群内 Service、已安装 `psql` 的受控终端操作。
将下例占位符替换为已分配的 database 和应用 role;密码通过终端提示输入,不写入命令行或 wiki。
连接参数中的 TLS 配置沿用维护者交付的配置。
```bash
psql -X -W -v ON_ERROR_STOP=1 \
-h shared-postgresql-rw.shared-db.svc.cluster.local -p 5432 \
-U YOUR_APP_ROLE -d YOUR_APP_DATABASE \
-c 'SELECT current_database(), current_user, 1 AS connection_ok;'
```
预期返回自己的数据库名、登录角色及 `connection_ok = 1`。
该示例不修改业务数据,也不证明建表、迁移或其他权限已经满足。
`-X` 避免加载本地 psql 启动脚本,`-W` 请求密码提示,`ON_ERROR_STOP` 使命令遇错退出。
语法见 [PostgreSQL psql 文档](https://www.postgresql.org/docs/current/app-psql.html)。
AI 接续任务时先确认操作范围,再执行现场查询;不能因为存在这段示例就自动登录数据库。
## 共享实例的维护边界
- 应用 schema migration 只面向自己的数据库,按应用升级流程执行;需要额外扩展或权限时先交由维护者处理。
- 连接池、慢查询和批量任务会影响共享资源,新增消费者时应说明负载预期。
- 数据库停用、role 删除和数据清理是独立操作,不能因应用 manifest 删除就推断数据库可一并删除。
- 配置文件记录 `instances: 1`,使用 CNPG 本身不代表已经配置数据库多副本高可用。
存储配置为 OpenEBS 的 `localpv-zfs-ceph`。持久卷存在不等于已有独立备份或完成恢复验收,
本页不对当前备份情况作未经验证的结论。
历史迁移文档中的 dump/restore 与回滚步骤属于迁移场景,不能整段重跑作为日常接入流程。
其中出现的旧服务名也不代表这些服务仍在运行。
## 遇到问题先看哪里
- 域名不解析或连接超时:先确认客户端位于何处、使用的入口及网络访问范围。
- 认证失败:核对 role、database 和应用自己的凭据来源;不要改用 `postgres` 绕过问题。
- 登录成功但操作被拒绝:区分数据库连接、schema、表和扩展权限,向维护者提供失败动作,不发送密码。
- 多个消费者同时异常:转到共享数据库和存储的运维入口,避免在各应用中分别覆盖连接配置。
源码入口为 homelab-infra 的 `apps/shared-postgresql/migration.md`、
`cloudnativepg-cluster.yaml` 和 `shared-postgresql-service.yaml`(后两者位于同一目录)。
服务依赖 Kubernetes、CNPG、集群 DNS 与持久存储;Tailscale 入口另依赖对应网络及授权。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#shared-postgresql)。
+76
View File
@@ -0,0 +1,76 @@
---
title: SMTP relay 应用发信指南
lifecycle: unknown
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# SMTP relay
为集群应用提供统一出站邮件入口:应用通过集群内 SMTP 连接 relay,
relay 再使用 STARTTLS 与 XOAUTH2 向 Microsoft 365 提交邮件。
本页依据 homelab-infra `apps/smtp-relay/README.md` 与 Service/Deployment 配置整理,
本轮没有连接 relay、发送邮件或查询邮箱。
## 应用接入参数
| 参数 | 已记录值 |
|---|---|
| SMTP host | `smtp-relay.smtp-relay.svc.cluster.local` |
| SMTP port | `25` |
| 应用到 relay 的 TLS | 此内部链路按明文 SMTP 配置 |
| 应用到 relay 的认证 | 不提供用户名或密码 |
| From / envelope sender | `[email protected]` |
| relay 的上游 | `smtp.office365.com:587`,STARTTLS + XOAUTH2 |
这里的无认证入口限于既定内部使用路径,不能直接把它暴露为外部发信入口。
其他发件身份需要对应的 Send As 授权,不能只在应用中随意改 From。
应用只需要 relay 参数,不需要读取或持有 Microsoft 365 refresh token。
## 发送一封接入测试邮件
下面在已能访问集群 Service 的应用环境中使用 Python 标准库。
将 `SMTP_TEST_RECIPIENT` 设置为自己控制的收件地址;执行会真实发送邮件,应先得到该次发信授权。
这份示例本轮未执行。
```python
import os
import smtplib
from email.message import EmailMessage
recipient = os.environ["SMTP_TEST_RECIPIENT"]
sender = "[email protected]"
message = EmailMessage()
message["From"] = sender
message["To"] = recipient
message["Subject"] = "Homelab SMTP relay test"
message.set_content("SMTP relay integration test.")
with smtplib.SMTP("smtp-relay.smtp-relay.svc.cluster.local", 25, timeout=30) as smtp:
refused = smtp.send_message(message, from_addr=sender, to_addrs=[recipient])
if refused:
raise SystemExit("收件人被拒绝,请检查 relay 状态")
```
客户端提交成功只表示 relay 接收,不保证最终送达。
维护者随后结合 relay 投递日志与收件箱确认完整链路;也检查垃圾邮件文件夹。
日志中的上游接收结果仍不能替代收件人侧确认。
## 失败时如何区分
- 连接超时或域名失败:检查集群 DNS、Service 与应用网络范围。
- relay 接收但不送达:检查投递队列、上游连接和认证,而不是给应用配置上游密码。
- `535 5.7.3`:源码提示检查 OAuth 身份是否为实际 sender,以及 token 是否需要重新初始化。
- `5.7.60`:检查 From、envelope sender 与 Microsoft 365 的发信授权是否匹配。
消费者接入不能通过重跑完整 Terraform、部署或 OAuth 初始化流程来试错。
refresh token 持久化在 `smtp-relay-tokens` PVC,SASL 层负责更新;
它是可变运行数据,不是可复制进 wiki 的配置。
源码的 device-code 流程使用 public client,维护说明明确 `CLIENT_SECRET` 留空;
不要照抄同一旧 README 中与之不一致的“创建 client secret”注释。
初始化、重新授权、DKIM 与恢复入口为 `apps/smtp-relay/README.md`。
其中 DKIM 等日期属于历史记录,本文不将其升级为新一次验证。
依赖为 Kubernetes/DNS、token PVC、Microsoft 365 邮箱与授权、上游网络及域名邮件配置。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#smtp-relay)。
+64
View File
@@ -0,0 +1,64 @@
---
title: Tailscale 远程访问指南
lifecycle: unknown
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# Tailscale
Tailscale 提供远程访问 homelab 的网络路径。维护者于 2026-09-16 表示没有需补充的动态事项;
本页根据 `apps/tailscale/subnet-routes.sh` 和共享 PostgreSQL Service 配置整理。
未读取含 OAuth 值的安装脚本,也未查询 tailnet、路由批准状态或现场连通性。
## 两种访问路径
| 路径 | 来源记录的用途 |
|---|---|
| laptop 子网路由 | 访问 LAN 与两个 SDN 网段中的原有地址 |
| Kubernetes operator 暴露 Service | 为特定 Service 提供 tailnet 入口,例如共享 PostgreSQL |
子网脚本将 laptop(LAN 地址 `192.168.10.127`)记录为唯一子网路由器,声明以下完整路由集合:
- `192.168.10.0/24`:homelab LAN。
- `10.60.0.0/24`:SDN labnet。
- `10.61.0.0/24`:SDN retronet。
operator 管理的 Service 入口不能直接视为新的通用子网路由器。
子网路由可达也不等于拥有所有目标服务的应用权限。
## 第一次从远程客户端访问
1. 在自己的客户端登录维护者指定的 tailnet,完成该设备所需的批准流程。
2. 确认客户端接受子网路由。Linux 客户端需要时可执行下面的设置;它改变本机路由接受配置。
3. 打开已有权限的 LAN 服务,例如 [Grafana](grafana.md)。域名还须通过适当的 DNS 配置解析。
```bash
sudo tailscale set --accept-routes=true
```
客户端行为见 [Tailscale 子网路由文档](https://tailscale.com/docs/features/subnet-routers)。
服务登录仍按该服务自己的流程进行。
如果访问 operator 暴露的 Service,使用维护者提供的 tailnet 地址;
不要把 Kubernetes `.svc.cluster.local` 名称当成远程客户端已经可解析的名称。
## 路由、DNS 与权限分别检查
“客户端已登录”“路由已广播”“路由已批准”“访问规则允许”和“目标服务可用”是不同条件。
LAN 的 [Blocky / 路由器 DNS 设计](lan-dns.md) 不自动证明远程客户端已获得相同解析配置。
IP 可达而域名失败时,先查看远程客户端 DNS 路径,不直接改 LAN DNS。
脚本记录两个 SDN 网段由 laptop 从 VyOS 通过 OSPF 学习。
即使 Tailscale 仍广播这两个前缀,底层 OSPF 路由缺失也会导致转发失败。
新增路由还需 tailnet 批准及访问规则配合,单看广播配置不足以验收。
`apps/tailscale/subnet-routes.sh` 是维护端脚本,`--advertise-routes` 替换完整集合;
普通客户端接入无需执行它。新增网段时按完整声明审查,避免意外移除既有路由。
现有脚本提供批准信息的查看方法;执行现场检查前仍需按本库规则对齐范围。
依赖为 Tailscale 控制与数据路径、laptop 转发及目标网络;SDN 另依赖 VyOS/OSPF,
operator Service 另依赖 Kubernetes 和 operator。
本页没有记录 tailnet OAuth、设备密钥或凭据内容。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#tailscale)。
+28 -41
View File
@@ -1,58 +1,45 @@
---
title: 旧 VictoriaMetrics Compose 栈
title: 旧 VictoriaMetrics Compose 栈(已清理)
lifecycle: retired
evidence: live-verified
last_reviewed: 2026-09-16
last_verified: 2026-09-16
sources:
- 维护者提供的 Kubernetes 完整可观测性栈替代目标
- 2026-09-16 本机 Docker 容器、卷及文件元数据只读检查
- 2026-09-16 monitoring namespace 的资源状态只读检查
- 维护者于 2026-09-16 明确要求直接删除旧配置和全部旧数据卷
- 2026-09-16 Docker 卷删除前后检查及 Kubernetes monitoring 状态检查
---
# 旧 VictoriaMetrics Compose 栈
# 旧 VictoriaMetrics Compose 栈(已清理)
**旧运行栈已停用,历史数据卷仍保留。数据是否已迁移、是否需要长期保留尚未确认。**
这里的 retired 只描述旧 Compose 运行栈,不代表旧数据已获准删除。
**旧配置与三个 Docker 数据卷已于 2026-09-16 删除,未备份、未迁移旧数据。**
维护者在了解保留数据情况后明确选择直接删除。新 Kubernetes 可观测性栈未做部署修改。
维护者最初的目标是以 Kubernetes 内的完整可观测性栈替代它,以便集成其他服务。
2026-09-16 经维护者授权进行了有限只读检查,没有启动、停止、迁移或删除任何服务或数据。
## 清理范围与结果
## 检查结果
删除前,旧 Compose 栈已经没有容器;再次确认三个旧卷没有任何容器引用后,
按完整卷名逐个删除,并检查卷列表确认它们均不存在:
- `docker ps -a` 按 Compose project `victoriametrics` 筛选,没有容器;
按 VictoriaMetrics、vmagent、vmalert、Grafana、Alertmanager 名称及镜像筛选也没有旧栈容器。
- 三个 Docker 卷仍存在,按卷筛选所有容器,没有发现引用它们的容器。
- Kubernetes `monitoring` 中 VMSingle/main 和 VMAgent/main 状态为 operational;
Grafana、指标、日志、追踪及相关采集组件的 Pod 处于 Running。
- 新栈的 Grafana、VMSingle、VLSingle、VTSingle PVC 均为 Bound。
这些资源状态不等于已经验证新旧数据一致或完成全部端到端采集验收。
| 已删除卷 | 删除前内容 |
|---|---|
| `victoriametrics_vmdata` | 约 131 MiB,包含历史指标数据与索引 |
| `victoriametrics_vmagentdata` | 空目录,占用约 4 KiB |
| `victoriametrics_grafanadata` | 约 45 MiB,包含旧 grafana.db 和插件等 |
| 旧 Docker 卷 | 磁盘占用(du -sh) | 保留内容 |
|---|---|---|
| `victoriametrics_vmdata` | 131 MiB | data、indexdb、metadata、cache 等;data/small 和 data/big 下有 `2026_02`、`2026_03` 目录 |
| `victoriametrics_vmagentdata` | 4 KiB | 本次查看目录为空 |
| `victoriametrics_grafanadata` | 45 MiB | `grafana.db`(1,536,000 字节)及 plugins、dashboards 等目录 |
源码仓库 `apps/victoriametrics/` 下的 13 个受管文件已删除,平台文档和告警规则注释
中的旧路径引用已修正。旧配置可以从 Git 历史找回;不能通过 Git 恢复已删除的数据卷内容。
本次未创建任何数据备份。
元数据统计确认 `data/` 下有 247 个文件,逻辑大小合计 118,467,976 字节;
`indexdb/` 下有 173 个文件,逻辑大小合计 11,864,570 字节。
基础设施清理已通过 [PR #73](https://git.ddupan.top/panxiao81/homelab-infra/pulls/73)
于 2026-09-16 16:05:33 UTC 合并到 main,合并提交为
[`9c64d31`](https://git.ddupan.top/panxiao81/homelab-infra/commit/9c64d31d3dea2ac2663170ca8125f03ac95cf0dd)。
PR 仅包含此次清理;源码工作区原有的其他修改未纳入。
本机卷路径为 `/var/lib/docker/volumes/<卷名>/_data`。
旧 `grafana.db` 文件修改时间为 2026-03-09 08:30:18 UTC。
目录名和文件修改时间仅是文件系统证据,不能据此断言样本的准确时间范围、完整性或可查询性。
## 清理后的检查
## 如何理解当前状态
- Docker 中三个指定卷均不存在,旧配置目录已不存在。
- 新栈 VMSingle/main、VMAgent/main 仍为 operational。
- Grafana、VMSingle、VLSingle、VTSingle 的四个 PVC 均为 Bound。
- `platform/observability/metrics` 的 Kustomize 渲染通过。
旧卷确有保留内容,不能按“只剩 Compose 配置”处理。
本机没有运行中的旧栈容器,本轮也没有可直接查询的旧实例;未为检查数据而启动旧实例。
没有读取 Grafana 数据库内容或凭据,也没有执行历史样本查询。
下一步若需要保留、恢复或迁移历史数据,应先与维护者确定目标,再安排独立工作。
在此之前保留三个卷,不运行 `docker compose down -v` 或将它们纳入未使用卷清理。
旧数据当前没有容器引用,不能因此视为可安全删除。
## 文档与代码归属
- 旧 Compose 配置:homelab-infra `apps/victoriametrics/compose.yaml`。
- 新可观测性栈:homelab-infra `platform/observability/README.md`。
- 本次只同步知识库,未改动源码中的历史配置或执行退役清理。
这些检查确认清理范围及新栈资源状态,不宣称新旧历史数据完成迁移。
现役监控的维护入口为 homelab-infra `platform/observability/README.md`。
+43
View File
@@ -0,0 +1,43 @@
---
title: vlmcsd 服务入口
lifecycle: unknown
evidence: configuration
last_reviewed: 2026-09-16
last_verified: null
---
# vlmcsd
homelab 中的 KMS 兼容服务,配置使用 `mikolatero/vlmcsd` 镜像。
维护者于 2026-09-16 表示没有需补充的动态事项;本页依据
`apps/vlmcsd/compose.yaml` 整理,未检查运行状态或客户端。
## 入口与客户端使用
Compose 将宿主 TCP `1688` 映射到容器 `1688`。实际宿主地址和客户端使用范围未在该文件中记录,
接入时由维护者提供;它是协议服务,不是网页,也没有仓库中已记录的 OIDC 登录步骤。
已有 Windows KMS 客户端需要指定服务器时,在管理员终端中将 `YOUR_KMS_HOST` 替换为已提供的地址:
```powershell
cscript.exe "$env:SystemRoot\System32\slmgr.vbs" /skms YOUR_KMS_HOST:1688
cscript.exe "$env:SystemRoot\System32\slmgr.vbs" /ato
cscript.exe "$env:SystemRoot\System32\slmgr.vbs" /dlv
```
第一步修改该客户端的 KMS 目标,第二步发起激活请求,第三步查看结果;
适用前提是客户端版本与其已有授权配置支持 KMS,不能将端口连通当成激活成功。
命令依据[镜像项目使用说明](https://github.com/mikolatero/docker-vlmcsd),本轮未执行。
已有客户端无需为了接入此服务先卸载产品密钥;本页不复制那类重置步骤。
## 故障与依赖
连接失败先核对宿主地址、TCP `1688` 与网络规则;服务可达但请求失败时,
结合客户端详细状态和服务日志区分协议、版本及客户端配置问题。
具体客户端清单、DNS 自动发现记录和宿主位置未从所读 Compose 得到,不能自行补成现状。
依赖为 Docker 与客户端到宿主的网络。所读 Compose 未声明持久卷;
这只描述此服务配置,不代表客户端状态可以随意清除。
维护配置入口为 homelab-infra `apps/vlmcsd/compose.yaml`。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#vlmcsd)。
+85
View File
@@ -0,0 +1,85 @@
---
title: zot 镜像与制品仓库使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
---
# zot 镜像与制品仓库
zot 保存容器镜像与 OCI 制品,底层数据存放于 [SeaweedFS](seaweedfs.md)。
客户端使用 Registry API,不需要直接访问 S3 bucket。
本页依据 homelab-infra 工作区 `apps/zot/README.md` 的 2026-09-16 记录整理。
源文档记录双入口已上线并验收、由 Flux 管理;本轮未查询现场或执行下面的示例。
## 两个入口
| 入口 | 用途 | 认证 |
|---|---|---|
| `zot.ad.ddupan.top` | 内网拉取镜像或制品 | 匿名只读 |
| `zot-push.ad.ddupan.top` | 鉴权访问及已授权发布 | SPIRE JWT-SVID,audience 为 `zot`;写权限按 SPIFFE ID 和 repository 分配 |
需要到 LAN 的路由与内网 DNS。两个入口对应相同制品数据,例如推送
`zot-push.ad.ddupan.top/team/image:tag` 后,可从
`zot.ad.ddupan.top/team/image:tag` 拉取,无需再复制一份镜像。
## 第一次拉取
安装 crane 后,在可写的工作目录执行源码文档提供的只读示例:
```bash
crane pull zot.ad.ddupan.top/verification/anonymous-spire:smoke image.tar --format oci
```
预期得到本地 `image.tar` OCI archive。该验证制品仅含测试内容,没有可执行入口,
用于验证拉取链路,不要把它当作能运行的业务镜像。
日常部署使用发布方提供的真实镜像路径和 tag/digest;匿名拉取不需要登录推送入口。
## 发布自己的镜像
发布前需要同时具备:
1. 执行环境能通过 Workload API 获取自己的 SPIFFE 身份。
2. workflow 获取 `aud=zot` 的短期 JWT-SVID。
3. zot 已为该 SPIFFE ID 授予目标 repository 所需的 `read/create/update` 权限。
根据所读源文档,当前持久配置没有常驻 publisher 或删除授权,曾用于验收的临时写权限
已经撤回。因此以下是获授权后的使用模板,不能仅登录成功就假定可以推送。
假定 workflow 已将 JWT-SVID 放入当前进程的 `ZOT_JWT`,准备好自己的 `image.tar`,
并将示例目标替换为已授权的 repository/tag,在 Bash 中执行:
```bash
(
set +x
set -euo pipefail
: "${ZOT_JWT:?workflow 必须先取得 aud=zot 的 JWT-SVID}"
export DOCKER_CONFIG="$(mktemp -d)"
trap 'rm -rf -- "$DOCKER_CONFIG"' EXIT
printf '%s' "$ZOT_JWT" | crane auth login zot-push.ad.ddupan.top \
--username zot --password-stdin
crane push image.tar zot-push.ad.ddupan.top/team/image:tag
)
unset ZOT_JWT
```
临时配置目录退出时删除。登录、token 获取和刷新由 workflow 负责,
[Dynamic Runner](gitea-dynamic-runner.md) 提供环境和身份能力,不代办这些业务流程。
这里的 token 交换不会延长原 SVID 的有效期。
## 常见问题与数据边界
- 拉取域名不能推送:它只提供匿名读取,发布应使用推送域名。
- 401:检查 issuer、audience、有效期,以及 workflow 是否实际取得了 JWT-SVID。
- 登录成功但推送被拒绝:检查具体 SPIFFE ID 的 repository policy;身份与写权限分开配置。
- S3 后端报错:检查 zot 到 SeaweedFS 的连接与受管凭据,不能用客户端的 JWT 代替后端 AK/SK。
zot 的持久数据在 SeaweedFS `zot` bucket 的 `registry/` 前缀;zot Pod 的临时目录不是备份。
恢复需要完整 bucket 数据、OpenBao 专用凭据与部署配置。源文档记录独立异机/离线备份尚未建立,
不能将同一 SeaweedFS 的副本视为独立灾备;重装 zot 不得删除该 bucket。
部署、授权变更、凭据轮换及验收细节以 homelab-infra `apps/zot/README.md` 为准。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#zot)。
+237
View File
@@ -0,0 +1,237 @@
---
title: 使用指南来源追溯
last_reviewed: 2026-09-16
---
# 使用指南来源追溯
这份索引帮助读者打开使用指南所依赖的源码,并区分可复现版本与工作区材料。
2026-09-16 对照的是 homelab-infra 本地已有 `origin/main` 对应的
[提交 `5ba4411`](https://git.ddupan.top/panxiao81/homelab-infra/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5)。
本轮没有 fetch、查询服务或修改原仓库;它不是“此刻远端最新版本”的保证。
只对明确列出的来源文件比较 Git blob 与工作区文件哈希,未复制秘密内容或访问运行凭据。
下表是本次文件来源核对,不追认旧指南编写时的内容完全一致,也不验证部署结果。
| 标记 | 如何使用链接 |
|---|---|
| 内容一致 | 固定版本与本次工作区文件一致,可用来复现该文件内容 |
| 工作区有差异 | 链接只供比较已提交基线,不能证明工作区新增内容已合并 |
| 该提交未收录 | 不编造远端文件链接,仍按指南注明的工作区路径读取 |
共核对 62 个不同文件:内容一致 44,工作区有差异 12,该提交未收录 6。
某文件本地显示 untracked,不代表它一定不存在于别的分支;以这里指定提交的树为比较对象。
查更新资料可从 [homelab-infra](https://git.ddupan.top/panxiao81/homelab-infra) 进入,但不要把旧固定链接当实时状态。
维护者说明、独立项目 README、SPIRE ticket 和历史 PR 仍以各页直接链接为准。
本索引只补 homelab-infra 中近期使用指南的主要来源,不替代每页证据范围。
## gitea
[返回使用指南](services/gitea.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/gitea/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/gitea/README.md) |
| `platform/gitea-runner/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/gitea-runner/README.md) |
## grafana
[返回使用指南](services/grafana.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `platform/observability/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/observability/README.md) |
| `platform/observability/grafana/values.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/observability/grafana/values.yaml) |
## zot
[返回使用指南](services/zot.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/zot/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/zot/README.md) |
## seaweedfs
[返回使用指南](services/seaweedfs.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/seaweedfs/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/seaweedfs/README.md) |
| `apps/zot/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/zot/README.md) |
## openbao
[返回使用指南](services/openbao.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `infrastructure/openbao/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/openbao/README.md) |
## netbox
[返回使用指南](services/netbox.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/netbox/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/netbox/README.md) |
| `apps/netbox/terraform/topology.yml` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/netbox/terraform/topology.yml) |
## shared-postgresql
[返回使用指南](services/shared-postgresql.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/shared-postgresql/migration.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/shared-postgresql/migration.md) |
| `apps/shared-postgresql/cloudnativepg-cluster.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/shared-postgresql/cloudnativepg-cluster.yaml) |
| `apps/shared-postgresql/shared-postgresql-service.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/shared-postgresql/shared-postgresql-service.yaml) |
## litellm-gateway
[返回使用指南](services/litellm-gateway.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/litellm-gateway/docker-compose.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/litellm-gateway/docker-compose.yml) |
| `apps/litellm-gateway/config.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/litellm-gateway/config.yaml) |
## tailscale
[返回使用指南](services/tailscale.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/tailscale/subnet-routes.sh` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/tailscale/subnet-routes.sh) |
## ps3netsrv
[返回使用指南](services/ps3netsrv.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/ps3netsrv/docker-compose.yml` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/ps3netsrv/docker-compose.yml) |
## vlmcsd
[返回使用指南](services/vlmcsd.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/vlmcsd/compose.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/vlmcsd/compose.yaml) |
## external-secrets
[返回使用指南](services/external-secrets.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `platform/external-secrets/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/external-secrets/README.md) |
| `platform/external-secrets/clustersecretstore.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/external-secrets/clustersecretstore.yaml) |
| `platform/external-secrets/externalsecrets.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/external-secrets/externalsecrets.yaml) |
| `platform/external-secrets/kustomization.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/external-secrets/kustomization.yaml) |
## openebs
[返回使用指南](services/openebs.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `platform/openebs/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/openebs/README.md) |
| `platform/openebs/storageclasses.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/openebs/storageclasses.yaml) |
## k3s-dns
[返回使用指南](services/k3s-dns.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `platform/k3s/Corefile.desired` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/k3s/Corefile.desired) |
| `platform/k3s/coredns-custom.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/k3s/coredns-custom.yaml) |
## marker
[返回使用指南](services/marker.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/marker/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/marker/README.md) |
| `apps/marker/Dockerfile` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/marker/Dockerfile) |
| `apps/marker/deployment.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/marker/deployment.yaml) |
| `apps/marker/service.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/marker/service.yaml) |
## openviking
[返回使用指南](services/openviking.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/openviking/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/openviking/README.md) |
| `apps/openviking/docker-compose.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/openviking/docker-compose.yml) |
## smtp-relay
[返回使用指南](services/smtp-relay.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `apps/smtp-relay/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/smtp-relay/README.md) |
| `apps/smtp-relay/service.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/smtp-relay/service.yaml) |
| `apps/smtp-relay/deployment.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/smtp-relay/deployment.yaml) |
## samba-ad
[返回使用指南](services/samba-ad.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `infrastructure/samba-ad/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/samba-ad/README.md) |
| `infrastructure/samba-ad/ansible/join-windows.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/samba-ad/ansible/join-windows.yml) |
| `infrastructure/samba-ad/ansible/join-member.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/samba-ad/ansible/join-member.yml) |
| `infrastructure/samba-ad/ansible/roles/samba_member/tasks/main.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/samba-ad/ansible/roles/samba_member/tasks/main.yml) |
## oci
[返回使用指南](services/oci.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `infrastructure/oci/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/oci/README.md) |
| `infrastructure/oci/ansible/README.md` | 该提交未收录 | — |
| `infrastructure/oci/terraform/providers.tf` | 该提交未收录 | — |
| `infrastructure/oci/terraform/versions.tf` | 该提交未收录 | — |
| `infrastructure/oci/terraform/compute.tf` | 该提交未收录 | — |
| `infrastructure/oci/terraform/amd.tf` | 该提交未收录 | — |
## proxmox
[返回使用指南](services/proxmox.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `infrastructure/proxmox/README.md` | 该提交未收录 | — |
| `infrastructure/proxmox/README-ha.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/proxmox/README-ha.md) |
| `infrastructure/proxmox/ansible/auth.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/proxmox/ansible/auth.yml) |
| `infrastructure/proxmox/ansible/site.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/proxmox/ansible/site.yml) |
| `infrastructure/proxmox/ansible/ha.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/proxmox/ansible/ha.yml) |
## publish-service
[返回使用指南](guides/publish-service.md)
| 源码路径 | 与工作区比较 | 提交链接 |
|---|---|---|
| `platform/cert-manager/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/cert-manager/README.md) |
| `platform/cert-manager/certificate-wildcard-ad.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/cert-manager/certificate-wildcard-ad.yaml) |
| `platform/envoy-gateway/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/envoy-gateway/README.md) |
| `platform/envoy-gateway/gateway.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/platform/envoy-gateway/gateway.yaml) |
| `infrastructure/dns/README.md` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/dns/README.md) |
| `infrastructure/dns/records.yml` | 工作区有差异 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/dns/records.yml) |
| `infrastructure/samba-ad/ansible/provision-dc.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/samba-ad/ansible/provision-dc.yml) |
| `infrastructure/samba-ad/ansible/roles/samba_ad_dc/tasks/dns_records.yml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/infrastructure/samba-ad/ansible/roles/samba_ad_dc/tasks/dns_records.yml) |
| `apps/netbox/securitypolicy.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/netbox/securitypolicy.yaml) |
| `apps/netbox/networkpolicy.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/netbox/networkpolicy.yaml) |
| `apps/authelia/referencegrant-extauth.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/authelia/referencegrant-extauth.yaml) |
| `apps/gitea/httproute.yaml` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/apps/gitea/httproute.yaml) |
| `clusters/homelab/README.md` | 内容一致 | [固定版本](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/5ba441164661bdff24700595e0e6cd7ddb33eec5/clusters/homelab/README.md) |
+69
View File
@@ -0,0 +1,69 @@
import sys
import tempfile
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
from check_docs import check, metadata_errors, split_frontmatter
class DocumentChecks(unittest.TestCase):
def run_check(self, documents):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
for name, text in documents.items():
file = root / name
file.parent.mkdir(parents=True, exist_ok=True)
file.write_text(text)
return check(root, list(documents))
def test_commonmark_links_and_code_examples(self):
errors = self.run_check({
"README.md": "[引用][page]\n\n[page]: guide.md#中文-标题\n\n"
"![附件](asset.svg)\n\n`[假链接](missing.md)`\n\n"
"```md\n[示例](missing.md)\n```\n",
"guide.md": "# 中文 标题\n",
"asset.svg": "<svg/>",
})
self.assertEqual([], errors)
def test_broken_reference_and_heading(self):
errors = self.run_check({"README.md": "[x][r]\n\n[r]: missing.md\n\n[x](#absent)\n"})
self.assertTrue(any("目标不存在" in e for e in errors))
self.assertTrue(any("标题锚点不存在" in e for e in errors))
def test_duplicate_headings_and_html_anchor(self):
self.assertEqual([], self.run_check({"README.md":
'# Same\n# Same\n<a id="custom"></a>\n[x](#same-1) [y](#custom)\n'}))
def test_escaped_paths_tables_and_external_links(self):
self.assertEqual([], self.run_check({
"README.md": '| a | b |\n|---|---|\n| [x](a%20b.md) | [web](https://example.invalid) |\n',
"a b.md": '# Target\n',
}))
def test_outside_repository_rejected(self):
errors = self.run_check({"README.md": "[x](../outside.md)\n"})
self.assertTrue(any("越出仓库" in e for e in errors))
def test_frontmatter_dates_and_evidence(self):
meta, _ = split_frontmatter('---\ntitle: Example\nlifecycle: active\nevidence: live-verified\n'
'last_reviewed: 2026-09-16\nlast_verified: null\n---\n# Title\n')
self.assertTrue(any("live-verified" in e for e in metadata_errors(meta, required=True)))
meta['last_verified'] = '2026-09-17'
self.assertTrue(any("不能晚于" in e for e in metadata_errors(meta, required=True)))
meta['last_verified'] = '2026-02-30'
self.assertTrue(any("YYYY-MM-DD" in e for e in metadata_errors(meta, required=True)))
def test_duplicate_yaml_keys_rejected(self):
errors = self.run_check({"README.md": '---\ntitle: A\ntitle: B\n---\n'})
self.assertTrue(errors)
def test_new_service_requires_metadata_and_index(self):
errors = self.run_check({"services/new.md": "# New\n", "services/index.md": "# Services\n"})
self.assertTrue(any("缺少 frontmatter" in e for e in errors))
self.assertTrue(any("未被 services/index.md" in e for e in errors))
if __name__ == '__main__':
unittest.main()
+23 -21
View File
@@ -1,15 +1,19 @@
# 待核实与文档缺口
# 首轮状态对齐记录(已完成)
审阅日期:2026-09-16;初版依据工作区,后续按维护者说明和指定资料对齐。
旧 VictoriaMetrics Compose 已获授权做有限现场检查,其余项目未因本清单自动查询现场。
下面的检查方法只是候选步骤,执行前先问维护者当前进度及查询范围。
以下路径相对于 homelab-infra。优先修复影响恢复、认证、DNS 和首次使用的问题。
**2026-09-16,维护者确认本轮待核实事项已结束;当前没有开放的状态核实任务。**
结论来自维护者说明、指定的项目文档与 ticket,以及旧监控栈的授权检查和清理。
本轮完成不等于所有服务都经过现场检查,也不等于各开发项目全部完工。
下文保留对齐结果;后续写作与源码文档同步移至[文档完善清单](documentation-backlog.md)。
动态实施进度继续由各项目文档和 ticket 维护,不另开一轮全量状态盘点。
## 已对齐的动态工作
NATS 已作为集群共享服务部署,当前唯一消费者为 Dynamic Runner,见 [NATS](services/nats.md)。
维护者明确 Dynamic Runner 正在积极开发,其启用范围、durable 名称和实现进度以
[项目文档](https://git.ddupan.top/panxiao81/gitea-dynamic-runner)为准。
维护者补充动态 Pod 已上线测试、系统总并发 4,VM 正在工作、系统总并发 1;
纯 self-hosted runner 准备退役。使用入口见 [Gitea / Actions](services/gitea.md)。
不再将旧示例的 durable 名称差异或启用范围列为独立待核实项。
NATS 原生通过 Account 隔离租户,跨 Account 的名称不构成全局冲突;
runner 的队列协调约定仅在其所属 Account 和 stream 范围内讨论。
@@ -28,25 +32,24 @@ SPIFFE/SPIRE 按维护者指定,以 [#34](https://git.ddupan.top/panxiao81/hom
原工作区集群总览的“首次上线待验证”不作为当前阶段判断。
详见 [SPIFFE/SPIRE 使用入口与阶段状态](services/spire.md);源码工作区本轮未修改。
## 待向维护者确认的记录差异
## 旧监控栈清理结果
初轮列出的状态差异已按维护者说明、指定资料或授权检查完成分类;不再保留自动现场核查任务。
[旧 VictoriaMetrics Compose](services/victoriametrics-legacy.md) 已于 2026-09-16 只读检查:
旧栈无容器,三个旧卷仍存在且无容器引用;VM 卷约 131 MiB、Grafana 卷约 45 MiB。
新 Kubernetes 栈的资源状态正常,但没有验证数据迁移或新旧数据一致性。
旧数据暂时保留,是否恢复、迁移或删除需先由维护者决定。
[旧 VictoriaMetrics Compose](services/victoriametrics-legacy.md) 已于 2026-09-16 完成清理:
维护者明确要求直接删除旧配置和全部数据卷,三个无引用 Docker 卷及旧配置均已删除,
未备份或迁移数据。新 Kubernetes 栈的资源状态检查和指标清单渲染通过。
基础设施清理已通过 [PR #73](https://git.ddupan.top/panxiao81/homelab-infra/pulls/73)
合并 main(`9c64d31`);配置交付和数据处置均已完成。
## 优先补充的使用说明
## 已确认的归属与范围
1. Gitea / Actions:登录、创建仓库、选择 runner,以及可信任务限制。
2. Grafana:登录、找到内存与 Swap 看板、查询指标和日志的一个完整例子。
3. zot / SeaweedFS:拉取、发布授权、S3 客户端接入,以及数据备份边界。
4. OpenBao:日常登录、按权限取用秘密、申请权限;与灾难恢复分开说明。
5. NetBox:查看拓扑与 IPAM 的路径,强调目前是评估镜像,改动入口在 Git。
6. codex-proxy、LiteLLM gateway、shared PostgreSQL、Tailscale、ps3netsrv、vlmcsd、k3s:补用途和当前状态;这些目录缺少根 README。
- 维护者于 2026-09-16 指定 Samba AD、OCI、Proxmox 优先 IaC、以代码为准;
后续可直接核对仓库配置,不重复询问同一资料范围。配置声明与现场验证仍分开记录。
## 盘点盲区
- 维护者于 2026-09-16 说明 codex-proxy“应该是退役的”,已从现役应用列表移至归档范围;
未查询运行环境,也没有删除源码或数据。LiteLLM、Tailscale、ps3netsrv、vlmcsd 无需补充动态事项,
已基于仓库配置补使用指南;这不等于新增的现场验收。
- e5renew 和 research-auto 已由维护者明确为 GitHub 上的[外部消费者](services/external-consumers.md),
不属于 homelab 基础设施,不再列为盘点盲区或缺失组件。
@@ -57,7 +60,6 @@ SPIFFE/SPIRE 按维护者指定,以 [#34](https://git.ddupan.top/panxiao81/hom
operator 仍按项目记录标为 API 骨架阶段;本轮未查询运行环境。
- workload-sts 已按维护者提供的信息查阅:仓库已归档,停止开发、不部署 PoC,
作为[早期设计与替代决策的历史来源](architecture/workload-sts-history.md)保留,不列为待接入服务。
- 新增 NATS、zot、microVM 等来源含未提交文件;合并后补可访问的 commit/PR 链接。
- Backstage 仍作为计划入口记录;本轮没有证明已有部署。
- Backstage 为计划中的统一入口,不作为已部署服务记录。
完成核实后,将结果写回对应权威文档,并更新服务总览的证据等级和验证日期。
后续出现新的状态问题时,先向维护者对齐,再按授权范围更新对应服务文档。