HomeButler:把服务器报告从 7 行噪音压到 2 行变更
Show HN: Homebutler – my server report printed 7 lines for 2 changes, now 2
HomeButler 是一个单 Go 二进制工具,会记住服务器上次快照并只报告真正发生的变化,0.26.0 起用 replaced 等八类变更词替代单纯计数对比,避免容器同名重建被误判为"无变化"。它无需常驻 daemon 或数据库,可通过 CLI、JSON、Web 面板或 MCP 供 AI 智能体使用,支持 brew 安装与容器部署,经 SSH 访问被监控机器。
只提值得说的变化。
一个单独的 Go 二进制文件,记住你的服务器上次长什么样,
然后告诉你——或者一个 agent——什么变了。
brew install Higangssh/homebutler/homebutler # or: curl -fsSL https://raw.githubusercontent.com/Higangssh/homebutler/main/install.sh | sh homebutler report # first run saves a baseline; the second tells you what moved
或者作为容器,通过 SSH 连接你的机器——docs/docker.md:
docker run -v ~/.config/homebutler:/config -v ~/.ssh:/root/.ssh:ro ghcr.io/higangssh/homebutler
分区规则、标签和严重级别在终端里用颜色区分。当输出被管道传输、重定向或从 cron 运行时,颜色会自动去掉。
这就是全部理念。大多数 homelab 工具给你展示当下的图表,然后把 “这重要吗?”留给你自己判断。HomeButler 记住你的服务器上次长什么样,判断什么值得说,然后说出来——前后都是六个容器,并不等于“没有变化”,当其中一个是不同的容器时。
读取一条变化
每一行有三列:什么类型的变化、它发生在什么上,以及
到底发生了什么。类型是八个词之一,而且在
--json 里是同一个词,所以 agent 可以直接据此分支,而无需阅读文字:
| 类型 | 含义 | 你会在什么之后看到它 |
|---|---|---|
gone |
它上次在,现在不在了 | docker rm、服务停止、端口关闭 |
new |
它上次不在,现在在了 | 启动任何东西 |
replaced |
名字相同,底下的东西不同 | docker compose up -d——容器被重建,所以名字和数量都没变 |
image |
同一个容器,不同的镜像 | 拉取新标签 |
state |
同一个容器,在它停止的地方运行,或者反过来 | 崩溃,或者把某个东西重新启动 |
port |
同一个端口,由不同的进程应答 | 一个服务接管了另一个服务的端口 |
disk |
挂载点移动超过半个 GB | 任何会写入的东西 |
skipped |
无法进行比较 | 拍摄任一快照时 Docker 都处于停止状态 |
replaced 是其余这一切存在的理由。一个在相同名字下重建的容器会让所有计数保持一致,这就是为什么一份比较计数的报告——
就像这个在 0.26.0 之前所做的那样——会回答“没有重大变化”,而你正在运行的东西已经在底下被换掉了。
skipped 是第二个:homebutler 说它无法比较,而不是报告
什么都没变。一个它无法担保的“一切正常”比没有答案更糟。
标题指明了正在与哪个快照进行比较,所以“什么变了”在它覆盖的时间窗口上从不含糊。
HomeButler 帮你回答每个 homelab 最终都会产生的那些无聊但痛苦的问题:
- 我的服务器现在运行着什么?
- 哪个容器占用了这个端口?
- 为什么这个服务在凌晨 3 点重启了?
- 我的备份真的可以恢复吗?
- 我能安装这个自托管应用,而不用再手写一个 compose 文件吗?
- 我能让 AI 助手检查我的服务器,而不用给它一个完整的 SSH shell 吗?
不需要守护进程,不需要数据库。从终端、cron、你想要时才启动的 web 仪表盘,或者 AI agent 运行它。
设计目标很简单:给人类和 agent 一个狭窄、结构化的服务器接口。HomeButler 返回可读的摘要和 JSON,而不是让你去信任一个黑盒 shell 会话。
半分钟看完整个东西 · 全尺寸观看
快速开始
# One-line install (auto-detects OS/arch) curl -fsSL https://raw.githubusercontent.com/Higangssh/homebutler/main/install.sh | sh # Or via Homebrew brew install Higangssh/homebutler/homebutler # Or as a container — the hub that reaches your machines over SSH docker run -d -p 8080:8080 -v ~/.config/homebutler:/config -v ~/.ssh:/root/.ssh:ro \ ghcr.io/higangssh/homebutler serve --host 0.0.0.0 --token "$(openssl rand -hex 16)" # Interactive setup — add your servers in seconds homebutler init
立即使用:
homebutler status # CPU, memory, disk, uptime homebutler docker list # running containers homebutler inventory scan # containers + ports + topology homebutler report # butler-style health report + change summary homebutler install uptime-kuma # deploy a self-hosted app homebutler backup drill uptime-kuma # verify a backup actually restores homebutler watch tui # terminal dashboard homebutler serve # web dashboard at http://localhost:8080
机器可读输出随处可用:
homebutler status --json homebutler inventory scan --json homebutler report --json
它能做什么
- 安装应用——用一条命令部署 Uptime Kuma、Jellyfin、Pi-hole、Gitea、Portainer 等
- 映射你的服务器 — 查看容器、暴露端口、系统端口和服务拓扑
- 运行 doctor 检查 — 诊断资源压力、已停止的容器、公开端口、备份卫生、通知、报告基线就绪情况,以及已配置的 Proxmox 端点可达性
- 捕获崩溃 — 在 Docker、systemd 或 PM2 重启前后保存日志,并检测反复重启循环
- 验证备份 — 在信任备份之前,先在隔离容器中启动它们
- 查看 Proxmox 集群 — 节点、QEMU 和 LXC 客户机、存储、任务状态,以及诚实的仪表盘新鲜度,并带有明确指定目标的电源操作
- 随处可用 — CLI、JSON、Web 仪表盘,或面向 AI 代理的 MCP,而无需给它们 SSH
为什么选择 homebutler?
自托管并不难,因为单个 docker compose up 很难。难的是维护永无止境:端口冲突、容器静默重启、备份看起来没问题直到恢复那天,而且每台服务器都会变成略有不同的雪花。
HomeButler 是面向这片混乱中间地带的小型运维工具包。
与你已经在运行的工具并存
保留 Uptime Kuma 用于它是否在线,Beszel 或 Netdata 用于图表,Dozzle 用于日志。 HomeButler 回答它们都没有问的问题:与上次相比有什么不同,这重要吗?
-
它所监视的机器上无需代理。该二进制文件通过
homebutler deploy一次性放置在那里,并且仅在需要时通过 SSH 运行——没有守护进程,没有开放端口,两次运行之间没有任何监听。 -
判断是写好的规则,而不是模型。什么值得占一行写在 docs/report.md 中,相同的输入会给出相同的报告——无需 AI,无需账户,无需付费层级。
-
它会检查备份能否恢复。从未恢复过的备份只是一个文件夹。
backup drill将归档作为应用的第二个副本启动,使用自己的网络和端口,并要求它通过 HTTP 健康检查,然后才认为归档良好——之后移除它创建的所有内容。演练失败会以非零状态退出,因此backup drill --all应与backup放在同一个 cron 条目中。docs/backup.md 说明了它会做什么以及它不能证明什么。🔐 Integrity: ✅ tar valid (8 files) 🚀 Boot: ✅ container started in 0s 🌐 Health: ✅ HTTP 200 on port 60405 ✅ DRILL PASSED
核心工作流
🧾 Butler 报告
homebutler report homebutler report --keep 7 # retain only the latest 7 snapshots homebutler report --no-save # preview without writing a snapshot
report 为你提供一份简洁的管家式家庭实验室摘要:当前健康状况、警告、自上次快照以来的显著变化,以及建议的后续命令。首次运行时,HomeButler 会在 ~/.homebutler/reports/snapshots/ 下创建基线;后续运行会与最新快照进行比较。旧快照会自动修剪(默认 --keep 30),因此报告不会无限增长。
🩺 Doctor 检查
homebutler doctor homebutler doctor --strict # non-zero exit if warnings/failures are found homebutler doctor --json # automation / MCP friendly
doctor 是一种只读预检,用于发现家庭实验室用户通常发现得太晚的问题:磁盘或内存使用率过高、已停止的容器、公开绑定端口、过期或缺失的备份、缺失的通知、report 是否有用于变更检测的基线,以及每个已配置的 Proxmox 端点是否能用其令牌访问。每个发现都会指明要运行的下一个命令,因此 --strict 使其可用于 cron 或 CI——包括无法访问或正在重启的 Proxmox 主机。
每个发现都带有一个 category,而 --json 带有相同的词,因此
调用方无需阅读标题即可据此过滤:
| 类别 | 关于什么 |
|---|---|
system |
CPU、内存、磁盘 |
docker |
已停止或不健康的容器 |
exposure |
在所有接口上监听的端口 |
backup |
备份缺失、过期、从未演练,或增长而没有保留限制 |
report |
是否有可供比较的基线 |
watch |
列出了目标但没有任何轮询 |
notifications |
已配置的通道,或从未测试过 |
proxmox |
一个用其持有的令牌无法到达的端点 |
config |
配置文件本身——权限、homebutler 不知道的密钥位置 |
incomplete |
某个采集器没有响应,因此此诊断不完整 |
overall |
没有具体问题:一切正常 |
incomplete 才是值得处理的那个。它意味着你正在阅读的答案缺少一个部分,这与该部分正常是不同的。
🗂 配置验证
homebutler config validate
homebutler config validate --strict # exit non-zero on warnings too
homebutler config validate --jsonconfig validate 在不启动任何东西的情况下读取你的配置,并告诉你使用了哪个文件、四条解析规则中的哪一条选中了它,以及 homebutler 对每个部分的实际理解。它之所以存在,是因为配置出错的两种方式都是静默的:homebutler 无法识别的键会被无声丢弃,而不存在的 --config 路径会回退到内置默认值,而不是报错。
Sections
✓ servers 2 servers (homelab, nas)
· notify not set
✓ alerts cpu 95% · memory 85% · disk 90%
Findings
⚠️ Line 5: field notifiy not found in the homebutler config
→ Did you mean "notify"? Unrecognised keys are ignored silently.
📦 一键应用安装
$ homebutler install list
📦 Available apps (15):
uptime-kuma A self-hosted monitoring tool
vaultwarden Lightweight Bitwarden-compatible password manager
jellyfin Free software media system for streaming movies, TV, and music
pi-hole Network-wide ad blocking via DNS filtering
…
homebutler install uptime-kuma— 数秒内部署自托管应用。预检查 Docker、端口和重复项。自动生成docker-compose.yml。查看所有可用应用 →
🗺️ 清单与拓扑
homebutler inventory scan
homebutler inventory show --filter exposed
homebutler inventory export --format mermaid
homebutler --json inventory scaninventory scan 为你快速绘制服务器上正在运行的内容:系统健康、Docker 容器、应用端口和系统端口。Docker 发布的端口会连接回拥有它们的容器,因此 Colima/Lima 等本地转发细节仍然清晰可懂。
🏠 Home Network
Server homelab (192.168.1.10)
Summary ✅ 1 running · ⚪ 1 stopped · 🌍 2 public ports · 🔒 4 local ports
📦 Containers (2)
├─ ⚪ vaultwarden · not started
│ └─ image vaultwarden/server:latest
└─ ✅ api-server · running
├─ image my-api:latest
└─ exposes :8080 → 8080/tcp
🌐 App Ports (1)
└─ 🌍 :8080/tcp · api-server
要在不阅读整棵树的情况下回答“从我的机器/网络外部可以访问什么?”,请将扫描过滤为仅暴露端口:
homebutler inventory scan --filter exposed
🏠 Home Network
Server homelab
🌐 Exposed Ports
├─ :8080/tcp · api-server
└─ :8443/tcp · dashboard
仅显示在所有接口上监听的端口(0.0.0.0、::、*)。任何绑定到特定地址的内容都会被隐藏,包括回环和局域网地址。不支持的过滤值会返回错误,将 --filter 与 --json 组合也会返回错误;默认的 inventory scan 输出保持不变。
当你需要为 GitHub、Obsidian、文档或 AI 助手制作图表时,请使用 Mermaid 导出:
graph TD home["🏠 Home Network"] --> homelab["🖥 homelab<br/>192.168.1.10"] homelab --> c1["📦 api-server<br/>running"] homelab --> p1["🌍 :8080/tcp<br/>api-server"] c1 -. exposes .-> p1
加载中
演示
🌐 Web 仪表盘
homebutler serve— 通过go:embed嵌入单一二进制文件中的 Web 仪表盘。可从任何浏览器查看服务器、Docker 容器、开放端口、告警和 Wake-on-LAN。使用--token时它还会编辑配置:阈值、通知通道、服务器、Proxmox 端点和唤醒设备。
报告标签页,你实际阅读它的地方
有人在收到通知后打开的屏幕。首先显示需要注意的内容,然后是每个变化所携带的温和说明,接着是正在比较的快照及其时间。无法进行的比较会如实说明,而不是读起来像一切正常。
加载它不会保存任何内容——每次打开都拍摄快照的页面会修剪掉你想用来比较的基线。保存快照是一个按钮。
✨ Web 仪表盘亮点
- 服务器概览 — 通过颜色编码状态(绿色 = 在线,红色 = 离线)一目了然地查看所有服务器
- 系统指标 — CPU、内存、磁盘使用率,带进度条和颜色阈值
- Docker 容器 — 运行/停止状态,带友好标签(“运行中 · 4天”,“已停止 · 6小时前”)
- 顶级进程 — 按 CPU/内存排序的顶级进程,带僵尸进程检测
- 资源警告 — 仪表盘中的可视化 CPU、内存和磁盘阈值
- 网络端口 — 开放端口,带进程名称和绑定地址
- Wake-on-LAN — 为已配置设备提供一键唤醒按钮
- 服务器切换 — 用于在本地和远程服务器之间切换的下拉菜单
- 零依赖 — 无需 Node.js 运行时。前端在构建时被编译进 Go 二进制文件
homebutler serve # Start on port 8080 homebutler serve --port 3000 # Custom port homebutler serve --demo # Demo mode with realistic sample data homebutler serve install # Let the host keep it running
🔄 进程重启监控
你的容器在凌晨 3 点崩溃了——但为什么? homebutler watch 在发生的那一刻就捕捉到它,保存濒死日志,找出原因,并告诉你它是否在反复发生。
支持的后端: Docker(实时事件流)· systemd(轮询)· PM2(轮询)
步骤 1:添加要监控的目标
homebutler watch add nginx # Interactive: choose Docker / systemd / PM2 homebutler watch add --kind docker nginx # or specify directly homebutler watch add --kind systemd nginx.service homebutler watch add --kind pm2 my-api homebutler watch list # See what you're watching
步骤 2:开始监控
homebutler watch start # Foreground, Ctrl+C to stop homebutler watch start --interval 10s # Custom poll interval (default 30s)
homebutler watch install # register it with systemd or launchd homebutler watch installed # is it registered? homebutler watch uninstall
watch install 将循环交给监督主机的任何程序——Linux 上的 systemd 用户单元,macOS 上的 launchd 代理——这样监控就能在注销和重启后继续存活。两者都是用户级别的,且都不是偏好选择:在 Linux 上,监控列表位于你的主目录中,因此 root 单元会找到一个空列表;在 macOS 上,Docker Desktop 只在已登录会话中运行,因此 LaunchDaemon 会轮询一个不存在的守护进程。在 Linux 上,除非启用了 lingering,否则用户单元会在注销时停止;watch install 会检查,如果未启用,就告诉你运行 loginctl enable-linger $USER(仅当你的系统拒绝时才使用 sudo)。
watch start 是监控进程。它监视监控列表中的容器和服务是否重启,根据你的阈值检查 CPU、内存和磁盘,并运行你配置的任何修复规则——一个进程,一套通知提供程序。alerts --watch 仍然存在,并独自完成阈值那一半工作。
你配置中 proxmox: 下的每个端点也会被轮询:无法访问或被 ACL 过滤的端点,以及该端点的 guests: 下列出的任何客户机,会在问题开始时报告一次事件,在问题清除时报告一次恢复事件。未列在那里的客户机仅作观察——watch start 从不对其发出警报,无论它是否被有意停止。有关 guests: 字段,请参见Proxmox 设置 →。
当检测到崩溃时,你会看到:
[03:14:22] INCIDENT: nginx (incident nginx-20260410-031422.581-7a2124)
Crash: OOM — process killed by SIGKILL (oom, confidence: high)
⚠ FLAPPING: acute (3 restarts in short window)
步骤 3:调查
homebutler watch history # List all incidents homebutler watch show <incident-id> # Full details
watch show 输出包括:
- 死亡前日志 — 进程在死亡前打印的内容
- 重启后日志 — 重启后发生的情况
- 崩溃分析 — 类别(oom / panic / segfault / timeout / dependency / error)、原因、置信度、匹配的日志模式
- 抖动状态 — 如果进程陷入崩溃循环
崩溃分析
每个事件都会使用退出代码和日志模式自动分析:
| 信号 | 退出代码 | 含义 |
|---|---|---|
| SIGKILL | 137 | OOM Killer 或强制终止 |
| SIGSEGV | 139 | 段错误(内存损坏) |
| SIGTERM | 143 | 优雅关闭请求 |
| — | 1 | 应用程序错误 |
| — | 0 | 正常退出(可能是有意重启) |
像 panic:、Out of memory、Connection refused、FATAL 和 timeout 这样的日志模式会被自动匹配,以帮助识别根本原因。
抖动检测
检测进程何时陷入重启循环(例如,崩溃 → 重启 → 再次崩溃):
- 急性 — 10 分钟内重启 3 次以上(当前有东西坏了)
- 慢性 — 24 小时内重启 5 次以上(缓慢的反复出现的问题)
抖动事件在历史记录中标记为 [FLAPPING],并在 watch show 中高亮显示。
通知(可选,默认关闭)
通知默认禁用,这对于所有内容都在本地运行的气隙或封闭网络很有用。
~/.config/homebutler/config.yaml 中的一个最小示例:
notify: telegram: bot_token: "your-bot-token" chat_id: "your-chat-id" watch: enabled: true notify_on: flapping cooldown: 5m flapping: short_window: 10m short_threshold: 3 long_window: 24h long_threshold: 5 retention: max_incidents: 200 alerts: cpu: 90 memory: 85 disk: 90 rules: - name: cpu-spike metric: cpu threshold: 90 action: notify - name: elsa-monitor-down metric: container kind: systemd # docker (default) | systemd | pm2 watch: [lh-elsa-monitor.service] action: restart
重启非容器的东西
action: restart 会重启 Docker 容器,除非规则另有说明。kind: systemd 或 kind: pm2 让它改为指向某个服务或 PM2 应用。
类型写在规则上,而不是从监控列表中查找,因此重启主机服务是你在配置中要求的事情。这也意味着在 kind 存在之前编写的每条规则都保持其原本的含义。
使用前有两件事值得了解:
systemctl restart 需要 root 权限或一条 polkit 规则。 以非特权方式运行 homebutler 时,systemd 重启会被拒绝,报告为失败,并且警告会在 alerts --watch 启动时出现,而不是在规则首次触发时。
处于抖动状态的目标不会被重启。 重启一个已经处于重启循环中的东西会助长这个循环,而且大多数 systemd 单元都带有 Restart=always,所以 homebutler 重启它们会与 systemd 自身的退避机制相冲突。阈值就是上面的 watch.flapping 阈值,跳过会被报告,而不会计为成功或失败。这也适用于 Docker 目标。
旧版 ~/.homebutler/watch/config.json 仍会作为监视特定设置的兜底被读取,旧版 alerts.yaml 通知/webhook 提供程序设置也仍被接受,以兼容较旧的配置。
-
watch.enabled: true— 允许监视通知 -
watch.notify_on: flapping— 仅在检测到重复重启循环时通知 -
watch.notify_on: incident— 每次事件都通知 -
watch.notify_on: all— 事件和抖动都通知 -
watch.notify_on: off— 禁用监视通知而不移除提供程序配置 -
watch.cooldown: 5m— 在冷却窗口内抑制同一事件指纹的重复通知 -
watch.flapping— 用于重启循环检测的可选高级调优 -
watch.retention.max_incidents: 200— 磁盘上保留多少条事件,最新的在前。目录增长最快的时刻恰恰是服务在循环中重启的时候。设为-1可保留全部。每条事件每侧最多保留 100 行捕获的日志,且最多 64 KB。仅靠行数并不能限制文件大小:单行上的一个堆栈跟踪或 JSON 文档可以任意长,而被 OOM 杀掉的容器恰恰最可能写出这样的行。放不下的日志会保留其末尾——进程最后说的话才能解释它为什么停止——并说明丢弃了多少。
这些设置也可以写在 watch.notify: 块下,这是规范形式:
watch: notify: enabled: true notify_on: flapping cooldown: 5m flapping: short_window: 10m
两种拼写都会被读取,所以两种布局都可用。如果文件中同时包含两者,notify: 块胜出,并且 homebutler config validate 会说明这一点。
管理目标
homebutler watch remove nginx # Stop watching homebutler watch check # One-shot check (no continuous monitoring)
🧊 Proxmox VE
homebutler proxmox status homebutler proxmox guests --status running homebutler proxmox guest shutdown --node pve1 --type lxc --vmid 105 --confirm homebutler proxmox task UPID:pve1:... --node pve1
Proxmox 端点是一种独立的目标类型,在 proxmox: 下使用 API 令牌而非 SSH 进行配置,因此它不会加入 --server 或 --all 的扇出。TLS 验证保持开启:信任来自固定的 SHA-256 指纹,然后是 CA 文件,最后才是显式的 insecure 回退。
读取是普通的。电源操作则不是:每一个操作都需要显式指定端点、节点、客户机类型和 VMID,并且在未提供 --confirm 时拒绝运行,该检查在任何凭据被读取之前进行。它们还需要在端点上配置自己的 action_token_id(加上 action_token 或 action_token_file)——仅靠读取令牌无法启动、重启或关闭客户机;创建第二个令牌请参见 Proxmox 设置 →。shutdown 请求客户机干净地关闭——它不是 Proxmox 的硬 stop,后者会切断电源并可能留下文件系统。操作成功报告的是它提交的任务,而不是客户机已完成;proxmox task 会单独回答这一点。
proxmox script 打印固定到某个提交的 Community Script 的安装命令,并附带警告:该脚本未经 homebutler 审查且以 root 运行。它从不获取或运行该脚本——为什么那行代码在那里,请参见 #62。
🖥️ TUI 仪表板
homebutler watch tui— 一个由 Bubble Tea 驱动的基于终端的仪表板。实时监控所有已配置的服务器,带有颜色编码的资源条和 Docker 容器状态。无需浏览器。
🧠 AI 驱动的管理(MCP)
想要自动化时,请使用自然语言。 MCP 客户端可以调用 homebutler 工具来检查服务器状态、列出 Docker 容器、检查端口或运行运维工作流。查看截图与设置 →
应用安装
用一条命令部署自托管应用。每个应用都通过 docker compose 运行,并带有自动预检查、健康验证和清晰的生命周期管理。
# List available apps homebutler install list # Install (default port) homebutler install uptime-kuma # Install with custom port homebutler install uptime-kuma --port 8080 # Install jellyfin with media directory homebutler install jellyfin --media /mnt/movies # Check status homebutler install status uptime-kuma # Stop (data preserved) homebutler install uninstall uptime-kuma # Stop + delete everything homebutler install purge uptime-kuma
工作原理
~/.homebutler/apps/
└── uptime-kuma/
├── docker-compose.yml ← auto-generated, editable
└── data/ ← persistent data (bind mount)
- 预检查 — 验证 docker 已安装/正在运行、端口可用、没有重复容器
- 基于 Compose — 每个应用都有自己的
docker-compose.yml,你可以查看和自定义 - 数据安全 —
uninstall会停止容器但保留你的数据;purge会删除所有内容,包括应用使用的 Docker 卷,并列出它们的名称。目前有一个例外:filebrowser 的账户和设置在uninstall并重新安装后不会保留(见表格) - 跨平台 — 自动检测 docker socket(默认、colima、podman)
可用应用
| 应用 | 默认端口 | 描述 | 备注 |
|---|---|---|---|
uptime-kuma |
3001 | 自托管监控工具 | |
plex |
32400 | Plex Media Server | --media /path 用于挂载媒体目录 |
vaultwarden |
8080 | 兼容 Bitwarden 的密码管理器 | |
filebrowser |
8081 | 基于 Web 的文件管理器 | ⚠️ uninstall 会保留 /srv 下的文件,但不会保留其账户和设置:重新安装会启动新的数据库(#327) |
it-tools |
8082 | 开发者实用工具(JSON、Base64、Hash 等) | |
gitea |
3002 | 轻量级自托管 Git 服务 | |
jellyfin |
8096 | 媒体系统(电影、电视、音乐) | --media /path 用于挂载媒体目录 |
homepage |
3010 | 现代 homelab 仪表盘 | |
stirling-pdf |
8083 | 一体化 PDF 工具(合并、拆分、转换、OCR) | |
speedtest-tracker |
8084 | 带历史图表的互联网速度测试 | |
mealie |
9925 | 食谱管理器和膳食计划器 | |
pi-hole |
8088 | DNS 广告拦截 | ⚠️ 使用 53 端口(DNS)、NET_ADMIN 权限 |
adguard-home |
3000 | DNS 广告拦截器和隐私保护 | ⚠️ 使用 53 端口(DNS) |
portainer |
9443 | Docker 管理 GUI | ⚠️ 挂载 Docker socket(HTTPS) |
nginx-proxy-manager |
81 | 带 SSL 和 Web UI 的反向代理 | ⚠️ 使用 80/443 端口 |
应用特定选项
# Jellyfin: mount your media library homebutler install jellyfin --media /mnt/movies # Pi-hole / AdGuard: DNS ad blocking (port 53 required) homebutler install pi-hole # ⚠️ If port 53 is in use (Linux): sudo systemctl disable --now systemd-resolved # Portainer: Docker GUI (mounts docker socket) homebutler install portainer # Access via HTTPS: https://localhost:9443 # Nginx Proxy Manager: reverse proxy homebutler install nginx-proxy-manager # Default login: admin@example.com / changeme (change immediately!) # Any app: custom port homebutler install <app> --port 9999
安全检查
- 端口冲突检测 — 安装前检查端口是否已被占用
- DNS 互斥 — 如果 pi-hole 和 adguard-home 都已安装则发出警告
- Docker socket 警告 — 当应用需要 Docker socket 访问权限(portainer)时发出提醒
- 操作系统特定指导 — Linux 提供 systemd-resolved 修复,macOS 提供 lsof 命令
- 安装后提示 — DNS 设置、HTTPS 访问、默认凭据警告
用法
homebutler <command> [flags]
Commands:
status System status (CPU, memory, disk, uptime)
doctor Diagnose health, exposure, backups, and readiness
config validate Check the config file and report what is ignored
docker list List running containers
install <app> Install a self-hosted app (docker compose)
alerts Show current alert status
watch tui TUI dashboard (monitors all configured servers)
watch add/list/remove Manage watched containers
watch check/start One-shot or continuous restart detection
watch history/show Browse restart history
proxmox status Proxmox VE cluster, nodes, guests, and storage
serve Web dashboard (browser-based, go:embed)
Flags:
--json JSON output (default: human-readable)
--verbose, -v Show detailed error information
--server <name> Run on a specific remote server
--all Run on all configured servers in parallel
--port <number> Port for serve command (default: 8080)
--config <path> Config file (auto-detected, see Configuration)
运行 homebutler --help 查看所有命令。
📋 所有命令与参数
Commands:
init Interactive setup wizard
config validate Check the config file and report what is ignored
status System status (CPU, memory, disk, uptime)
doctor Diagnose health, exposure, backups, and readiness
watch tui TUI dashboard (monitors all configured servers)
watch add <name> Add container to restart watch list
watch list Show watched containers
watch remove <name> Remove container from watch list
watch check One-shot restart check
watch start Continuous monitoring: restarts, thresholds, rules
watch install Register watch with systemd or launchd
watch installed Report whether it is registered
watch uninstall Remove the service unit
watch history List restart history (alias: incidents)
watch show <id> Show restart details with logs
serve Web dashboard (browser-based, go:embed)
docker list List running containers
docker restart <n> Restart a container
docker stop <n> Stop a container
docker logs <n> Show container logs
docker top <n> Show processes running inside a container
docker inspect <n> Show image, state, ports, mounts, networks, health
report What changed since the last snapshot
inventory scan Map containers, ports, and topology
inventory show Same as scan (--filter exposed narrows it)
inventory export Export the map (--format mermaid)
proxmox status Proxmox VE cluster, nodes, guests, storage
proxmox guests List QEMU and LXC guests
proxmox node <n> Node detail
proxmox guest ... start / shutdown / reboot (needs --confirm)
proxmox task <upid> Task status for an action already submitted
proxmox tasks Recent tasks on a node
proxmox script Community Script install commands (prints, never runs)
notify test Send a test notification through configured providers
wake <name> Send Wake-on-LAN packet
ports List open ports with process info
ps Show top processes (alias: processes)
ps --sort mem Sort by memory instead of CPU
ps --limit 20 Show top 20 (default: 10, 0 = all)
network scan Discover devices on LAN
alerts Show current alert status
alerts --watch Thresholds only (watch start covers these too)
trust <server> Register SSH host key (TOFU)
backup Backup Docker volumes, compose files, and env
backup list List existing backups
backup drill <app> Verify backup restores correctly (isolated)
backup drill --all Verify all apps in backup
restore <archive> Restore from a backup archive
upgrade Upgrade local + all remote servers to latest
deploy Install homebutler on remote servers
install <app> Install a self-hosted app (docker compose)
install list List available apps
install status <a> Check installed app status
install uninstall Stop app (keep data)
install purge Stop app + delete all data
mcp Start MCP server (JSON-RPC over stdio)
version Print version
Flags:
--json JSON output (default: human-readable)
--verbose, -v Show detailed error information
--server <name> Run on a specific remote server
--all Run on all configured servers in parallel
--port <number> Port for serve command (default: 8080)
--demo Run serve with realistic demo data
--watch Continuous monitoring mode (alerts command)
--interval <dur> Watch interval, e.g. 30s, 1m (default: 30s)
--config <path> Config file (auto-detected, see Configuration)
--local Upgrade only the local binary (skip remote servers)
--local <path> Use local binary for deploy (air-gapped)
--service <name> Target a specific Docker service (backup/restore)
--allow-bind <path> Host path a restore may write a bind mount to (repeatable)
--endpoint <name> Proxmox endpoint from config (optional if only one)
--confirm Required for a Proxmox guest power action
--to <path> Custom backup destination directory
--archive <path> Specific backup archive for drill
--all Verify all supported apps (backup drill)
🌐 Web 仪表盘
homebutler serve 会启动一个嵌入式 Web 仪表盘 — 无需 Node.js、无需 Docker、无需额外依赖。
homebutler serve # http://localhost:8080 homebutler serve --port 3000 # custom port homebutler serve --demo # demo mode with sample data homebutler serve install # hand it to launchd or systemd, so it survives logout homebutler serve uninstall # and take it back
安装的 unit 会记录地址,但绝不记录 token — token 来自配置文件中的
web.token,因为 --token 在 ps 中对机器上的每个用户都可见。
备份与恢复
一条命令完成 Docker 备份 — 卷、compose 文件和 env 变量。
homebutler backup # backup everything homebutler backup --service jellyfin # specific service homebutler backup --to /mnt/nas/backups/ # custom destination homebutler backup list # list backups homebutler restore ./backup.tar.gz # restore
⚠️ 为保证数据一致性,备份前应暂停数据库服务。
📖 完整备份文档 → — 工作原理、归档结构、安全说明。
告警阈值(高级)
alerts 仍然存在,用于 CPU、内存和磁盘阈值检查,但这是一个高级流程,不是推荐给新用户的第一步。
homebutler alerts --watch # default: 30s interval homebutler alerts --watch --interval 10s # check every 10 seconds homebutler alerts history # view alert history homebutler notify test # test your notification channels
默认阈值:CPU 90%、内存 85%、磁盘 90%。先从 watch 开始,只有当你特别想要基于阈值的检查时,再添加 alerts。
🔍 备份演练
“拥有备份”和“能够恢复”是两回事。
Backup Drill 在隔离的 Docker 环境中启动你的备份,并验证应用是否真的能响应——就像针对数据的消防演习。演练失败会以非零状态退出。
homebutler backup drill uptime-kuma # verify one app homebutler backup drill --all # verify all apps homebutler backup drill --json # machine-readable output homebutler backup drill --archive ./file # use a specific backup
完整演练流程,包括一次通过的演练不能证明什么:docs/backup.md。
会发生什么:
- 找到最新的备份归档
- 验证归档完整性(
tar校验) - 创建隔离的 Docker 网络 + 随机端口
- 从备份数据启动应用
- 运行 HTTP 健康检查
- 报告通过/失败并清理所有内容
🔍 Backup Drill — uptime-kuma
📦 Backup: ~/.homebutler/backups/backup_2026-04-04_1711.tar.gz
📏 Size: 18.6 MB
🔐 Integrity: ✅ tar valid (8 files)
🚀 Boot: ✅ container started in 0s
🌐 Health: ✅ HTTP 200 on port 58574
⏱️ Total: 2s
✅ DRILL PASSED
零风险——在完全隔离的环境中运行。你正在运行的服务绝不会被触及。
支持以下健康检查:nginx-proxy-manager、vaultwarden、uptime-kuma、pi-hole、gitea、jellyfin、plex、portainer、homepage、adguard-home。
配置
homebutler init # interactive setup wizard📖 report 比较什么 →——什么值得一行,什么被刻意抑制,以及为什么。
📖 配置详情 →——配置文件位置、监视/通知选项,以及高级告警阈值。
多服务器
通过 SSH 从单台机器管理多台服务器。
homebutler status --server rpi # query specific server homebutler status --all # query all in parallel homebutler deploy --server rpi # install on remote server homebutler upgrade # upgrade all servers
📖 多服务器设置 →——SSH 认证、配置示例、部署与升级。
MCP 服务器
内置 MCP 服务器——代理获得与输入 JSON 相同的报告,包含 kind、target 和 detail,而不是需要解析的句子,并且每个工具都被归类为读、写或破坏性。
{
"mcpServers": {
"homebutler": {
"command": "npx",
"args": ["-y", "homebutler@latest"]
}
}
}适用于 Claude Desktop、ChatGPT、Cursor、Windsurf 以及任何 MCP 客户端。
📖 MCP 服务器设置 →——支持的客户端、可用工具、代理技能。
安装
Homebrew(推荐)
brew install Higangssh/homebutler/homebutler
自动安装到 PATH。适用于 macOS 和 Linux。
一行安装
curl -fsSL https://raw.githubusercontent.com/Higangssh/homebutler/main/install.sh | sh自动检测操作系统/架构,下载最新版本,并安装到 PATH。
npm(MCP 服务器)
npm install -g homebutler
自动下载 Go 二进制文件。此包发布一个命令,
homebutler-mcp,它会启动 MCP 服务器——npx -y homebutler@latest
启动的是那个,而不是 CLI。对于命令行,请使用上面其他
安装方式之一。
Go 安装
go install github.com/Higangssh/homebutler@latest
从源码构建
git clone https://github.com/Higangssh/homebutler.git
cd homebutler
make build-allmake build-all 将 Web 仪表板编译进二进制文件,需要安装 Node。
make build 跳过它——无论哪种方式 CLI 都是完整的,而
homebutler serve 随后会提示仪表板缺失,并列出获取它的两种方式。
卸载
rm $(which homebutler) # Remove binary rm -rf ~/.config/homebutler # Remove config (optional)
架构
管家观察、决定什么值得说,并说出来——对你说,或对代理说。
有变化 →
report命名并排序 → 通知、仪表板或 MCP 调用 传递相同的答案。
┌─────────┐ ┌─────────┐ ┌─────────┐
│ CLI │ │ MCP │ │ Web │
│ stdout │ │ stdio │ │ :8080 │
└────┬────┘ └────┬────┘ └────┬────┘
└────────────┼────────────┘
▼
internal/*
system · docker · ports · network
wake · alerts · remote (SSH)
三个界面,一个核心:
| 界面 | 传输 | 使用场景 |
|---|---|---|
| CLI | Shell stdout/stderr | 终端、脚本、通过 exec 的 AI 代理 |
| MCP | 基于 stdio 的 JSON-RPC | Claude Desktop、ChatGPT、Cursor、任何 MCP 客户端 |
| Web | HTTP(go:embed) |
浏览器仪表板,通过 homebutler serve 按需使用 |
三者都调用相同的 internal/ 包——没有代码重复。
代理读取与人相同的报告,并获得它必须分支处理的部分, 而不是需要解释的屏幕:
report = json.loads(subprocess.run( ["homebutler", "report", "--json"], capture_output=True, text=True).stdout) for change in report["notable_changes"]: if change["kind"] == "replaced": # the container came back as something else redeploy(change["target"]) else: log(change["text"]) # "port: :8080/tcp — nginx → caddy"
每一行也携带 text,因此只想打印它的调用者不必
把句子重新拼起来。没有发现任何内容的运行返回 "notable_changes": [],
因此上面的循环在平静的日子里什么都不做。
以上都不是 homebutler 的职责:MCP 客户端、聊天机器人、cron 行或 终端前的人都能得到相同的答案。
默认不开放端口。 CLI 和 MCP 仅使用 stdin/stdout。Web 仪表板是可选加入的(homebutler serve,绑定 127.0.0.1)。
贡献
欢迎贡献!请先开一个 issue 讨论你想修改的内容。 CONTRIBUTING.md 说明了 homebutler 接受哪些内容,以及一个新目标需要证明什么。
安全
发现了漏洞?请通过 Security 标签页 私下报告,而不是公开 issue。SECURITY.md 说明了哪些内容在范围内,以及可以期待什么。
许可证
来源:Hacker News · github.com






