Unison 怒评
摘要
一位开发者将 Unison 作为轻量级替代方案进行评估,用于自托管 KeePass 数据库的同步,以取代重量级同步工具。文中详细记录了配置过程中遇到的挑战以及 Socket 模式的搭建过程。
<p><a href="https://lobste.rs/s/bml5i5/unison_anger">评论</a></p>
查看缓存全文
缓存时间: 2026/05/12 11:18
# Unison In Anger
来源:https://blog.feld.me/posts/2026/05/unison-in-anger/
我使用 KeePass 系列软件管理密码,在 iPhone 上可以使用出色的 KeePassium(https://keepassium.com/),它支持通过 WebDAV 同步密码数据库,实现自建“云”同步基础设施,但 Linux/FreeBSD 上的 KeePassXC(https://keepassxc.org/)却完全不提供这类功能。如果你想同步密码数据库,只能自己想办法。
通常这时候会有人建议使用 Dropbox 风格的文件同步软件,比如 Syncthing。这确实可行,但说实话,这需要运行一个相当重的服务,尽管它是用 Go 写的,在我的一台服务器上仍然会消耗约 400MB 内存。
我也见过有人推荐 git,但那也很重。我的主密码数据库将近 2MB,KeePass 每次修改都会重写整个文件,所以 git 仓库会随时间迅速膨胀。
Rsync 呢?但双向同步会很棘手……
我们正经历严重的内存短缺。肯定有更简单的方案,对吧?几十年来人们在 *nix 上处理文件,我们能想到的最好方案就是 Syncthing?
我继续寻找轻量级的 *nix 文件同步工具,大多走进了死胡同,直到 Unison 出现了。
我想我叔叔认识他。他说他已经去世了。
这看起来很有希望。
## 进入 Unison(https://blog.feld.me/posts/2026/05/unison-in-anger/#enter-unison)
保持本色,Ponyboy
Unison(https://github.com/bcpierce00/unison)……我认识你已有几十年了。曾试用过 GUI 版本五分钟,困惑不解,就再也没碰过。是时候深入了解一下了。
简介
Unison 是一款适用于 POSIX 兼容系统(如 *BSD、GNU/Linux、macOS)和 Windows 的文件同步工具。它允许将一组文件和目录的两个副本存储在不同主机(或同一主机的不同磁盘)上,分别进行修改,然后通过将每个副本中的变更传递到另一个副本来使它们保持同步。
Unison 自 1998 年就已存在,和所有由关心用户的开发者编写的软件一样,它附带了一份极其详尽的手册(https://raw.githubusercontent.com/bcpierce00/unison/documentation/unison-manual.pdf)。看看这家伙!它太棒了,就像官方的 Bacula 文档一样。
另一方面,它也让人望而生畏。里面的内容太多了。不过,我只有一个目标:想办法用它解决我的问题,而*不必*依赖像 SSH 这样的重型工具。文档确实提到可以监听 socket,但却试图吓退你。
警告
TCP socket 方式是不安全的:不仅你的变更文本会以未受保护的形式在网络上传输,而且世界上任何人都可以连接到服务器进程,读取你文件系统的内容!(当然,要做到这一点,他们需要理解 Unison 客户端与服务器之间通信的协议,但他们只需要一份 Unison 源代码即可。)Socket 方式仅提供给有特定需求的专业用户;其他所有人都应该使用 ssh 方式。
你好 👋 我是一名专业用户,想这样做,谢谢!
## 让它跑起来(https://blog.feld.me/posts/2026/05/unison-in-anger/#making-it-work)
这是我的计划和目标。
- 同步整个目录,其中可以有多个 KeePass 数据库文件
- 不允许任何客户端删除任何文件(防止“糟糕,同步状态坏了,所有东西都被删了”)
- 尽可能快速且轻量
使用 Unison 的 socket 模式很困难。确实非常困难,以至于我的特定配置在文档中根本找不到任何示例。我不得不把源代码交给一个 LLM 去啃,才找出让它正常工作所需的准确语法。下面是结果。
### 服务端(https://blog.feld.me/posts/2026/05/unison-in-anger/#server)
服务端是这样运行的:
`UNISON=/var/db/unison /usr/local/bin/unison default \-socket 8080`
在 `/var/db/unison` 中有一个配置文件 `default.prf`:
``
# /var/db/unison/default.prf
# 在这个根目录下有一个叫 "keepass" 的目录。
# 那才是我们实际要同步的内容。
root = /path/to/dir
# 同步时不需要保留用户/组所有权
owner = false
group = false
# 这个 backup 行告诉它要包含什么——glob 匹配所有
backup = Name *
# 注意这里提到了 "keepass"
nodeletionpartial = BelowPath keepass -> /path/to/dir
``
重要
**nodeletionpartial** 可以阻止 Unison 执行任何文件删除。在这里,它适用于 keepass 目录下的所有内容。
### 客户端(https://blog.feld.me/posts/2026/05/unison-in-anger/#client)
在我的家目录下,有客户端配置文件的这个文件。我要把 keepass 目录同步为 `/home/feld/unison` 的子目录。
``
# /home/feld/.unison/default.prf
# 是的,两个 root。有点怪,对吧?
root = /home/feld/unison
root = socket://192.168.1.100:8080//path/to/dir
batch = true
silent = false
auto = true
owner = false
group = false
times = true
prefer = newer
# 要同步的目录
path = keepass
# 在客户端,我们也告诉它不要删除。以防万一……
# 而且这里必须不带端口。很让人困惑吧?感谢 Claude
nodeletionpartial = BelowPath keepass -> 192.168.1.100
``
好了!现在运行 `unison default` 就应该能同步了。把这个小家伙放进 crontab 里,然后继续你的生活:
``
# 分钟 小时 日期 月份 星期 命令
MAILTO=""
*/5 * * * * /usr/local/bin/unison default 2>&1 >/dev/null
``
现在它会每 5 分钟同步一次,考虑到我修改密码的频率很低,这已经绰绰有余了。如果我偶尔不放心,可以在做任何更改之前手动运行 `unison default` 来确认已同步。最坏的情况是,可能因为客户端时间不同步导致服务器误以为我的文件更新而覆盖数据,但我有 ZFS 快照和 Bacula 备份,所以不太担心。
## 但是,安全呢!(https://blog.feld.me/posts/2026/05/unison-in-anger/#but-security)
好吧,我知道这不是最好的做法,因为完全没有对传输过程进行安全保护。发挥一点创造力。我的建议是使用类似 stunnel(https://www.stunnel.org/)或 spiped(https://www.tarsnap.com/spiped.html)的工具。我最终选择了 spiped,并把它作为守护进程在客户端上运行,它创建了一个 unix socket `~/.unison/s.pipe`,然后我让 Unison 通过它来工作。这需要对客户端和服务端做一些调整。spiped/stunnel 配置的细节没什么意思,任何人都能轻松搞定,但我必须做的服务端和客户端改动如下:
### 服务端(https://blog.feld.me/posts/2026/05/unison-in-anger/#server-1)
我让它监听 `127.0.0.1:8081`,然后 spiped 会监听 `0.0.0.0:8080`,这样我就不用修改任何防火墙规则了。`listen` 标志控制你绑定的 IP 地址,而 socket 只是端口。(有点奇怪,对吧?)
`/usr/local/bin/unison default \-listen 127.0.0.1 \-socket 8081`
注意
我本可以让 Unison 监听一个 unix socket,而不是 `127.0.0.1:8081`,但这留给读者作为练习。
### 客户端(https://blog.feld.me/posts/2026/05/unison-in-anger/#client-1)
我必须修改客户端的配置文件,加入以下内容:
``
root = socket://{/home/feld/.unison/s.pipe}//path/to/dir
nodeletionpartial = BelowPath keepass -> {/home/feld/.unison/s.pipe}
``
## 同步;同步;同步(https://blog.feld.me/posts/2026/05/unison-in-anger/#sync-sync-sync)
结论:它管用。速度快。几乎不消耗资源。感谢 Benjamin C. Pierce 制作了这个工具。我不知道是谁折磨你,让你在 Unison 中实现了如此丰富的功能。这篇博客文章或许更应该是一份文档拉取请求,但我们真的想鼓励更多人这么做吗?嗯……
相似文章
rsync 与愤怒
Rsync 维护者 Andrew Tridgell 为其使用 AI 工具(Claude, Codex, Gemini)以提升安全性并重写测试套件的行为进行辩护,回应了来自开源社区的强烈反对。
你的AI编程代理是否会互相干扰?
AvailSync 是一个小型 MCP 工具,通过在工作前检查仓库可用性,防止多个 AI 编程代理发生冲突。
我同时运行 Claude Code 和 Codex,却总是丢失它们之间的线索——于是构建了一个位于 S3 存储桶中的无服务器协调层
tracecraft 是一个 CLI 工具,使用兼容 S3 的存储桶作为多个编码代理(如 Claude Code 和 Codex)的无状态协调层,支持原子任务认领、邮箱、共享内存和跨工具框架会话镜像。
Openrsync:由OpenBSD团队开发的rsync实现
Openrsync是OpenBSD团队采用BSD许可重新实现的rsync,兼容现代rsync协议并支持Unix系统。
@levelsio: 这是我最近的设置。每个网站我都在Termius中设置了一个配置文件,比如 > hoodmaps.com,点击后立即进入…
Pieter Levels分享了他的服务器工作流程:使用Termius配置文件和一个自定义的tmux函数,自动连接到每个网站的会话,实现设备间无缝切换和一致的工作会话。