rustpbx 0.3.16

A SIP PBX implementation in Rust
Documentation
# A example config file
# mv config.toml.example config.toml
# cargo run . --bin rustpbx --conf config.toml

http_addr = "0.0.0.0:8080"
# http_gzip = true
log_level = "debug"
#log_file = "/tmp/rustpbx.log"
# Paths can include a trailing * to skip whole subtrees
# http_access_skip_paths = ["/health", "/metrics*"]
media_cache_path = "./config/mediacache"
# SQLite database (default)
database_url = "sqlite://rustpbx.sqlite3"
# MySQL database example:
# database_url = "mysql://root@localhost:3306/rustpbx"

# external IP address for SIP signaling and media
# if server is behind NAT, set your public IP here (without port)
# external_ip = "1.2.3.4"

# rtp_start_port = 20000
# rtp_end_port = 30000

# setup your STUN/TURN servers here, for webrtc web clients
# [[ice_servers]]
# urls = ["stun:stun.l.google.com:19302"]

# [[ice_servers]]
# urls = ["turn:restsend.com:3478"]
# username = "user"
# credential = "pass"

[console]
#session_secret = "please_change_me_to_a_random_secret"
base_path = "/console"
# allow self-service administrator signup after the first account
allow_registration = false
# set to true to force Secure cookie attribute, otherwise it is auto-detected based on request
secure_cookie = false

[proxy]
modules = ["acl", "auth", "presence", "registrar", "call"]
addr = "0.0.0.0"
udp_port = 15060
registrar_expires = 60
ws_handler= "/ws"
media_proxy = "auto"
# Base directory for generated routing/trunk/ACL files
generated_dir = "./config"
routes_files = ["config/routes/*.toml"]
trunks_files = ["config/trunks/*.toml"]
addons = ["acme", "wholesale"]
# Don't responed the request when user not existed (slience for spam scanner)
ensure_user = true

# ACL rules
acl_rules = [
    # "allow 10.0.0.0/8",
    # "deny 0.123.4.0/16",
    "allow all",
    "deny all"
]
acl_files = ["config/acl/*.toml"]

[[proxy.user_backends]]
type = "memory"
users = [
    { username = "bob", password = "123456" },
    { username = "alice", password = "123456" },
]

[[proxy.user_backends]]
type = "extension"

[recording]
enabled = true
auto_start = true

[callrecord]
type = "local"
root = "./config/cdr"

# SipFlow: Unified SIP+RTP recording system
# [sipflow]
# type = "local"
# root = "./config/sipflow"
# subdirs = "daily"  # "none" | "daily" | "hourly"

# Local: SQLite + structured file (default settings)
# type = "local"
# root = "./config/sipflow"
# flush_count = 1000
# flush_interval_secs = 5
# id_cache_size = 8192

# Remote
# type = "remote"
# udp_addr = "192.168.1.100:3000"
# http_addr = "http://192.168.1.100:3001"
# timeout_secs = 10

# Ringback tone configuration
# [dialplan.ringback]
# Ringback mode: "local" | "passthrough" | "auto" | "none"
# - local: Always play local ringback file (ignore callee early media)
# - passthrough: Always forward callee's early media (silent if no early media)
# - auto: Smart selection - passthrough if early media exists, otherwise play local (default)
# - none: Disable ringback (standard 180 Ringing, no audio)
# mode = "auto"

# Local ringback audio file (used in local and auto modes)
# Supports WAV, MP3, raw audio formats, and HTTP/HTTPS URLs
# audio_file = "/sounds/company_ringback.mp3"
# audio_file = "https://cdn.example.com/ringback.wav"

# Whether to loop the ringback audio (default: true)
# loop_playback = true

# Whether to wait for ringtone playback completion (default: false)
# wait_for_completion = false


# [proxy.trunks.wuhoo]
# dest = "sip:123.456.789.00:1234"

# [[proxy.routes]]
# name = "default"
# priority = 1
# dest = "wuhoo"

# [proxy.routes.match]
# "to.user" = "^\\+.*"

# [proxy.routes.rewrite]
# "to.user" = "+{1}"
# "to.host" = "123.456.789.00:1234"
# "from.user" = "12345"
# "from.host" = "123.456.789.00:1234"