跳到正文
Hacker News· swq115·· 6 天前AI 评分22

HomeButler:把服务器报告从 7 行噪音压到 2 行变更

Show HN: Homebutler – my server report printed 7 lines for 2 changes, now 2

AI 导读

HomeButler 是一个单 Go 二进制工具,会记住服务器上次快照并只报告真正发生的变化,0.26.0 起用 replaced 等八类变更词替代单纯计数对比,避免容器同名重建被误判为"无变化"。它无需常驻 daemon 或数据库,可通过 CLI、JSON、Web 面板或 MCP 供 AI 智能体使用,支持 brew 安装与容器部署,经 SSH 访问被监控机器。

正文 · AI 翻译

HomeButler logo

只提值得说的变化。
一个单独的 Go 二进制文件,记住你的服务器上次长什么样, 然后告诉你——或者一个 agent——什么变了。

网站 · 文档 · 发布

Go 1.25+ License: MIT Release homebutler MCP server Coverage Status Go Reference

HomeButler mascot holding a tiny server

homebutler report run on a home server two hours after two containers were changed: filebrowser recreated and uptime-kuma moved from version 1 to 2. The report names exactly those two as replaced, with the old and new container IDs and both image tags, then the current status

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 记住你的服务器上次长什么样,判断什么值得说,然后说出来——前后都是六个容器,并不等于“没有变化”,当其中一个是不同的容器时。

读取一条变化

homebutler report output: a port answered by a different service flagged under Needs Attention, then what changed since the last report — a container gone, one new, one recreated behind the same name, a process running a different invocation, a port that changed owner — then current status and the command to verify the port

每一行有三列:什么类型的变化、它发生在什么上,以及 到底发生了什么。类型是八个词之一,而且在 --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 会话。

a run through homebutler: report naming what moved since the last snapshot — a container gone, a port answered by something new, one recreated behind the same name — then the same answer as JSON with the kind as a field, then doctor listing what is exposed and what has never been backed up with the command for each, then a backup drill booting the archive in its own container and requiring an HTTP health check, then the same report on a phone, then the settings screen editing notification channels

半分钟看完整个东西 · 全尺寸观看

快速开始

# 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

homebutler doctor reporting a full disk, a stopped container, and a missing report baseline, each with the command to run next

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 --json

config 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 scan

inventory 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 web dashboard

homebutler serve — 通过 go:embed 嵌入单一二进制文件中的 Web 仪表盘。可从任何浏览器查看服务器、Docker 容器、开放端口、告警和 Wake-on-LAN。使用 --token 时它还会编辑配置:阈值、通知通道、服务器、Proxmox 端点和唤醒设备。

报告标签页,你实际阅读它的地方

the Report tab on a phone: what needs attention first — a container recreated and not running, a port answered by something new — then the changes with their kind word, including a container replaced behind the same name and a comparison that could not be made, then doctor's findings ordered by severity with the command to run for each

有人在收到通知后打开的屏幕。首先显示需要注意的内容,然后是每个变化所携带的温和说明,接着是正在比较的快照及其时间。无法进行的比较会如实说明,而不是读起来像一切正常。

加载它不会保存任何内容——每次打开都拍摄快照的页面会修剪掉你想用来比较的基线。保存快照是一个按钮。

✨ 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。

📖 Proxmox 设置、令牌和 TLS →

🖥️ TUI 仪表板

homebutler TUI dashboard

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 访问、默认凭据警告

想要更多应用?提交 issue 或查看 贡献指南。

用法

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 中对机器上的每个用户都可见。

📖 Web 仪表盘详情 →

备份与恢复

一条命令完成 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。

会发生什么:

  1. 找到最新的备份归档
  2. 验证归档完整性(tar 校验)
  3. 创建隔离的 Docker 网络 + 随机端口
  4. 从备份数据启动应用
  5. 运行 HTTP 健康检查
  6. 报告通过/失败并清理所有内容
🔍 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-all

make 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 说明了哪些内容在范围内,以及可以期待什么。

许可证

MIT

来源:Hacker News · github.com