Mozilla Autopush-rs 部署与配置全攻略
目录
之前折腾 Mozilla 的推送服务,发现它的 Rust 实现版 Autopush-rs 挺有意思。它用了典型的“生产者-消费者”架构,底层是 Rust + Actix 加上 Redis 存储。这篇笔记是我在配置 autopush-rs 并和 Sunup 客户端集成时踩坑记录下来的,主要包括它的工作原理、配置参数和 Docker 部署细节,希望能帮到同样在折腾推送的你。
1. 架构原理与组件分工
Autopush-rs 的设计其实挺巧妙的,两端完全解耦,靠 Redis 来同步状态,最终把公网上的推送请求一路送到手机的私有长连接上。
1.1 服务组件分工
Autoconnect (WebSocket Server):
- 角色: 面向客户端(如 Sunup Android 客户端)。
- 功能: 建立并维护长连接,接收心跳,并将推送消息分发到设备。
- 默认端口:
8080(WebSocket),8081(内部路由端口)。
Autoendpoint (HTTP API):
- 角色: 面向应用服务器(如 Mastodon/Matrix 等发送通知的服务)。
- 功能: 接收标准 WebPush 请求,查询路由信息,并通知
autoconnect进行推送。 - 默认端口:
8000。
Storage (Redis/Valkey):
- 功能: 存储注册信息(Routers)和待发消息,并用于可靠性跟踪。
1.2 交互流程图 (Mermaid)
sequenceDiagram
participant App as 应用服务器 (Sender)
participant Endpoint as Autoendpoint (8000)
participant Redis as Redis 数据库
participant Conn as Autoconnect (8080/8081)
participant Client as Sunup 客户端 (手机)
Note over Client, Conn: 1. 建立长连接
Client->>Conn: 建立 WebSocket (8080)
Conn->>Redis: 注册 node_id (例如 http://autoconnect:8081)
Conn-->>Client: 返回 pushEndpoint (指向 Autoendpoint)
Note over App, Client: 2. 触发推送
App->>Endpoint: 发送 POST WebPush 请求 (8000)
Endpoint->>Redis: 查询用户的 node_id
Redis-->>Endpoint: 返回 http://autoconnect:8081
Note over Endpoint, Conn: 3. 内部下发
Endpoint->>Conn: 内部通知 (8081 HTTP)
Conn->>Client: 通过已有的 WS 连接下发消息
2. 核心配置说明
它的配置比较灵活,写在配置文件里或者直接挂环境变量都行。
2.1 Autoconnect 配置
| 选项 | 环境变量 | 类型 | 默认值 | 描述 |
|---|---|---|---|---|
| actix_max_connections | AUTOCONNECT__ACTIX_MAX_CONNECTIONS | 数字 | 无 | Actix Web 服务器的最大并发连接数 |
| actix_workers | AUTOCONNECT__ACTIX_WORKERS | 数字 | 无 | Actix Web 服务器每个绑定地址的工作线程数 |
| auto_ping_interval | AUTOCONNECT__AUTO_PING_INTERVAL | 数字 | 300 | 向客户端发送 ping 的时间间隔(秒) |
| auto_ping_timeout | AUTOCONNECT__AUTO_PING_TIMEOUT | 数字 | 4 | 等待客户端 ping 响应的时间(秒) |
| crypto_key | AUTOCONNECT__CRYPTO_KEY | 字符串 | 内部生成 | 用于端点加密的加密密钥 (32 字节 Base64) |
| db_dsn | AUTOCONNECT__DB_DSN | 字符串 | 无 | 后端数据库的数据源名称 |
| endpoint_hostname | AUTOCONNECT__ENDPOINT_HOSTNAME | 字符串 | “localhost” | 生成端点 URL 的公网主机名 |
| endpoint_port | AUTOCONNECT__ENDPOINT_PORT | 数字 | 8082 | 生成端点 URL 的公网端口覆盖值 |
| endpoint_scheme | AUTOCONNECT__ENDPOINT_SCHEME | 字符串 | “http” | 生成端点 URL 的方案 (http/https) |
| hostname | AUTOCONNECT__HOSTNAME | 字符串 | 无 | 机器主机名,用于内部路由注册 |
| human_logs | AUTOCONNECT__HUMAN_LOGS | 布尔值 | false | 是否使用人类可读的日志格式 |
| msg_limit | AUTOCONNECT__MSG_LIMIT | 数字 | 1000 | 每个客户端存储的最大消息数 |
| port | AUTOCONNECT__PORT | 数字 | 8080 | 应用程序监听的 WS 端口 |
| router_port | AUTOCONNECT__ROUTER_PORT | 数字 | 8081 | 节点间通信的内部路由端口 |
2.2 Autoendpoint 配置
**注意:**部分旧版文档中提到的 AUTOENDPOINT__ 前缀在当前版本中应修改为 AUTOEND__。
| 选项 | 环境变量 | 类型 | 默认值 | 描述 |
|---|---|---|---|---|
| scheme | AUTOEND__SCHEME | 字符串 | “http” | 端点 URL 方案 |
| host | AUTOEND__HOST | 字符串 | “127.0.0.1” | 监听主机 |
| port | AUTOEND__PORT | 数字 | 8000 | 监听端口 |
| db_dsn | AUTOEND__DB_DSN | 字符串 | 无 | 后端数据库数据源名称 |
| crypto_keys | AUTOEND__CRYPTO_KEYS | 字符串 | 内部生成 | 加密密钥列表 (逗号分隔) |
| auth_keys | AUTOEND__AUTH_KEYS | 字符串 | 无 | 身份验证密钥列表 (逗号分隔) |
| human_logs | AUTOEND__HUMAN_LOGS | 布尔值 | false | 是否使用人类可读日志 |
| max_notification_ttl | AUTOEND__MAX_NOTIFICATION_TTL | 数字 | 2592000 | 通知消息最大生存时间 (秒) |
3. 关键配置文件 (TOML 示例)
密钥可通过 openssl rand -base64 32 命令行生成。
3.1 autoconnect.toml
# --- 内部识别 (至关重要) ---
# 此 hostname 会存入 Redis。Autoendpoint 必须能通过此名称访问到本容器。
hostname = "autoconnect"
port = 8080
router_port = 8081
# --- 推送地址生成 (给手机客户端看) ---
endpoint_scheme = "https"
endpoint_hostname = "push-api.example.com"
endpoint_port = 443
# --- 存储与安全 ---
db_dsn = "redis://valkey:6379"
crypto_key = "[mqCGb8D-N7mqx6iWJov9wm70Us6kA9veeXdb8QUuzLQ=]"3.2 autoendpoint.toml
host = "0.0.0.0"
port = 8000
db_dsn = "redis://valkey:6379"
# 必须与 autoconnect 的 crypto_key 保持一致
crypto_keys = "[mqCGb8D-N7mqx6iWJov9wm70Us6kA9veeXdb8QUuzLQ=]"
scheme = "http"
human_logs = true4. 部署指南
4.1 Docker Compose 部署
---
# https://github.com/orgs/forkdo/packages?repo_name=autopush-rs
services:
autoendpoint:
container_name: autoendpoint
env_file:
- path: ./.env
required: false
hostname: autoendpoint
image: ghcr.io/forkdo/autoendpoint:latest
ports:
- 8000:8000
restart: unless-stopped
autoconnect:
container_name: autoconnect
env_file:
- path: ./.env
required: false
hostname: autoconnect
image: ghcr.io/forkdo/autoconnect:latest
ports:
- 8080:8080
restart: unless-stopped4.2 环境变量 (.env)
# CUSTOM
TZ=Asia/Shanghai
################################# autoendpoint 对应项 ###############
AUTOEND__HOST="autoendpoint"
AUTOEND__PORT=8000
AUTOEND__DB_DSN="redis://valkey:6379"
# 密钥需为随机 32 字节 Base64
# openssl rand -base64 32
AUTOEND__CRYPTO_KEYS="[CRYPTO_KEY]"
AUTOEND__AUTH_KEYS="[AUTH_KEY]"
AUTOEND__HUMAN_LOGS=true
########################## autoconnect 对应项 ############################
AUTOCONNECT__HOSTNAME="autoconnect"
AUTOCONNECT__PORT=8080
AUTOCONNECT__ROUTER_PORT=8081
# 外部应用可访问的配置
AUTOCONNECT__ENDPOINT_SCHEME="https"
AUTOCONNECT__ENDPOINT_HOSTNAME="push-api.example.com"
AUTOCONNECT__ENDPOINT_PORT=443
AUTOCONNECT__DB_DSN="redis://valkey:6379"
AUTOCONNECT__CRYPTO_KEY="[CRYPTO_KEY]"
AUTOCONNECT__HUMAN_LOGS=true
################################ Valkey ###################################
VALKEY_ARGS=--save 60 10004.3 Nginx 反向代理配置
location / {
proxy_pass http://127.0.0.1:8000; # 指向 Autoendpoint (API) 或 Autoconnect (WS)
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 3m;
proxy_send_timeout 3m;
proxy_read_timeout 3m;
client_max_body_size 0; # Stream request body to backend
}5. 踩坑与避坑指南
最后总结几条部署时最容易踩坑的地方:
- 域名别搞混了:
- WebSocket 域名 (
push.domain.com): 建议指向autoconnect的8080端口。 - Push API 域名 (
push-api.domain.com): 建议指向autoendpoint的8000端口。
- WebSocket 域名 (
- Hostname 陷阱:
autoconnect.toml里的hostname千万别写127.0.0.1。在 Docker 环境下直接填autoconnect容器服务名就行,否则autoendpoint根本连不上它。
- 密钥必须一致:
- 两边的配置里,
crypto_key(connect) 和crypto_keys(endpoint) 必须完全一致,不然鉴权会直接失败。
- 两边的配置里,
- 重启后的重连:
- 改完配置重启服务端后,记得把客户端(手机端)杀掉重新打开建立连接,让它刷新 Redis 里缓存的路由信息。
相关链接: