我都在自托管些什么
我很早就接触到了自托管领域,尽管那时候还没有这个说法。大学一年级时,我就在床下跑了一台装有 Linux 的服务器来托管网站。有一次室友嫌风扇噪音太大直接拔了电源,导致网站停了一段时间。随后几年,我运行的是 MythTV,后来换成了 XBMC(即现在的 Kodi)。
最近,我在印度生活了几年。那里的流媒体服务价格按西方标准来看非常便宜。我们有 Netflix、Disney Plus(在印度叫 Hotstar)和 Spotify。离开印度后,我不愿意再按西方价格付费订阅这些服务。同时,我也受够了那种“成瘾式”的体验循环,尤其是对于我儿子而言。我们希望限制他的观看范围,只允许看特定的节目,但平台不断推送的“为你推荐”和“接下来播放”总是引发冲突。虽然可以限制内容列表或关闭自动播放,但为每个服务单独设置,并时刻留意客户端应用更新后的重新配置需求,实在太过麻烦。
因此,我换了一种方式“切断线缆”(即取消订阅),彻底抛弃流媒体服务,转而使用自托管的 Jellyfin。在此后的一年半时间里,Jellyfin 为我打开了自托管其他许多服务的大门,降低了我对云服务提供商的依赖,带来了久违的稳定感。我不再被频繁的站点改版、价值存疑的新功能,以及关于服务条款更新、强制仲裁、数据泄露等的邮件轰炸所困扰。我会阅读自托管软件新版本的更新日志,自行决定是否升级以及何时升级。
规则
我遵循几条基本准则。
除运行在路由器上的 VPN 服务器外,我不将任何服务直接暴露在公网。我不关心这样做有多方便,也不关心应用有多安全,尤其是在 AI 辅助黑客攻击日益增多的当下,我认为这根本不明智。此外,我的 ISP 对 IPv4 地址使用了 CGNAT,因此我的家庭网络无法通过 IPv4 从公网直接访问。我的 VPN 服务器仅在 IPv6 上具有公网路由能力,这一限制虽有一些缺点,但对我的使用场景来说是可以接受的,而且很可能有助于减少恶意的连接尝试。最大的缺点是,由于公共 Wi-Fi 网络很少提供 IPv6,我的 VPN 几乎无法在这些网络上工作。使用手机时,我可以关闭 Wi-Fi 转而通过移动数据连接……如果信号有的话。 在可能的情况下,我倾向于原生运行服务,但会将复杂的服务或依赖众多的服务容器化。比如 Love:它是一个单独的 Go 二进制文件服务。如果某个服务只提供 Docker Compose 文件,并且要求运行 MySQL、Redis 和另外三个容器?那我已经在寻找替代方案了。如果依赖关系不至于过于繁重,原生方式更好、更快、更高效。我可以使用相同的管理工具和命令来管理多个服务,不需要为了在某个容器内运行命令而费心去适应它,也不用担心这个容器缺少 curl,那个容器运行 busybox 导致参数不同,或者还要处理虚拟网络和主机端口映射的问题。 与此相关,我现在不再使用 Docker。这并非一个原则性的立场,只是我受够了在服务器上管理一套完全独立的服务控制系统。我已经在用 systemd,而目前 Podman 与 systemd 的集成已经非常出色。 硬件 去年我买了一台 Beelink 迷你 PC,具体型号是 S12 Pro,搭载 Intel N100 处理器、16 GB 内存和 512 GB 内置 SSD。那会儿还是涨价潮之前,所以我花了 180 欧元。现在亚马逊上同样的商品要 359 欧元,真是肉疼!服务器外接了一个 6 TB 硬盘用于存储媒体文件。 我在 Hacker News 上关于自托管服务的评论引发了一些疑问:这些服务怎么可能跑在 16 GB 内存上。正如下面要讲的,我在架构上做了一些降低服务器资源占用的选择,但说到底,跑这么多东西根本不需要什么高级硬件。当然我没法在这台机器上跑本地 AI 推理,但除此之外的所有服务,基本上开箱即用,或者稍微改改配置就能跑起来。服务列表
按字母顺序排列。
Actual Budget
一款预算管理软件,有桌面客户端和网页应用,支持自定义报表和基于规则的交易分类。我只用它做预算和记录支票、储蓄、信用卡账户,投资账户则交给一个云服务管理。以后有机会再想办法摆脱那个云服务吧……
虽然 Actual Budget 支持从各家银行自动导入交易,但我没用这个功能。每月结束后,我会手动下载上个月的账单(优先 OFX 格式,实在没有就 CSV),然后手动导入。这对我完全够用,因为我主要拿它记账,而不是真正做……预算管理。
Podman 部署。
Audiobookshelf
把有声书和播客下载到自己的服务器上,然后在手机上收听。有声书功能我用得不多,主要是给孩子搭的,不过它的章节管理做得非常好。播客方面我先后用过 PlayerFM 和 Pocket Casts,现在只要人在家里、VPN 正常,我就用 Audiobookshelf。
原生部署。
Automatic Ripping Machine (ARM)
ARM 可以自动抓取并转码 DVD(也支持蓝光,但我不用)。是的,都 2026 年了,我还在抓 DVD。要知道我们家早就停了有线电视,所以这不仅是我们获取新内容的渠道,也是获取中英双语内容的途径。
Podman 部署。
Backrest
Restic 备份工具的 Web 界面。备份至关重要!尤其针对 Immich(照片)。Restic 在去重和压缩备份数据方面表现出色,Backrest 则让存储保留策略的管理变得简单直观。若备份失败,通知会发送至 Gotify。
原生运行。
Beszel
Beszel 是一个简单的监控仪表盘,它从代理端(这里指小巧的后台服务)收集基础统计数据,展示 CPU 负载、内存与磁盘占用、温度、电池电量等指标。这有助于我监控家中其他主机(几台 Raspberry Pi 和一个 Proxmox 集群,后者或许会成为未来某篇文章的主题)。
原生运行。
Caddy
Caddy 是一款 Web 服务器和反向代理。起初我不太理解反向代理的价值,觉得通过本地域名、IP 地址加端口直接访问服务足够了。但随着我部署的服务越来越多,且部分服务强制要求 HTTPS,我便注册了一个域名(非本站域名),并配置 Caddy 自动获取 Let's Encrypt SSL 证书。现在,我的几乎所有服务都可通过 HTTPS 和友好的子域名在内网(或经由 VPN)访问。新增服务只需快速编辑一下 Caddyfile 即可。
原生运行。
Cockpit
Cockpit 是服务器的 Web 管理控制台,采用标准系统认证方式。对我而言,它的主要用途是在未配置通知的服务出现故障时进行排查。
原生运行。
Forgejo
Forgejo 是 Gitea 的分支项目,部署方式精简为单个二进制文件。如今 GitHub 的稳定性常沦为笑谈,但我也很看重拥有自己 git 远端仓库带来的速度优势。未来我可能会搭建 CI/CD 和 runner,哪怕只是为了部署这个博客。
原生运行。
FreshRSS
基于 Web 的 RSS 阅读器。如今我基本只访问两个网站,所以很少使用它。不过,我会订阅一些自托管服务的 GitHub 发布页,以便查看新版本的特性和修复内容。
原生运行。
Frigate
网络视频录像机(NVR)。我最初使用的是 Zoneminder,主要因为我对它有情怀。但很明显,Zoneminder 已经过时了。Frigate 表现非常出色。我运行 8 个 IP 摄像头配合它使用,它可以对进入车道的行人和车辆发出警报,并与 Home Assistant 集成以驱动各种自动化流程(例如,当检测到后院有人时,自动打开摄像头泛光灯)。我未来可能会写一篇文章,详细分享我在 IP 摄像头方面的折腾经验。我的所有摄像头都运行在低于其支持的最高分辨率上,主要是为了避免 Wi-Fi 网络拥塞。大多数摄像头还支持更低的 RTSP 子流分辨率,Frigate 正是利用它来执行移动和物体检测。保持摄像头分辨率较低可以避免视频处理带来过高的 CPU 和内存占用,以及录像导致的磁盘占用过大。这些分辨率足以识别人脸,而且我所在国家的隐私法律禁止拍摄公共通行区域,所以我的摄像头都不会对准远处。
Podman。
Gonic
用 Go 编写的 Subsonic 兼容服务器。我多年前购买了一个永久的 Subsonic 许可证,但原始项目已经非常陈旧,且现代替代方案更好。我运行了两个独立的 Gonic 实例,一个提供儿童音乐,另一个提供成人音乐。
Native。
Gotify
用 Go 编写的简单通知服务。许多自托管服务直接支持 Gotify 通知,或者可以通过自定义 HTTP POST 发送通知。结合 Uptime Kuma,我使用 Gotify 接收各种通知,例如服务或设备宕机、孩子正在 Jellyfin 上观看什么内容、Audiobookshelf 中有新播客集可用等。
Native。
Home Assistant
Home Assistant 值得单独写一篇。它实在太棒了,很难想象要在 Google Home、Amazon Alexa 或 Apple Home 这类封闭生态里实现同样的功能会是什么样子。虽然现在设备厂商都在向 Matter 等协议看齐,情况有所改善,但 Home Assistant 提供的控制力和灵活性依然难以超越。不过它的学习曲线挺陡的,而且我还得认真考虑如何在不影响家庭功能的前提下应对潜在的服务器故障。
用 Podman 部署。
Homepage
后来我发现自部署的服务太多,需要一个专门的服务来管理它们。Homepage 是个不错的方案。它几乎为我运行的所有服务提供了小组件,可以快速总览各项服务的状态,也能直接跳转到对应服务的子域名。
用 Podman 部署。
Immich
Google Photos 的替代品。我受够了 Google 在应用里不停推销付费存储套餐。我自己的存储空间还够用,但我太太的空间总是快满了。去年 2.0 版发布后不久,我们就迁移到了 Immich。所有网络流量都在家庭内网时,加载满是照片的页面要快得多。我还想出了和家人共享相册的办法。不过在 Immich 上还有很多工作要做——我有很多重复照片,而且既然存储不再是问题,我在筛选照片和视频上就没那么勤快了。
用 Podman 部署。
Jellyfin
正如开头提到的,我自托管媒体已经很久了,可以追溯到二十多年前的 MythTV。Jellyfin 对媒体文件的目录组织有自己的规范,但总体用起来还不错。我只用它看电影、剧集和家庭录像,所以其他功能(电子书、音乐、照片等)没法评价。我儿子虽然还记得 Netflix,但对 Jellyfin 也很满意。我很喜欢它没有自动播放、看不到推荐算法、也不用划过一堆垃圾内容才能找到想看的东西。
我管理资源需求的一个主要方法是偏好使用 720p 媒体而非 1080p 或更高分辨率。显然,在抓取 DVD 内容时,分辨率只能是 576p 或 480p。虽然我有一台 4K 电视,但它尺寸不大。尽管我能分辨标清和高清之间的画质差异,但对于绝大多数内容而言,720p 对我来说已经足够了。
Podman。
Music Player Daemon (MPD)
有些解决方案就是好用且无需更改,我认为 MPD 就是这样。它已经存在 23 年了。虽然 Gonic 非常适合我在手机上听音乐,甚至可以通过 VPN 在外出时将家里的音乐流媒体传输到手机上,但 MPD 是我通过 Snapcast 向全屋音响系统播放音乐的方式。我运行两个 MPD 实例,一个用于音乐,另一个用于播客。
原生。
PocketBase
我过去使用 SQLite 文件来记录特殊账户(HSA、529 等)的交易和收据,并通过 SQL Workbench/J 直接访问。但随着我在不同国家、货币和保险体系之间迁移,事情变得复杂起来,我也希望让妻子能够录入交易。于是我迁移到了 PocketBase,本质上它仍然只是一个 SQLite 文件,但附带一个不错的基于 Web 的管理前端,我将其滥用为通用的 CRUD 前端。它的简单程度让妻子也能轻松使用,同时我仍可以对底层数据库文件运行任意查询。
原生。
Readeck
Readeck 允许我标记并归档我阅读内容的副本。研究生期间我是 Zotero 的重度用户,但好几年没需要写参考文献列表了。不过,我仍然希望确保日后能访问我阅读过的某些内容。我最初尝试了 Wallabag,但它在归档付费墙后的内容时遇到问题,即使我在手机上已登录。相比之下,Readeck 可以归档手机看到的内容并将其存储在我的服务器上。
原生。
Samba
Samba 提供共享网络存储,使在服务器上复制文件以及与家人共享重要文档变得容易。令人趣味的是,这个最初于 1980 年代开发、主要与 Windows 相关的文件共享协议,仍然是局域网内跨平台文件共享的最佳选择。
原生。
slskd
懂的都懂。
原生。
Snapcast
Snapcast 提供全屋音频同步播放。类似 Sonos,但没有昂贵的厂商绑定和计划性报废。它值得单独写一篇文章介绍。虽然设置起来比较复杂,但效果非常好。我打算购买一些额外的设备,主要用作 Snapcast 接收端。
原生。
Syncthing
Syncthing 是我 Immich 照片备份策略的一部分。我在 MacBook 上设置了一个单向同步(仅接收),这样 Immich 中的所有照片最终都会备份到 MacBook 的外接硬盘上。
原生。
Transmission Daemon
这个也是不言自明的。
原生。
Uptime Kuma
在我妻子多次抱怨“X 不工作了”、而我不得不手动重启服务后,我意识到需要一种方式来监控哪些服务在运行、哪些已停止。Uptime Kuma 功能简单但很实用。我可以 Ping 设备以确保其在线,检查 Podman 容器状态,查找各种服务的 HTTP 2XX 响应码,甚至解析 JSON 负载并提取健康检查所需的详细信息。如果有服务宕机,我可以发送 Gotify 通知(当然,之前会先重试几次)。
Podman。
Vaultwarden
Bitwarden 的自托管版本。多年来,我一直在使用KeePass,但始终没有很好的同步方案,所以干脆避免在手机登录各种账户。与此同时,我妻子使用的是 LastPass,除了自动填充经常失灵外,还发生过各种数据泄露和安全事件。让她迁移到 KeePass 不切实际,所以我选择了Vaultwarden,这是一个开源且 API 兼容的 BitWarden 重新实现,可以与官方 BitWarden 客户端配合使用。我不是很喜欢 BitWarden 的浏览器扩展,但总体还行。Android 应用足够好用,连接局域网时可以无缝自动同步;否则,我可以连上 VPN,必要时手动触发同步。
我有点担心 Bitwarden 未来可能对 Vaultwarden 变得不友好,破坏客户端兼容性。据我所知,目前唯一另一个兼容 Bitwarden 的主流客户端是 Keyguard,但它不是开源授权,而且采用免费增值模式。
用 Podman 运行。
Vikunja
我用 Trello 大约有十年了。但今年早些时候 Trello 发生了长达数天的严重宕机之后,我决定找一个可以自托管的替代品。一个只服务两个用户的服务,还要为此搭 PostgreSQL 或 MySQL 数据库,我直接不考虑。Vikunja 默认使用 SQLite,当然也能配置其他数据库后端。它并不完美,Android 应用也缺少一些功能,但对我来说够用了。单二进制文件部署?求之不得。
用 Podman 运行。
Yubal
一个用来下载 YouTube Music 播放列表的简易 Web 应用。下载 YouTube 视频我一般用 yt-dlp,在手机上看则用 NewPipe,但 Yubal 能把从 YouTube Music 下载的音乐妥善命名、整理并打上标签。
用 Podman 运行。
没有自托管的服务
下面这些是我没自托管、试过后放弃、或者不太可能去尝试的东西。
The *arr 全家桶
Sonarr、Lidarr、Radarr 等。每次看别人介绍搭建过程,给我的感觉就是又耗资源又容易出问题,三天两头坏。这和我选择自托管服务的初衷完全背道而驰。
Collabora Online
虽然能彻底告别 Google 当然很好,但作为存储和分享信息的方式,Google Docs 的便捷性和易用性实在难以超越。话虽如此,除非文档确实有上云的必要,我平时还是选择 LibreOffice Writer 和 Calc。既然我已经有共享网络硬盘了,再跑一个 Collabora Online(基于 Web 的办公套件)而不是直接在本地用 LibreOffice,就显得多此一举。
Firefly III
在尝试 Actual Budget 之前,我用过 Firefly III,当时觉得它原生支持多货币管理,挺有必要。结果部署很复杂,要跑好几个容器,光数据导入就得单独开一个。相比之下,Actual Budget 好搭得多,用起来也顺手。我有个简单脚本专门处理汇率换算,所以在 Actual Budget 里,外币账户的余额都能统一折算成美元显示。
Owntracks
我挺喜欢 Google Maps 的“时间线”功能,但 Google 把位置数据限制在单设备后,我就想找找个自托管替代方案。可惜 OwnTracks 的安卓端一直不稳定,试遍所有电池和定位设置,它也无法持续上报位置。Dawarich 是另一个选择,但它至少要跑四个容器(PostgreSQL、Redis、Sidekiq、Web 应用)。对我来说,投入的资源成本远高于能换来的实际价值,不值得折腾。
Music Assistant
如果你还没有一套顺手听音乐的方案,Music Assistant 或许是个不错的选择。但我手里已经有 Gonic、Snapcast 和 MPD 配合得很好,Music Assistant 总想“大包大揽”接管一切——比如它会不停地把我的 Snapcast 设备分组打乱重排。
邮件
自托管邮件服务性价比太低,投入的精力大,换来的好处却很少。我没法承担收不到或发不出邮件的风险。长远看,我打算从 Gmail 迁移到某个付费服务商。
结语
目前共跑了 17 个原生服务和 11 个 Podman 容器,全部由 systemd 统一管理。htop 显示内存占用约 7.5 GB,CPU 使用率在 30% 到 40% 之间波动。没想到这台迷你机算力这么强。眼下 AI 热潮把硬件价格推得老高,希望未来能有更多自托管项目把简单和高效放在第一位。