Self-hosted E2EE relay for RunMon: stores and forwards ciphertext between agents and phone apps.
Project description
RunMon Relay
RunMon 的自托管中转服务 —— 在 GPU 服务器上的 agent 和手机 App 之间转发端到端加密的密文。
服务器和手机都不需要公网 IP,双方各自出站连到 relay;relay 是唯一有公网地址的一方,且只存密文 —— 被入侵也读不到你的训练日志。转发的是几 KB 级的加密文本 + 心跳,1 核 1G 绰绰有余。
大多数人不需要自建:
mon pair默认会用一个公共体验中转,直接就能上手。只有你想让数据完全走自己的服务器时,才需要下面这套。
先分清:本机试跑 vs 生产部署
只想在本机跑一下看看 —— 一条命令就够:
pip install runmon-relay
python -m runmon_relay --host 127.0.0.1 --port 8080
但这样它只监听本机、只有明文 HTTP,手机和别的服务器连不进来。要真正给 agent 和手机用,必须做下面的生产部署 —— 因为客户端连的是 WSS(加密 WebSocket),而 relay 自己不管 TLS,得靠前面的 nginx。
三句话概括生产部署:relay 跑在本机 8080(明文)→ nginx 在 443 做 TLS 终止 + WebSocket 反代 → certbot 签证书 → systemd 保证它一直活着。
生产部署(5 步)
前提
- 一台有公网 IP 的服务器(agent 和手机都往它连)
- 一个你能改 DNS 的域名
- 服务器已装
python3(≥3.10)、nginx、certbot(certbot+python3-certbot-nginx)
1. 装 relay 到独立目录
用一个专门的 venv 和服务账号,和系统 Python 隔离:
sudo useradd -r -s /usr/sbin/nologin runmon # 服务账号(推荐,权限最小)
sudo mkdir -p /opt/runmon-relay
sudo python3 -m venv /opt/runmon-relay/venv
sudo /opt/runmon-relay/venv/bin/pip install runmon-relay
sudo chown -R runmon:runmon /opt/runmon-relay
2. 用 systemd 常驻
下载现成的单元文件(已内置 MemoryMax=300M,适合小内存机器,崩了自动重启):
sudo curl -fsSL https://raw.githubusercontent.com/murphy977/runmon/main/relay/deploy/runmon-relay.service \
-o /etc/systemd/system/runmon-relay.service
sudo systemctl daemon-reload
sudo systemctl enable --now runmon-relay
systemctl status runmon-relay # 应为 active (running)
curl http://127.0.0.1:8080/health # 应返回 {"ok":true}
到这里 relay 已经在本机 127.0.0.1:8080 跑起来了,但还只有本机能访问。
3. DNS 加一条 A 记录
把一个子域名指向服务器公网 IP:
mon.example.com A 你的服务器IP
等它生效(dig mon.example.com 能解析到你的 IP)再往下走 —— certbot 签证书需要域名先解析得到。
4. nginx 反向代理
下载现成模板,关键是它带了 WebSocket upgrade 头 —— agent 和手机的长连全靠它,漏了会 404:
sudo curl -fsSL https://raw.githubusercontent.com/murphy977/runmon/main/relay/deploy/nginx-example.conf \
-o /etc/nginx/sites-available/runmon-relay.conf
sudo sed -i 's/mon.example.com/mon.你的域名.com/g' /etc/nginx/sites-available/runmon-relay.conf
sudo ln -s /etc/nginx/sites-available/runmon-relay.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
5. certbot 签 HTTPS 证书
sudo certbot --nginx -d mon.example.com
certbot 会自动往 nginx 配置里填证书路径、加上 80→443 跳转,并设置自动续期。
验证
curl https://mon.example.com/health # 应返回 {"ok":true}
返回 {"ok":true} 就成了。之后让用户配对时指定你的地址:
mon pair --relay https://mon.example.com
Cloudflare / CDN 注意
如果你的域名套了 Cloudflare 等 CDN(橙云代理),它可能会拦掉默认 UA 的 WebSocket 升级请求,导致连不上。RunMon 的 agent 已内置 User-Agent: runmon/x.y.z 绕过这个问题;但如果你自己写别的客户端或调试,记得带上非默认 UA。回源要走 443(Full/Strict SSL 模式)。
安全说明
- 经 relay 的业务数据全部 ChaCha20-Poly1305 密文,密钥只在 agent 和 App 两端,relay 只做存储转发,被入侵也只见密文。
- 设备 token 只存哈希;配对码一次性、限时。
- relay 建议只监听
127.0.0.1(如上),公网入口统一由 nginx 收口,别把--host 0.0.0.0直接暴露到公网。
这个包不是日常入口
日常在 GPU 服务器上用的是 agent 那个包:
pip install runmon
完整介绍、手机 App 下载和快速开始见 项目主页 和 GitHub 仓库。
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file runmon_relay-1.0.2.tar.gz.
File metadata
- Download URL: runmon_relay-1.0.2.tar.gz
- Upload date:
- Size: 10.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb4dda3bce3000d441c942e6d7be5be61df787d3309a7e15fd6f5deedea60bd6
|
|
| MD5 |
7295c77c051faa65b95c557a2d3bf7c5
|
|
| BLAKE2b-256 |
5ceb54d82266f2738668625abb7fe8f632c8d8115b0739cb25bdac70e1ab075a
|
File details
Details for the file runmon_relay-1.0.2-py3-none-any.whl.
File metadata
- Download URL: runmon_relay-1.0.2-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2837b96224a1e86f899bf9e5ff88ae4d963aa6826b477435c5ee625de931202
|
|
| MD5 |
e4daa4a4e13ae4945f18be4c7744fa7a
|
|
| BLAKE2b-256 |
5d8c700191e4e3f6ff3ff246811837cd0fbe07546fb0489973149ff73da2e190
|