SipFlow Cluster Deployment

SipFlow is RustPBX’s built-in SIP+RTP signaling capture and replay system, supporting local mode and standalone cluster mode.

1. Feature Overview

CapabilityDescription
SIP signaling captureComplete SIP request/response messages
RTP media captureOptional, triggered by recording policy
WAV replayGenerate call recordings from RTP packets
Timeline viewerView complete signaling flow by call_id in the web console
S3/HTTP uploadUpload to object storage after call ends

2. Local Mode (Single Node)

2.1 Configuration

[sipflow]
[sipflow.local]
subdirs = "daily"          # none / daily / hourly
flush_count = 100          # Flush to disk every 100 packets
flush_interval_secs = 5    # Max 5 seconds between flushes
id_cache_size = 10000      # Call-ID cache size

2.2 Storage Structure

sipflow/
├── 20260526/
│   ├── 20260526.sqlite     # Metadata index
│   └── 20260526.raw        # Raw packets (zstd compressed)
├── 20260527/
│   ├── 20260527.sqlite
│   └── 20260527.raw
  • *.sqlite: each record contains call_id, timestamp, source/destination IP/port, SIP method
  • *.raw: binary packet data, zstd compressed

2.3 RTP Recording Generation

Generate WAV from captured data:

GET /api/sipflow/media?call_id=xxx&start=0&end=3600&format=wav

Supports PCMU, PCMA, G722, L16 codec to WAV conversion.

2.4 Upload Configuration

Automatic upload after call ends:

[sipflow.upload]
type = "s3"
bucket = "sipflow-archives"
region = "us-east-1"
endpoint = "https://s3.amazonaws.com"
access_key = "AKIA..."
secret_key = "secret..."

# Or upload via HTTP
# [sipflow.upload]
# type = "http"
# url = "https://api.example.com/sipflow/upload"

3. Standalone Cluster Mode

For multi-node deployments, SipFlow can be deployed as a standalone service with consistent hash routing.

3.1 Architecture

┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│  RustPBX    │  │  RustPBX    │  │  RustPBX    │
│  Node 1     │  │  Node 2     │  │  Node 3     │
└──────┬──────┘  └──────┬──────┘  └──────┬──────┘
       │                │                │
       │   UDP packets + HTTP queries    │
       ▼                ▼                ▼
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│  SipFlow    │  │  SipFlow    │  │  SipFlow    │
│  Server A   │  │  Server B   │  │  Server C   │
│  :3000/3001 │  │  :3000/3001 │  │  :3000/3001 │
└─────────────┘  └─────────────┘  └─────────────┘
  • RustPBX nodes select a SipFlow Server via call_id consistent hashing
  • Each SipFlow Server stores data independently
  • Queries are automatically routed to the correct server

3.2 SipFlow Server Deployment

SipFlow Server is a standalone binary (sipflow), compiled from the RustPBX source:

cargo build --release --bin sipflow

Launch parameters:

/static/docs/addons/sipflow \
  --addr 0.0.0.0 \
  --port 3000 \           # UDP receive port
  --http-port 3001 \      # HTTP API port
  --root /data/sipflow \  # Storage directory
  --flush-count 200 \     # Flush packet count
  --flush-interval 5 \    # Flush interval seconds
  --buffer-size 65536     # UDP receive buffer

Docker deployment:

docker run -d --name sipflow-a \
  -v /data/sipflow:/data/sipflow \
  -p 3000:3000/udp -p 3001:3001 \
  docker.cnb.cool/miuda.ai/rustpbx:latest \
  /app/sipflow --addr 0.0.0.0 --port 3000 --http-port 3001 --root /data/sipflow

3.3 SipFlow Server HTTP API

EndpointMethodDescription
/healthGETHealth check
/flowGETQuery SIP signaling (callid, start, end parameters)
/mediaGETGenerate WAV recording (callid, start, end, format parameters)

3.4 RustPBX Node Configuration

Each RustPBX node configures the SipFlow remote backend:

[sipflow]
[sipflow.remote]
flush_interval_secs = 5

[[sipflow.remote.nodes]]
udp = "10.0.1.1:3000"
http = "http://10.0.1.1:3001"

[[sipflow.remote.nodes]]
udp = "10.0.1.2:3000"
http = "http://10.0.1.2:3001"

[[sipflow.remote.nodes]]
udp = "10.0.1.3:3000"
http = "http://10.0.1.3:3001"

Routing rules:

  • Write: hash(call_id) % node_count → select target server, send via UDP
  • Query: same hash routing to the correct server, HTTP GET request

3.5 Consistent Hashing

SipFlow uses simple modulo hashing (not a consistent hash ring):

  • When adding/removing nodes, approximately 1/N of call_ids will change routing
  • Recommend determining node count during planning to avoid frequent changes
  • After node changes, querying historical data may require per-node traversal

4. Web Console Viewer

Console → Call Records → Click Call → SIP Flow:

Click any call in the CDR list to view the complete SIP signaling timeline:

  • Timing of each SIP message
  • Request/response pairing
  • RTP stream information
  • Playable call recordings

5. Storage Planning

5.1 Disk Space Estimation

Data TypeSize per Call10K calls/day/month
SIP signaling~5 KB~150 MB
RTP media (optional)~50-200 KB~1.5-6 GB
SQLite index~500 B~15 MB

5.2 Retention Policy

Recommend cleaning expired data via a scheduled task:

# Delete data older than 90 days
find /data/sipflow -maxdepth 1 -type d -name "20*" -mtime +90 -exec rm -rf {} \;

Or configure upload to S3 with automatic local cleanup.

6. Network Requirements

PortProtocolPurpose
3000UDPRustPBX → SipFlow packet transport
3001HTTPRustPBX → SipFlow query API

RustPBX nodes must be able to reach all SipFlow Server UDP and HTTP ports.

7. Recording Policy vs SipFlow

SipFlow capture and call recording are independent:

ConfigurationDescription
[recording]Call recording (WAV/MP3)
[sipflow]Signaling capture (SIP+RTP packets)
  • SipFlow RTP capture follows the recording policy (only captures RTP for recorded calls)
  • SIP signaling is always captured (regardless of recording)
  • SipFlow-generated WAV can serve as a recording backup