把 Relayium 变成常驻接收服务
最近更新: 2026-08-06
relayium serve --once 只处理一次传入的传输就退出——适合偶尔拉取一次的场景。但如果你想让某台机器成为一个常驻的落地点——一台每晚接收备份的家庭服务器、一台 CI 会推送构建产物的构建机、一台随时能接收手机照片的 NAS——你会想让 serve 一直运行,而不是每次传输都手动启动它。
本指南涵盖启动一个长期运行的监听端、批准谁可以向它推送、为没有人守在终端前的场景预先授权对端、在 systemd 下运行它,以及让使用 sync --delete 的发送方镜像删除操作。
开始之前
下面用到的都是 relayium CLI,所以没装的话先装上。在 macOS 或 Linux 上,一条命令就能把预编译二进制放进你的 PATH:
curl -fsSL https://relayium.com/install.sh | sh
- 想自己挑文件,或在 Windows 上?从发布页下载二进制——relayium.com/cli 列出了所有安装方式(装了 Go 也可 go build -o relayium ./cmd/relayium)。
- relayium --version 可确认是否装好。不装这一步,下面的命令只会报 “command not found”。
启动监听端
开始之前你需要什么
- 两台机器上都装好 CLI。relayium version 会各自打印版本号;如果 shell 回答 command not found,说明那台还没装。
- 本机上一个用来接收文件的目录,以及装得下这些文件的磁盘空间。
- 一个发送方能访问到的地址,和一个放通的入站端口。不指定 --port 时 serve 监听 9031。
- 如果这台机器将来是没有终端运行的——那正是做成服务的意义——你需要事先拿到推送方的指纹。下面有专门一节讲这个,而它正是常驻接收端把一切都拒掉的最常见原因。
serve 通过证书固定的 TLS 1.3 连接监听 daemon 直连推送(relayium://host:port),并把收到的内容写入某个目录。启动它不需要预先共享任何东西——不用复制指纹,也不用注册服务器:
relayium serve --dir ~/inbox
relayium serve --dir /srv/drop --port 9040 # 非默认端口
relayium serve --dir ~/inbox --allow-delete # 允许使用 sync --delete 的发送方镜像删除操作
选好文件落地的位置,把监听器起起来。走到这一步不需要预先交换任何东西。
relayium serve --dir ~/inbox在发送方机器上,按 relayium:// 地址往这台主机推一个文件。
relayium push ./report.pdf relayium://drop.example.com:9031回到接收端,回答那个批准提示。按 y 会把该指纹写入 authorized_fingerprints,之后同一台机器再推就不会再问了。
确认文件真的落在了 --dir 里,而不是你启动 serve 时所在的那个目录。
ls -l ~/inbox
一个正常的监听器长什么样
serve 一上来就会说明自己还没有已授权的对端,然后在新机器第一次推送时提示,此后每一次都安安静静。发送方退出码 0,文件出现在 --dir 里。
$ relayium serve --dir ~/inbox
no authorized peers yet — you'll be asked to approve each new peer on its first push.
Incoming push from 203.0.113.7:54021
fingerprint: 74318e3b…
Accept and remember this peer? [y/N] y- --dir 设置文件落地的位置(默认是当前目录)。
- --port 设置监听端口(默认是 9031);如果发送方在别处,需要在防火墙上开放该端口。
- 不加 --once 时,serve 会持续运行并接受推送,直到你手动停止它,或者由进程管理器重启它——这正是它能成为常驻服务的原因。
批准谁可以推送
当一个新的对端第一次推送时,如果 serve 运行在终端中,它会显示这次推送来自哪里、它的指纹,并请你批准——就像 SSH 首次连接未知主机时会询问一样:
Incoming push from 203.0.113.7:54021
fingerprint: 74318e3b…
Accept and remember this peer? [y/N] y
- 回答一次 y,该指纹就会被写入 authorized_fingerprints;此后同一台机器的每次推送都会直接通过,不再提示。
- 指纹标识的是一台机器,而不是一个网络地址,因此即使发送方的 IP 变化,它依然有效。
- 这一步是交互式的,刻意如此——需要有人守在键盘前,而一旦 serve 迁移到 systemd(下一步),这就不成立了。
为非交互式场景预先授权对端
当 serve 没有终端可以弹出提示时——作为 systemd 服务、后台进程,或通过管道运行——它无法询问,因此会拒绝任何它尚未识别的指纹。这时应该提前授权对端。在将要推送的那台机器上运行 relayium id 打印它的指纹;在接收方上,在第一次推送到达之前把它加进去:
# 在将要推送的那台机器上:打印它的指纹
relayium id
# 在这台常驻接收机上:预先授权它
relayium authorize 74318e3b...
在将要推送的机器上打印它的指纹。它是 64 位十六进制,标识的是那台机器而不是它的地址。
relayium id在这台接收端上授权它——要用服务将来运行时相同的 --config-dir。用错用户执行、或者这边用默认路径而 unit 里用的是另一个,指纹就会写进服务永远不会读的那个文件里。
relayium authorize 74318e3b… --config-dir /etc/relayium
- authorize 是幂等的——对一个已经信任的指纹再次运行它不会有任何效果。
- 身份和信任文件存放在 --config-dir 指定的目录下,默认是 ~/.config/relayium(id.key/id.crt 是这台主机的身份,authorized_fingerprints 是对端允许列表)。
在 systemd 下运行
如果希望服务能在重启和崩溃后依然存活,把 serve 交给 systemd。把 --config-dir 指向一个固定路径,让主机的身份和它的对端允许列表在重启之间保持不变:
# /etc/systemd/system/relayium-serve.service
[Unit]
Description=Relayium always-on receiver
After=network-online.target
[Service]
ExecStart=/usr/local/bin/relayium serve --dir /srv/drop --port 9031 --config-dir /etc/relayium --allow-delete
Restart=always
User=relayium
[Install]
WantedBy=multi-user.target
在服务存在之前,先授权每一个应该能推送的对端。服务无法弹提示,凡是不在信任列表里的一律拒绝。
把上面那份 unit 文件写到 /etc/systemd/system/relayium-serve.service,其中 --config-dir 要指向你刚才授权时用的那个固定路径。
重新加载 systemd 并启动服务,同时设为开机自启,这样重启后还会回来。
sudo systemctl daemon-reloadsudo systemctl enable --now relayium-serve确认它在运行,并且日志里没有那条「全部拒绝」的警告。两者之中只有后一条是这个场景特有的。
systemctl is-active relayium-servejournalctl -u relayium-serve -n 20 --no-pager
一个正常的服务长什么样
is-active 回答 active,并且启动时那条「没有已授权对端」的警告不出现。这条警告是唯一一行能在任何发送方抱怨之前就告诉你:这个服务会拒掉每一次推送。
$ systemctl is-active relayium-serve
active
$ journalctl -u relayium-serve -n 20 --no-pager | grep -c 'all pushes will be rejected'
0- 在启用该服务之前,先为每一个应该能够推送的对端运行 relayium authorize <fingerprint>——服务本身无法弹出提示。
- systemctl enable --now relayium-serve 会启动它,并让它在每次开机时自动恢复运行。
- /etc/relayium/id.key 的权限必须恰好是 0600,属主是 unit 里 User= 指定的用户。其他任何值 relayium 都拒绝加载——包括 0400,所以把它加固到比 0600 更严,和让它全局可读一样会让服务起不来。
在 macOS 上开机自启(launchd)
macOS 没有 systemd——它的服务管理器是 launchd。要让 serve 在 Mac 上常驻(比如一台常开、当落地点用的 Mac mini),把它装成 LaunchDaemon,这样开机即启动、无需任何人登录。设置 UserName 让它以你自己的身份(而非 root)运行,并给 --dir 和 --config-dir 绝对路径,这样它的身份和信任文件仍留在你自己的 ~/.config/relayium 里:
<!-- /Library/LaunchDaemons/com.relayium.serve.plist (replace YOU with your macOS username) -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key> <string>com.relayium.serve</string>
<key>UserName</key> <string>YOU</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/relayium</string>
<string>serve</string>
<string>--dir</string> <string>/Users/YOU/inbox</string>
<string>--port</string> <string>9031</string>
<string>--config-dir</string> <string>/Users/YOU/.config/relayium</string>
<string>--allow-delete</string>
</array>
<key>RunAtLoad</key> <true/>
<key>KeepAlive</key> <true/>
<key>StandardOutPath</key> <string>/Users/YOU/relayium-serve.log</string>
<key>StandardErrorPath</key> <string>/Users/YOU/relayium-serve.log</string>
</dict>
</plist>
# 1) authorize each pusher first — launchd gives serve no terminal to prompt on:
relayium authorize <fingerprint> # get the fingerprint from the pusher's relayium id
# 2) save the plist above to that path, then load it (root-owned, starts at boot):
sudo chown root:wheel /Library/LaunchDaemons/com.relayium.serve.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.relayium.serve.plist
# check it's running / follow logs / stop it:
sudo launchctl print system/com.relayium.serve | grep state
tail -f ~/relayium-serve.log
sudo launchctl bootout system/com.relayium.serve
- launchd 不给 serve 终端,所以它无法弹出提示——请先为每个推送方运行 relayium authorize <fingerprint>,跟 systemd 一样。指纹来自那台机器的 relayium id。
- KeepAlive 会在 serve 崩溃时把它重新拉起;RunAtLoad 加上放在 /Library/LaunchDaemons 的 LaunchDaemon,会在开机时(无需登录)启动它——正适合一台无人值守的 Mac mini。
- 想要登录级的服务?把同一份 plist(去掉 UserName 键)放到 ~/Library/LaunchAgents/,用 launchctl bootstrap gui/$(id -u) <path> 加载——它会在你登录时启动,而不是开机时。
- 如果开了 macOS 应用防火墙,请允许 relayium 的传入连接(系统设置 → 网络 → 防火墙),否则发往你端口的推送会被拦截。
让 sync --delete 的发送方镜像删除操作
默认情况下,serve 只会新增或更新文件——即使发送方对它运行 sync --delete,新增和修改过的文件依然会被复制,但它请求的删除操作会被跳过,接收方会记录一条警告。用 --allow-delete 启动 serve 即可选择启用真正的镜像同步,让发送方那边删除的文件在这里也被删除:
relayium serve --dir /srv/mirror --allow-delete
- --allow-delete 是接收方一侧的选择性开关;发送方仍然需要用 sync --delete 主动请求删除。
- 如果不加这个选项,无论发送方请求什么,这台机器上都不会删除任何文件。
出问题时怎么办
这五种里有四种会让服务照常运行、看着一切健康——一个把所有请求都拒掉的监听器,也仍然是个监听器。每一种都有一行可读的输出或一条可跑的命令来判定。
现象、检查、修复
- 服务起来了也一直在跑,但每一次推送都被拒绝。
journalctl -u relayium-serve -n 20 --no-pager # warning: no authorized peers and no terminal to approve on; all pushes will be rejected.服务没有终端,所以它永远跑不了首次推送的批准提示,而它能看到的只有一个陌生指纹。请事先授权每个发送方:在发送方跑 relayium id,在这边跑 relayium authorize <指纹>——并且要用 unit 里那个 --config-dir。这条警告是启动时打印的,所以它从日志第一行起就在那里。
- 服务压根起不来,报 id.key 权限不安全。
stat -c '%a %U %n' /etc/relayium/id.key # 400 relayium /etc/relayium/id.key私钥权限必须恰好是 0600。不能是 0644,而且——这一点最容易踩——也不能是 0400,所以把它「加固得更严」和「放得更松」一样会让服务起不来。给它 chmod 600,并确认属主是 unit 里 User= 指定的那个用户。
- 发送方报告连接被拒绝。
relayium push ./build relayium://drop.example.com:9031 # hint: if the peer refused the connection, it may not have authorized this host.接收端不认识这个发送方。在发送方跑 relayium id,把那个指纹在接收端 relayium authorize 一下。如果你已经做过了,那就检查是不是在 unit 的 --config-dir 下做的:信任文件是按目录存的,授权进 ~/.config/relayium 的指纹,对一个读 /etc/relayium 的服务来说根本不存在。
- 手动跑 serve 时推送正常,走服务就不行,或者换一台机器就不行。
sudo ss -tlnp | grep 9031两个不同的原因,一条检查就能分开。如果根本没有监听,说明 unit 没有 enable——用 systemctl is-enabled relayium-serve 确认。如果在监听,那就是端口被挡了:在主机防火墙和云安全组里放通 9031。用了非默认 --port 的话,它必须和发送方 relayium://host:N 里的端口一致。
- sync --delete 发送方要求的删除在这台机器上从不发生。
journalctl -u relayium-serve | grep -i delete删除是接收端的显式选项,默认关闭:新增和变更的文件照常复制,每一次被跳过的删除都会在这边记一条警告。在 unit 的 ExecStart 上加 --allow-delete 再重启。光是发送方要求并不够,而这种不对称是刻意的——接收端不会因为别处敲了一个参数就丢文件。
常见问题
serve 默认监听哪个端口?
9031。可以用 --port 同时修改监听端(serve --port N)和推送方的目标地址(relayium://host:N)。
我必须手动批准每一次推送吗?
只需要批准某个指纹的第一次推送,而且仅当 serve 是在带终端的环境下运行时才会提示。此后它会被记住。如果 serve 以非交互方式运行(systemd、管道),就完全不会出现提示,而是直接拒绝未知对端——这时应改为用 relayium authorize 预先授权它们。
发送方可以删除我这台常驻接收机上的文件吗?
只有当你以 --allow-delete 启动了 serve,并且发送方在运行 sync --delete 时才可以。如果没有 --allow-delete,删除操作会被静默跳过,其余内容照常传输。
运行一个常驻接收服务是免费的吗?
是的。relayium serve 是免费、可自托管的 CLI 的一部分——连接的任何一方都不需要账号,也没有付费档位。
serve 把身份和对端列表存在哪里?
默认在 ~/.config/relayium 中(id.key/id.crt 是这台主机的身份,authorized_fingerprints 是允许列表)。对于 systemd 服务,可以把 --config-dir 指向一个固定位置,例如 /etc/relayium。
在 macOS 上怎么让 serve 开机自启?
macOS 没有 systemd——用 launchd。把 serve 装成 /Library/LaunchDaemons 里的 LaunchDaemon(开机启动;设置 UserName 以你的身份运行),或 ~/Library/LaunchAgents 里的 LaunchAgent(登录时启动)。本指南给了一份可直接改的 plist;没有 Homebrew 服务。由于 launchd 不给 serve 终端弹提示,请先用 relayium authorize 预先授权推送方。
把你拥有的任何一台机器变成一个免费的常驻接收方——通过证书固定的 TLS 直接推送,不经过任何中继。
获取 CLI