概述
Hearth(炉火)是一个自托管的家庭资料库。仓库主页上的一句话是:
Your family’s photos, videos, and files — warm, private, self-hosted.
家用照片、视频与文件归档:私密、自托管、开箱即用。
它把上传、浏览、家庭分组和整理放在同一套 HTTP API 上。服务端是 Go,Web 界面是 React,构建后嵌进同一个二进制。本仓库以服务端和 Web 为主;若另有 Android 客户端,README 说明它可以对接同一套 HTTP API,而不是放在这个仓库里。
下文依据 GitHub 上 main 分支的 README、许可证和公开代码,不补充仓库里没有写明的部署规模或使用人数。
程序怎么拼在一起
| 部分 | 仓库中的位置 | 作用 |
|---|---|---|
| 主进程 | cmd/hearth | HTTP 服务,默认监听 :8080 |
| MCP | cmd/hearth-mcp | stdio 服务,供 Cursor 等客户端调用同一套 API |
| Web | web/ | React 19 + Vite;web/ui.go 用 embed 装入 web/dist |
| 存储 | internal/store | SQLite(modernc.org/sqlite),迁移用 goose |
| 媒体 | internal/media | 按文件名和文件头分类,并包含 EXIF、缩略图相关代码 |
go.mod 写明模块名 hearth,Go 1.27。Makefile 里的 build / mcp 都使用 CGO_ENABLED=0。Docker 构建分两段:Node 24 打前端,Go 1.27 打二进制,最终镜像基于 Alpine 3.22,并安装 ffmpeg 与 vips-tools。docker-compose.yml 把数据放在命名卷 hearth-data,并用 GET /healthz 做健康检查。
GitHub Actions(.github/workflows/ci.yml)在推送和 pull request 上执行:安装 Go 1.27 与 Node 24、构建前端、go test ./...,再以 CGO_ENABLED=0 编译主程序。
文件、合集与权限
文件的 media_kind 只允许四类:image、video、audio、other。分类函数会看扩展名和文件头;只有音轨的 mp4 / m4a / webm 会归到音频,避免被当成视频打开。图片扩展名覆盖 jpeg、png、gif、webp、heic / heif。
可见性字段只有两种:private 与 shared。README 把 shared 解释为登录用户可见。除此之外,合集还可以授权给指定用户或用户组;管理员在检索等接口中可以越过普通成员限制。
合集最初有单一的 media_kind。后续迁移增加了 media_kinds,因此一个合集可以同时容纳多种类型。合集、用户组成员、合集成员和收藏都在同一组表里:collections、groups、group_members、collection_users、collection_groups、favorites。
误删走回收站:files.deleted_at 非空表示已删除,检索默认不返回这些行。收藏是用户与文件的一对记录,按用户和时间索引。
分享链接单独存放。shares 表记录文件、创建者和 expires_at。MCP 创建分享时,过期可选 never(默认)、7d 或 30d,对应 POST /api/files/{id}/shares。README 写明这是无需登录的预览链接。
示例配置里,单次上传上限为 2147483648 字节(2 GiB),会话默认 168 小时。真实的 hearth.toml 在 .gitignore 中,仓库只提供 config.example.toml。
主题
界面主题写在 web/src/styles.css。除默认配色外,还有五种具名主题:pine、dusk、sand、sea、sakura。sakura 使用浅粉背景和 #E891A8 强调色。App.jsx 按当前用户的 theme 字段设置 document.documentElement.dataset.theme。
检索
检索走 SQLite FTS5,分词器是 unicode61 remove_diacritics 2。
files_fts索引文件名,以及该文件所属合集名collections_fts索引合集名- 插入、删除、改名时由触发器维护索引
GET /api/search?q= 由 Store.Search 实现。查询会先截断到 200 个 Unicode 字符,再按空白拆成词。每个词变成带前缀的 FTS 查询("词"*),词与词之间是 AND。代码注释说明,这样英文词干和中文前缀都能配合 unicode61 使用。
未指定排序时,文件和合集都按同一优先级:
- 名称精确匹配(不区分大小写)
- 名称前缀
- 名称中包含
- 其余命中
同级再按 bm25() 从低到高,然后才是创建时间或名称。已进回收站的文件不会出现。权限与列表一致:管理员、所有者、shared,或该用户能访问的合集。默认最多返回 200 个文件和 50 个合集。
测试 TestSearchFTSRankingAndPermissions 覆盖了精确名先于前缀、前缀先于包含,以及私有文件不会被其他普通用户搜到等情况。
MCP
make mcp 生成 bin/hearth-mcp。进程名是 hearth,实现版本字符串为 0.1.0。它通过环境变量连接已经在跑的 Hearth:
| 变量 | 是否必需 | 默认 |
|---|---|---|
HEARTH_BASE_URL | 否 | http://127.0.0.1:8080 |
HEARTH_USERNAME | 是 | — |
HEARTH_PASSWORD | 是 | — |
示例描述符在 mcp/hearth.mcp.json,其中的用户名和密码是占位符。当前注册的工具有:
hearth_whoamihearth_list_fileshearth_searchhearth_list_collectionshearth_create_collectionhearth_list_groupshearth_rename_grouphearth_file_metadatahearth_set_favoritehearth_create_share
在本机跑起来
README 要求 Go 1.27+;只有构建前端时才需要 Node.js 24。首次启动若还没有可用管理员,会用环境变量创建,之后再次启动不会改密码。
| |
make run 监听 :8080,浏览器打开 /login。前端开发时另开一个终端,在 web/ 里执行 npm run dev,把 /api 代理到 127.0.0.1:8080。也可以直接 docker compose up --build。
示例 systemd 单元在 deploy/hearth.service:从 /etc/hearth/hearth.toml 读配置,工作目录 /var/lib/hearth。
许可证与贡献
仓库使用 MIT 许可证,版权声明为 Copyright (c) 2026 Junxiao and contributors。README 为中英对照。贡献说明要求改动保持聚焦,用 go test ./... 验证,涉及检索时覆盖中英文文件名,并且不要提交 hearth.toml、真实密码、本机绝对路径、上传日志或 data/。
代码与说明见 github.com/rovinax/hearth。
评论
留言经审核后显示,欢迎留下想法。