Cluster Deployment
RustPBX supports multi-node clustering for registration state synchronization, distributed SipFlow capture, and cross-node call control.
1. Architecture Overview
┌──────────────┐
│ Load Balancer│
│ (SIP/HTTP) │
└──────┬───────┘
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Node 1 │ │ Node 2 │ │ Node 3 │
│ SIP+HTTP │◄─► SIP+HTTP│◄─► SIP+HTTP│
│ SipFlow │ │ SipFlow │ │ SipFlow │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└───────────┼───────────┘
▼
┌──────────────┐
│ MySQL/PgSQL │
└──────────────┘
Key capabilities:
- Inter-node event sync via SIP MESSAGE for registration/presence
- SipFlow supports consistent hashing by
call_idto route to specific capture nodes - Shared database (MySQL/PostgreSQL) ensures config and CDR consistency
2. Database Requirements
Cluster mode does not support SQLite — a shared database is required:
| Database | Min Version | Recommended | Notes |
|---|---|---|---|
| MySQL | 8.0+ | 8.4 LTS | Charset utf8mb4, collation utf8mb4_unicode_ci |
| PostgreSQL | 14+ | 16 | Enable pg_stat_statements for monitoring |
Connection string examples:
# MySQL
database_url = "mysql://rustpbx:password@10.0.0.100:3306/rustpbx"
# PostgreSQL
database_url = "postgres://rustpbx:password@10.0.0.100:5432/rustpbx"
Important notes:
- All nodes must connect to the same database instance
- SeaORM auto-runs migrations on first startup; subsequent nodes detect and skip completed migrations
- DDL files in the source root (
rustpbx_ddl_*.sql) are available for manual schema creation
3. Cluster Configuration
3.1 Inter-Node Event Sync
Configure peer nodes in [cluster] section of config.toml:
[cluster]
peers = [
{ addr = "10.0.0.2", sip_port = 5060, ami_port = 8080 },
{ addr = "10.0.0.3", sip_port = 5060, ami_port = 8080 },
]
Each node only lists the other nodes — do not include itself. Nodes exchange JSON events via SIP MESSAGE (application/x-rustpbx-cluster-event).
Synced event types:
- Locator events: user registration/unregistration state
- Presence events: user online/offline/busy status
3.2 SipFlow Cluster Mode
[sipflow]
[sipflow.remote]
flush_interval_secs = 5
[[sipflow.remote.nodes]]
udp = "10.0.0.2:6060"
http = "http://10.0.0.2:6060"
[[sipflow.remote.nodes]]
udp = "10.0.0.3:6060"
http = "http://10.0.0.3:6060"
- Each proxy node can read and write; requests are routed by
call_idconsistent hashing - Deploy the standalone
sipflowbinary (fromsrc/bin/sipflow.rs) as the capture server
3.3 Core Config Per Node
http_addr = "0.0.0.0:8080"
database_url = "mysql://rustpbx:password@dbhost:3306/rustpbx"
external_ip = "10.0.0.1"
[proxy]
addr = "0.0.0.0"
udp_port = 5060
modules = ["acl", "auth", "registrar", "call", "presence"]
media_proxy = "auto"
[console]
session_secret = "your-secret-here" # Must be identical across all nodes
4. Load Balancing
4.1 SIP Traffic
Use a SIP Load Balancer (OpenSIPS, Kamailio) or DNS SRV:
- Source IP hash: ensures REGISTER messages from the same user reach the same node (reduces cross-node sync)
- Call-ID hash: ensures signaling for the same call stays on the same node
4.2 HTTP Traffic
Use Nginx/HAProxy reverse proxy:
upstream rustpbx {
ip_hash; # Session affinity
server 10.0.0.1:8080;
server 10.0.0.2:8080;
server 10.0.0.3:8080;
}
5. Deployment Steps
# 1. Prepare shared database
mysql -u root -p -e "CREATE DATABASE rustpbx CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
# 2. Deploy on each node
docker pull docker.cnb.cool/miuda.ai/rustpbx:0.4.5
# 3. Node 1 (10.0.0.1)
docker run -d --name rustpbx \
-v $(pwd)/config.toml:/app/config.toml \
-v $(pwd)/config:/app/config \
-p 8080:8080 -p 5060:5060/udp \
docker.cnb.cool/miuda.ai/rustpbx:0.4.5
# 4. Node 2/3: same steps, adjust external_ip and cluster.peers
6. Operations
- Database connection pool: each node’s default pool is managed by SeaORM; total
nodes × pool_sizemust not exceed databasemax_connections - Time sync: all nodes must use NTP — CDR timestamps depend on system clocks
- Config consistency:
config/trunks/,config/routes/etc. should be synced to all nodes via shared storage or GitOps - Rolling restart: restart nodes one at a time, ensuring at least one node remains online
- SipFlow storage: plan disk capacity per capture node independently (~50-200KB signaling data per call)