Ohhnews

分类导航

$ cd ..
foojay原文

告别Google Drive:用Tailscale上的Syncthing同步KeePass密码数据库

#syncthing#tailscale#文件同步#密码管理#隐私保护

我曾用 Dropbox 用了十几年,后来换成了 Google Drive。对大多数文件来说,两者都能胜任。但有那么一个文件始终不太合适:我的 KeePass 密码数据库。它是我需要在每台设备上访问的文件,也是我最希望保持私密的文件。在遭遇了太多烦人小事之后,我把它迁移到了运行在 Tailscale 网络之上的 Syncthing。其余的,暂时仍然留在 Google Drive。本文讲述其中的缘由与做法。

那个让我上心的文件

我的密码管理器基于 KeePass。笔记本上我用 KeePassXC,iPhone 和 iPad 上我用 KeePassium。两者打开同一个 .kdbx 文件。这是一个单一的加密二进制文件,每次修改都会整体重写,并受物理安全密钥保护。我会在任意设备上编辑它,有时离线操作。这对任何同步工具来说都是最糟糕的情形。

在我原来的设置中,Google Drive 充当笔记本与手机之间的中转站。我购入了 KeePassium 高级版,就是为了使用它的 Google Drive 集成。这个配置极其简单,而且一开始确实能用。然而,每隔一段时间,我 iPhone 上的副本就不再跟随笔记本上的那份。最可能的原因是 KeePassXC 的保存方式:它写入一个临时文件,删除原文件,再把临时文件重命名为原文件名。Google Drive 按标识符而非文件名来跟踪文件,所以被重命名后的文件算是一个新文件。KeePassium 却一直指向那个已被删除的旧文件。要么我接受一个过时的数据库,要么我让 KeePassium 指向新文件。重新添加数据库意味着必须从头解锁,而我的数据库受物理安全密钥保护。每隔几周就得去取一次那枚密钥,实在让人心累。我必须找一个解决方案。

注: 换一种保存方式本可以解决这个烦恼。不幸的是,我是在为本文查资料时才了解到 KeePassXC 的安全保存选项。而且无论如何我也不会回头,因为我想远离 Google 及其他总部位于美国的超大型企业。

Drive 还会把文件的每一个版本都保存在 Google 的服务器上。对于我与人协作编辑的文档,这是个优点。但对于一个只有我在编辑的文件,这就等于在我的密码数据库的历史记录存放在 Google 的服务器上。问题的根源其实并不在于 Google Drive 本身。

顺带一提,离开 Google 也有益于我的隐私。

Syncthing,以及为什么用 Tailscale

Syncthing 是一款点对点文件同步工具。每台设备运行自己的实例,并拥有一个唯一标识符。你通过交换标识符来配对设备,然后逐个文件夹地与特定设备共享。没有服务器拥有数据:每台设备都持有所订阅文件夹的完整副本。节点既可以是发送加接收,也可以仅接收。

Syncthing 开箱即可用于公共互联网。为此,它依赖 Syncthing 项目运行的基础设施:全局发现服务器,每台设备在此公布自己当前的 IP 地址;以及中继服务器,当两台设备无法直接连通时为其转发加密流量。无论哪种情况,流量都是端到端加密的。 尽管如此,第三方仍知道我设备的位置,而且我的加密流量可能会经过它的中继。

多亏了 Tailscale,我所有设备之间早已存在一个私有网络。我在从 Cloudflare Zero Trust 到 Tailscale一文中描述过这套设置。无论身处何地,每台设备在网格中都有一个稳定的名称和地址。有了 Tailscale,Syncthing 便不需要发现服务器,也不需要中继。我可以把它们关掉,直接按名称寻址设备。

我完全清楚 Tailscale 也是第三方。它的协调服务器分发设备的公钥,并知道哪台设备与哪台连接、从何方连接,尽管它们从来看不到流量内容。

不过,Tailscale 客户端是开源的,而且 Headscale 是协调服务器的一个自托管实现,官方的 macOS、iOS 和 Synology 客户端都能登录进去。如果哪天我想脱身,我一个下午就能把四台设备迁移过去。这是一条真实的退路,尽管并非完全免费:每台设备都会获得新的密钥、新的地址和新的名称,而且除非我自己运行中继,否则中继流量仍会经过 Tailscale 的服务器。眼下,便捷占了上风。

[LOADING...]

拓扑结构是一个星形。NAS 始终在线,所以其他每台设备都只与它配对。笔记本、iPhone 和 iPad 之间从不互相通信。这让配置更简单,代价是存在单一故障点。稍后我会再谈这一点。NAS 在协议中并无特殊角色。它之所以成为枢纽,仅仅因为它从不休眠。

设置

以下内容假设 Tailscale 已在每台设备上运行,且已启用 MagicDNS,从而每台设备都有一个形如 <device>.<tailnet>.ts.net 的名称。

Synology 设置

Syncthing 可通过 SynoCommunity 在 Synology 上使用。在“套件中心”中,将 https://packages.synocommunity.com 添加为套件来源,然后安装 Syncthing。该套件未经 Synology 验证,但这在意料之中。启动后,Web 界面位于 http://nas.<tailnet>.ts.net:8384。默认没有密码。在 操作 > 设置 > 图形界面 下设置一个密码。该套件以自己的用户身份运行;请在“控制面板”中赋予它对共享文件夹的写入权限。

打开它,然后进入 操作 > 设置 > 连接。取消勾选 全局发现、启用中继 和 启用 NAT 穿透。

[LOADING...]

本地发现是无害的,但我也把它取消勾选了。NAS 不需要发现任何其他设备;由设备来发现它。开启 NAT 穿透时,Syncthing 会请求路由器从互联网转发 22000 端口,并查询公共 STUN 服务器以获知自己的公网地址。我的路由器会忽略该请求,所以端口永远不会开放。

手机仍将我的公网 IP 列在 NAS 的地址之中:发现服务器会根据公告来源地把它填进去。我索性取消了该勾选,这样 NAS 既不与路由器通信,也不与 STUN 服务器通信。

Syncthing 的连接是双向的,所以每一对设备中只要有一方知道另一方的地址就足够了。在 Synology 上,这一方是被强制的。Tailscale 套件以用户空间模式运行:NAS 可以接受来自 tailnet 的连接,但无法发起任何连接。因此,每台设备都保存着 NAS 的地址,而 NAS 则把每台设备都保持为 dynamic。在未启用发现的情况下,dynamic 意味着 NAS 永远不会主动拨号连接任何人。

然后,创建文件夹。点击 添加文件夹,并选择 NAS 上的路径。暂时让 共享 选项卡留空。接下来是设备,它们会主动现身。在 文件版本控制 选项卡中,选择 简单文件版本控制。NAS 会在 .stversions 文件夹中保留每个文件最近几个版本。它是唯一这样做的设备。

macOS 设置

在 macOS 上,Homebrew 就能搞定:

brew install syncthing
brew services start syncthing

Web 界面位于 http://127.0.0.1:8384。应用与 NAS 上相同的连接设置。在 NAS 的 Web 界面中打开 操作 > 显示 ID,然后在笔记本上点击 添加远程设备。粘贴 NAS 的标识符,并将其地址设置为 tcp://nas.<tailnet>.ts.net:22000。不出一分钟,NAS 上就会显示一条横幅:有新设备请求连接。

接受它,保持其地址为 dynamic,并在 共享 选项卡中勾选该文件夹。随后笔记本上会显示文件夹提议。接受它,并把路径设为你想存放文件的位置。一旦成功,NAS 会列出笔记本为已连接,两边的文件夹都显示“最新”。在家中,Tailscale 会让两者在局域网内直接相连,所以同一个地址在任何地方都有效。

警告: macOS 会拒绝后台进程访问“文稿”、“桌面”和“下载”文件夹,除非你明确授予它权限。Syncthing 作为后台服务运行,因此位于“文稿”下的文件夹会以“不允许的操作”而停止。请把同步文件夹放在别处,例如 ~/Sync。

iOS 设置

Syncthing 没有官方的 iOS 客户端。我用的是 Sync Anything。它是免费增值模式:免费版只能同步到单台设备上的单个文件夹。如果你想要更多,你知道该怎么做。

在手机上,通过扫描 NAS 的 操作 > 显示 ID 屏幕上的二维码来添加 NAS。点按 NAS 条目上的 编辑,把 dynamic 替换为 tcp://nas.<tailnet>.ts.net:22000。

[LOADING...]

像笔记本那样,在 NAS 上接受手机并勾选文件夹。在手机上接受该文件夹。Sync Anything 没有开放连接开关,所以手机仍会向发现服务器公告自己,并可能使用中继。在设置了 NAS 地址后,它会优先通过 Tailscale 连接。那是我没能堵上的那个泄漏点。

与笔记本有一处不同:iOS 不允许应用永久在后台运行。同步在应用打开时进行,其他时候则伺机而为。注意,手机上的 Tailscale 也必须处于运行状态。

KeePassium 与 KeePassXC 设置

笔记本上没有任何变化:KeePassXC 从同步文件夹中打开 .kdbx 文件。在手机上,打开 KeePassium,添加一个数据库,然后在“文件”应用中浏览到 Sync Anything 的位置。KeePassium 读写的是一个本地文件。没有云连接器,也没有理由重新添加数据库,于是安全密钥可以一直躺在抽屉里。

我同步的内容

Syncthing 共享的是文件夹,而不是某个根目录。任何文件夹、磁盘上的任何位置、任何设备子集。与 Dropbox 和 Google Drive 相比,这是一个巨大的优势,因为它们只同步一个根文件夹,你最多只能选择某台设备能获得哪些子文件夹。

实际上,我还没真正用上这一优势。目前,我只与 NAS 同步一个根文件夹,里面仅包含密码数据库。照片通过 Synology Photos 处理,它有自己的应用。工资单是下一个候选对象,但我不需要在手机上查看它,而且我本来也很少看。那更多是一个长期存储而非同步的问题,是留待改日再议的设计难题。

权衡

不过,这套设置也有权衡。

四台设备、无服务器,再加一个每次修改都整体重写的文件:冲突是可能发生的。如果我离线在手机上编辑了数据库,随后又在笔记本上编辑,Syncthing 会保留两份,并将其中一份重命名为 .sync-conflict-*。KeePassXC 可以合并两个数据库,所以恢复不过是几分钟的事。这种情况我还没遇到过,但我知道万一发生我也有办法应对。

由于 iOS 的后台限制,手机上的副本可能落后。当我确知改过一个密码时,我需要先打开 Sync Anything,再打开 KeePassium。这是一个习惯,算不上解决方案。

另外,星形拓扑意味着当 NAS 宕机时,什么都同步不了。笔记本和手机各自保留自己的最后一份副本并继续运作。对我来说可以接受,因为 NAS 是家里最可靠的设备。让笔记本直接与手机配对本可以消除这个问题,但 Sync Anything 的免费版只允许一台远程设备。

最后,我没有做数据库备份。它存在于四台设备上,但四份始终相同的副本并不等于备份:一次删除或一次损坏的保存,都会在几秒钟内传播到全部四台设备。这正是 NAS 保留旧版本的原因。它能覆盖潜在的误编辑。NAS 本身没有备份;如果它坏了,三份当前的副本会幸存下来,但历史记录也随之而去。我接受这一点。RAID 5 能应对坏掉的磁盘,而历史记录只是一种便利,并非必需品。## 结论

我的密码数据库迫使我重新思考文件究竟该存放在哪里。答案是:就在我自己的机器上,而且只在那里。Syncthing 负责同步,Tailscale 则为它提供一个具有稳定名称的私有网络。我很乐意离开 Google Drive,哪怕只是为了一个文件。

一点一点,一步一步。接下来要迁移的是那些我经常阅读但不常写入的文件,以及归档文件。

延伸阅读:


最初发表于 A Java Geek,2026 年 11 月 1 日。

分享此页面

发现错误或有内容要补充?在 GitHub 上编辑此页面

[LOADING...]

作者

Nicolas Frankel

专注于云原生技术、DevOps、CI/CD 流水线与系统可观测性的技术专家。他的工作重心围绕创建技术内容、发表演讲,以及与开发者社区互动,推动现代软件的采用……

参与讨论