这篇记录一个从零部署 Syncthing 的备份场景:A 机器是 Ubuntu 或 Debian,作为源端;B 机器可以是 Ubuntu、Debian 或 Alpine,作为备份端;目标是把 A 机器上的 /srv/backup 单向同步到 B 机器,不让备份端的改动反向影响源端。
如果前面还有一台业务服务器只负责打包并上传备份,生产链路可以拆成三段:
业务服务器 A -> SSH 上传 tar.gz -> Syncthing 源端 B:/srv/backup -> Syncthing 单向同步 -> 最终备份端 C:/srv/backup这种情况下,A 不必运行 Syncthing;A 只需要把完整备份包原子地放入 B 的 /srv/backup。真正负责同步状态、设备连接和最终落盘的是 B 与 C 上的 Syncthing。
Syncthing 是一个持续文件同步工具,可以在两台或多台机器之间实时同步文件。它没有中心服务器,数据只保存在自己的设备上;设备之间的通信使用 TLS 加密,每台设备也通过独立证书身份识别。Web 管理面板只建议通过本机监听和 SSH 隧道访问,不要直接暴露到公网。
适用场景
- 源端目录:
/srv/backup - 备份端目录:
/srv/backup - 目录属主:
syncthing:syncthing - 同步模式:源端
仅发送,备份端仅接收 - 运行用户:专门创建的
syncthing普通服务用户 - 管理方式:通过 SSH 隧道访问 Syncthing Web GUI
实际生产里也可以把源端同步端口改成非默认端口,例如 B 机监听 29029/tcp 和 29029/udp,C 机继续监听默认 22000。Syncthing 设备地址保留 dynamic 时会通过发现服务交换真实地址;手动指定地址时才需要写成 tcp://公网IP:端口。
本文从安装开始就把服务、配置目录和同步目录都交给 syncthing:syncthing,符合 Syncthing 对运行用户的建议。
一、Ubuntu 源端配置
1. 安装 Syncthing
sudo apt update
sudo apt install syncthing -y创建服务用户、配置目录和同步目录:
sudo useradd --system --home /var/lib/syncthing --create-home --shell /usr/sbin/nologin syncthing
sudo install -d -o syncthing -g syncthing /var/lib/syncthing
sudo install -d -o syncthing -g syncthing /var/lib/syncthing/.config
sudo install -d -o syncthing -g syncthing /var/lib/syncthing/.local/state/syncthing
sudo install -d -o syncthing -g syncthing /srv/backup生成 Syncthing 配置:
sudo -u syncthing syncthing -generate="/var/lib/syncthing/.config/syncthing"2. 启动 systemd 服务
Ubuntu 和 Debian 的软件包通常提供 syncthing@.service 模板。这里使用 syncthing@syncthing.service,表示以 syncthing 用户运行:
sudo systemctl daemon-reload
sudo systemctl enable --now syncthing@syncthing.service
sudo systemctl status syncthing@syncthing.service --no-pager确认进程用户:
ps -eo pid,user,args | grep '[s]yncthing'正常应该看到 USER 是 syncthing,命令类似:
syncthing /usr/bin/syncthing serve --no-browser --no-restart --logflags=0查看监听端口:
ss -tunlp | grep syncthing常见监听包括:
tcp LISTEN 0 4096 127.0.0.1:8384 0.0.0.0:* users:(("syncthing",pid=1234,fd=14))
tcp LISTEN 0 4096 *:22000 *:* users:(("syncthing",pid=1234,fd=11))
udp UNCONN 0 0 *:22000 *:* users:(("syncthing",pid=1234,fd=13))
udp UNCONN 0 0 0.0.0.0:21027 0.0.0.0:* users:(("syncthing",pid=1234,fd=19))其中:
127.0.0.1:8384是 Web 管理面板。22000/tcp和22000/udp是设备同步端口。21027/udp主要用于局域网发现。
如果你在 Syncthing 高级设置里把监听地址改成了自定义端口,例如:
tcp://0.0.0.0:29029
quic://0.0.0.0:29029那系统防火墙、云安全组和另一端手动地址都要使用 29029,不要继续照抄 22000。
3. 通过 SSH 隧道访问源端面板
Web GUI 只监听本机时,从自己的电脑建立隧道:
ssh -N -L 8384:127.0.0.1:8384 user@你的Ubuntu服务器IP然后在本地浏览器打开:
http://127.0.0.1:83844. 放行同步通信端口
如果 Ubuntu 使用 UFW,只放行同步端口:
sudo ufw allow 22000/tcp
sudo ufw allow 22000/udp
sudo ufw reload不要把 8384 当成同步端口开放。8384 是管理面板端口;设备之间传输文件默认使用 22000/tcp、22000/udp,或者由 Syncthing 的发现和中继机制协商。
二、Ubuntu/Debian 备份端配置
如果备份端也是 Ubuntu 或 Debian,安装方式和源端一致,只是后面在 Web GUI 里把文件夹类型设为 仅接收。
sudo apt update
sudo apt install syncthing -y
sudo useradd --system --home /var/lib/syncthing --create-home --shell /usr/sbin/nologin syncthing
sudo install -d -o syncthing -g syncthing /var/lib/syncthing
sudo install -d -o syncthing -g syncthing /var/lib/syncthing/.config
sudo install -d -o syncthing -g syncthing /var/lib/syncthing/.local/state/syncthing
sudo install -d -o syncthing -g syncthing /srv/backup
sudo -u syncthing syncthing -generate="/var/lib/syncthing/.config/syncthing"
sudo systemctl daemon-reload
sudo systemctl enable --now syncthing@syncthing.service
sudo systemctl status syncthing@syncthing.service --no-pager通过 SSH 隧道访问备份端面板时,为了避免和源端本地 8384 冲突,可以映射到本地 8385:
ssh -N -L 8385:127.0.0.1:8384 user@你的Ubuntu接收端IP浏览器打开:
http://127.0.0.1:8385如果使用 UFW,同样只放行同步端口:
sudo ufw allow 22000/tcp
sudo ufw allow 22000/udp
sudo ufw reload三、Alpine 备份端配置
1. 安装 Syncthing
apk update
apk add syncthing创建服务用户、配置目录和同步目录:
adduser -D -H -s /sbin/nologin syncthing
install -d -o syncthing -g syncthing /var/lib/syncthing
install -d -o syncthing -g syncthing /var/lib/syncthing/.config
install -d -o syncthing -g syncthing /srv/backup生成 Syncthing 配置:
su -s /bin/sh syncthing -c 'syncthing -generate="/var/lib/syncthing/.config/syncthing"'2. 配置 OpenRC 服务
Alpine 使用 OpenRC。创建 /etc/init.d/syncthing:
cat << 'EOF' > /etc/init.d/syncthing
#!/sbin/openrc-run
name="syncthing"
command="/usr/bin/syncthing"
command_user="syncthing:syncthing"
command_args="-home=/var/lib/syncthing/.config/syncthing -gui-address=127.0.0.1:8384 -no-browser -no-restart"
command_background="yes"
pidfile="/run/syncthing.pid"
depend() {
need net
}
EOF启动并加入默认运行级别:
chmod +x /etc/init.d/syncthing
rc-update add syncthing default
rc-service syncthing start
rc-service syncthing status确认进程用户和监听地址:
ps -eo pid,user,args | grep '[s]yncthing'
ss -tunlp | grep syncthingWeb GUI 应该只监听 127.0.0.1:8384。访问 Alpine 面板时建立隧道:
ssh -N -L 8385:127.0.0.1:8384 user@你的Alpine服务器IP然后浏览器打开:
http://127.0.0.1:8385如果 Alpine 侧启用了防火墙,只放行同步通信端口即可:
22000/tcp
22000/udp四、建立设备信任
分别打开两台机器的 Syncthing Web GUI。
在 B 机器,也就是 Ubuntu、Debian 或 Alpine 备份端:
- 点击
操作。 - 点击
显示 ID。 - 复制设备 ID。
回到 A 机器,也就是 Ubuntu 源端:
- 点击
添加远程设备。 - 粘贴备份端的设备 ID。
- 保持
地址为默认的dynamic。 - 保存。
然后回到备份端面板,等待连接请求弹出,点击 添加设备 接受 Ubuntu 源端。
远程设备的 地址 字段最容易填错。不要填 0.0.0.0:8384、127.0.0.1:8384 或 http://...:8384;这些都是 Web GUI 管理端口,不是设备同步地址。常规场景保留 dynamic 即可;如果要手动指定直连地址,应写成 tcp://公网IP:22000 这类同步端口地址。
如果两台机器都在公网 VPS 上,通常会自动发现并连接。如果连接不上,优先检查:
- 两端同步通信端口是否放行。
- 云厂商安全组是否也放行了对应端口。
- 两端时间是否准确,证书认证对系统时间比较敏感。
- 远程设备地址是否仍为
dynamic,或者是否写成了正确的tcp://...:22000。
五、配置单向同步目录
1. 源端设置为仅发送
在源端 Syncthing 面板中:
- 点击
添加文件夹。 文件夹路径填写/srv/backup。- 在
共享选项卡中勾选备份端。 - 在
高级选项卡中,将文件夹类型设置为仅发送 (Send Only)。 - 保存。
仅发送 的意思是:源端是权威端。源端新增、修改、删除会同步到对端,但对端本地改动不会被当成正常变更反向覆盖源端。
2. 备份端设置为仅接收
在备份端 Syncthing 面板中:
- 等待源端发来的共享目录提示。
- 点击接受。
- 本地路径填写
/srv/backup。 - 在
高级选项卡中,将文件夹类型设置为仅接收 (Receive Only)。 - 保存。
仅接收 的意思是:备份端只接收源端下发的数据。如果有人在备份目录里手动改文件,Syncthing 会把它标记为本地变更,而不是推回源端。
如果备份端目录里本来就手工放入了同名文件,仅接收 可能会显示本地变更。确认文件来自源端且内容一致后,可以在备份端文件夹菜单中执行 还原本地更改,让备份端重新接受源端状态。
六、验证同步
在源端创建测试文件:
date | sudo -u syncthing tee /srv/backup/syncthing-test.txt >/dev/null观察两端 Web GUI,等待状态变成 最新。然后在备份端检查:
cat /srv/backup/syncthing-test.txt
ls -lh /srv/backup/syncthing-test.txt文件属主应为 syncthing:syncthing。再测试删除同步:
sudo -u syncthing rm /srv/backup/syncthing-test.txt如果源端删除文件,备份端也会跟着删除。这个行为适合“镜像式备份”,但不适合“防误删归档”。如果担心源端误删同步到备份端,应额外在备份端配置快照、版本控制或定时归档。
1. 对比两端目录大小和文件数
当 Syncthing 面板显示远程设备和文件夹都是 最新,但当前速率是 0 B/s 时,不一定是没有传输成功,也可能是已经同步完成、没有新数据需要传。
可以分别在源端和备份端执行:
du -sh /srv/backup
find /srv/backup -type f | wc -l如果文件数有差异,再进一步对比文件相对路径和字节数:
find /srv/backup -type f -printf '%P %s\n' | sort两端都执行一次。如果源端的业务文件在备份端都存在,大小也一致,Syncthing 面板又显示 最新,就可以认为同步已经完成。
Alpine 默认的 BusyBox find 不支持 -printf。在 Alpine 备份端可以改用:
find /srv/backup -type f -exec ls -ln {} \; | sort或者安装 GNU findutils:
apk add findutils2. 小磁盘 VPS 的空间保护
Syncthing 会检查配置和数据库所在磁盘的可用空间。小盘 VPS 如果只剩几 GB,可能看到类似错误:
insufficient space on disk for database优先清理磁盘空间。如果确认剩余空间足够支撑 Syncthing 数据库,也可以在 Web GUI 中调整:
操作 -> 设置 -> 高级 -> 选项 -> 最小主目录可用磁盘空间把它从默认值调低,例如 1%。这只是放宽 Syncthing 的保护阈值,不会增加实际磁盘空间。
七、内网备份端的 RouterOS 端口映射与直连排查
如果备份端在家里或办公室内网,例如备份端 IP 是 10.20.20.8,而源端是公网 VPS,那么只在备份端系统里放行 22000 还不够。外网源端想通过 IPv4 直连内网备份端,前端路由器也要把 Syncthing 同步端口 NAT 到备份端。
如果两端已经通过公网 IPv6 直连,或者 Syncthing 面板里远程设备已经显示 TCP WAN / QUIC WAN 且状态为 已连接,可以不做 RouterOS IPv4 端口映射。端口映射主要是给“没有可用公网 IPv6、又不想走 relay”的 IPv4 场景准备的。
下面以 RouterOS 为例:
- WAN 接口:
pppoe-out1 - 备份端内网 IP:
10.20.20.8 - Syncthing 同步端口:
22000/tcp和22000/udp
1. RouterOS 添加 dstnat 端口映射
/ip firewall nat
add chain=dstnat in-interface=pppoe-out1 protocol=tcp dst-port=22000 action=dst-nat to-addresses=10.20.20.8 to-ports=22000 comment="Syncthing TCP to 10.20.20.8"
add chain=dstnat in-interface=pppoe-out1 protocol=udp dst-port=22000 action=dst-nat to-addresses=10.20.20.8 to-ports=22000 comment="Syncthing UDP to 10.20.20.8"如果你的 RouterOS 使用 dst-address-type=local 统一匹配本机公网地址,也可以按现有规则风格写成:
/ip firewall nat
add chain=dstnat dst-address-type=local protocol=tcp dst-port=22000 action=dst-nat to-addresses=10.20.20.8 to-ports=22000 comment="Syncthing TCP to 10.20.20.8"
add chain=dstnat dst-address-type=local protocol=udp dst-port=22000 action=dst-nat to-addresses=10.20.20.8 to-ports=22000 comment="Syncthing UDP to 10.20.20.8"两种写法选一种即可,不要重复建太多同类规则。
2. RouterOS 放行 forward
如果防火墙 forward 链最后有 drop all other forward,就需要确保端口转发流量在 drop 前被放行。
可以单独放行 Syncthing:
/ip firewall filter
add chain=forward in-interface=pppoe-out1 protocol=tcp dst-address=10.20.20.8 dst-port=22000 action=accept comment="Allow Syncthing TCP to 10.20.20.8"
add chain=forward in-interface=pppoe-out1 protocol=udp dst-address=10.20.20.8 dst-port=22000 action=accept comment="Allow Syncthing UDP to 10.20.20.8"如果已有类似下面这种通用规则,并且 pppoe-out1 已经在 WAN interface list 里,那么单独的 Syncthing filter 规则不是必须的:
/ip firewall filter
add chain=forward action=accept connection-nat-state=dstnat in-interface-list=WAN comment="Allow DSTNAT Port Forwarding"规则顺序很重要:放行规则必须在最后的 drop 规则前面。
3. 检查 RouterOS 规则
打印 NAT 和 filter 规则:
/ip firewall nat print detail without-paging
/ip firewall filter print detail without-paging检查 Syncthing 规则是否有命中计数:
/ip firewall nat print stats where comment~"Syncthing"
/ip firewall filter print stats where comment~"Syncthing"如果外部源端正在尝试连接,packets 和 bytes 应该会增长。只要 NAT 和 filter 计数在增长,说明 RouterOS 端口转发基本已经生效。
还要确认 WAN 口拿到的是公网 IPv4:
/ip address print where interface=pppoe-out1如果这里显示的是 10.x.x.x、100.64.x.x、172.16.x.x 到 172.31.x.x、192.168.x.x 这类地址,说明上游可能是内网或 CGNAT。此时 RouterOS 本机端口映射无法从公网直接生效,需要改用公网 IPv6、WireGuard、Tailscale、ZeroTier,或者继续使用 Syncthing relay。
4. 指定直连地址
如果备份端所在网络有公网 IPv4,并且 RouterOS 已经映射到 10.20.20.8:22000,可以在源端 Syncthing 里编辑备份端设备:
高级 -> 地址把 dynamic 改成:
tcp://你的公网IP:22000保存后暂停/恢复该远程设备,或者重启源端 Syncthing:
sudo systemctl restart syncthing@syncthing.service回到 Syncthing 主界面,点开远程设备详情,正常直连时连接类型应从:
中继广域网变成类似:
TCP WAN如果仍然显示 中继广域网,说明它还在走 relay。relay 能用,但速度通常很慢,初次同步几个 GiB 时会非常明显。
如果源端使用自定义同步端口,例如监听在 29029,那么对端手动地址应写成:
tcp://源端公网IP:29029不要把 Web GUI 端口 8384 写进设备地址。8384 只用于浏览器管理面板,不承载文件同步。
5. 在备份端确认是否已经直连
在备份端 10.20.20.8 上查看 Syncthing 连接:
ss -tunp | grep syncthing如果看到类似下面这类连接,说明外部源端已经通过 RouterOS 打到了备份端的 22000:
tcp ESTAB 0 0 10.20.20.8:22000 192.0.2.10:29029 users:(("syncthing",pid=2635,fd=22))这里的重点是本地端口为 10.20.20.8:22000,对端是源端公网 IP。对端端口不一定是 22000,这很正常。
如果看到的是类似下面这种:
tcp ESTAB 0 0 10.20.20.8:50454 101.132.255.222:22067 users:(("syncthing",pid=2635,fd=11))这通常是 relay 中继连接,不代表直连已经成功。
八、安全建议
- Syncthing 服务、配置目录和同步目录统一使用
syncthing:syncthing。 - Web GUI 只监听
127.0.0.1:8384,通过 SSH 隧道访问。 - 不要把
8384Web GUI 管理端口直接暴露到公网。 - 同步端口只开放给必要来源更稳妥,云安全组和系统防火墙都要检查。
- 源端使用
仅发送,备份端使用仅接收,不要配置成默认的双向同步。 - 对重要备份目录,建议在备份端再做快照或版本保留,避免误删被实时同步。