-
Notifications
You must be signed in to change notification settings - Fork 102
Expand file tree
/
Copy pathconfig.toml.example
More file actions
297 lines (259 loc) · 11.1 KB
/
Copy pathconfig.toml.example
File metadata and controls
297 lines (259 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# 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"
# Auto-detect external IP via HTTP service (mutually exclusive with external_ip)
# At startup, a GET request is sent to this URL and the response body is parsed as IP
# Leave empty to use the default: http://ifconfig.me
# auto_external_ip = "http://ifconfig.me"
# 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"
# Shared SIP and HTTP AMI cluster peers.
# [cluster]
# peers = [{ addr = "10.0.0.2", sip_port = 5060, ami_port = 8080 }]
[console]
#session_secret = "please_change_me_to_a_random_secret"
base_path = "/console"
# API prefix for REST endpoints (default: "/api")
# All REST API endpoints will be prefixed with this path
api_prefix = "/api"
# 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
# Static files HTTP path prefix (default: "/static")
static_path = "/static"
[ami]
# AMI access allow list. Supports exact IPs, CIDR ranges, and "*".
# Defaults to localhost only when omitted.
allows = ["127.0.0.1", "::1", "10.0.0.0/8"]
[proxy]
modules = ["acl", "auth", "presence", "registrar", "call"]
addr = "0.0.0.0"
udp_port = 15060
registrar_expires = 60
ws_handler= "/ws"
ami_path = "/ami/v1"
ice_servers_path = "/iceservers"
media_proxy = "auto"
# Worker thread isolation: SIP signalling and RTP media run on separate tokio
# runtimes, preventing heavy media-plane load from starving SIP timer tasks.
# Defaults: sip_worker_threads = min(4, num_cpus), media_worker_threads = rest.
# sip_worker_threads = 4
# media_worker_threads = 28
# session_timer = true
# session_timer_always = false # Keep refreshing even if peer does not negotiate session timer
# 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"
# JWT Fast Registration — skip 401/407 Digest challenge for JWT-authenticated clients.
# Required for CC Agent-ID (cc-phone JWT) login mode. See docs/cc_agent_login_modes.md.
# See docs/config/03-auth-users.md for full documentation.
# [proxy.jwt_auth]
# enabled = true
# secret = "your-shared-hs256-secret"
# user_id_claim = "userId"
# check_local_user = false
# Enable dev-console JWT/PhoneAuth token mint endpoints (POST /api/cc/dev/*).
# Defaults to false — production should keep this off.
# dev_mint_enabled = true
# HTTP Token Auth Backend — one-shot token auth via external HTTP service.
# Add token_header to any HTTP user backend to enable one-shot registration.
# See docs/config/03-auth-users.md for full documentation.
# [[proxy.user_backends]]
# type = "http"
# url = "https://auth-service.example.com/sip-auth"
# method = "POST"
# sip_headers = ["X-Auth-Token"] # Forward token to external service
# token_header = "X-Auth-Token" # Enable one-shot token auth (skip 407)
# http_timeout_ms = 5000 # Default: 5000
# http_retry_count = 1 # Default: 1 (retries on network error + 5xx)
# http_retry_delay_ms = 500 # Default: 500
# token_cache_ttl_secs = 60 # Default: 0 (disabled). Recommended: 30-300
# token_cache_size = 10000 # Default: 10000 (LRU eviction)
# Audio codec allowlist (e.g. PCMU, PCMA, G722, OPUS).
# audio_codecs = ["pcma","pcmu","g722","opus"]
# Video codec allowlist for re-INVITEs sent to RTP/PSTN/IMS trunks.
# WebRTC-only codecs (VP8, VP9, AV1, …) and all rtcp-fb feedback attributes
# are stripped automatically. Defaults to ["H264"] when not set.
# video_codecs = ["H264"]
# ── Recording ─────────────────────────────────────────────────────────────────
# IMPORTANT: [recording] and [sipflow] are mutually exclusive for RTP capture,
# UNLESS force_file = true is set (see below).
#
# • Default (recommended): Omit [recording]. SipFlow captures both SIP
# signalling and RTP audio.
#
# • Legacy: Configure [recording] WITHOUT [sipflow]. The live WAV recorder
# owns RTP recording. No SIP signalling capture.
#
# • Hybrid (force_file): Configure BOTH [recording] and [sipflow], then set
# force_file = true inside [recording]. The WAV file recorder captures
# audio; SipFlow captures SIP signalling ONLY (no RTP). Media upload goes
# through [recording] (type = "http" or "s3"), signalling upload goes
# through [sipflow.upload] (signaling = true).
#
# Uncomment below when you need the legacy WAV recorder or the hybrid mode.
# [recording]
# enabled = true
# auto_start = true
# # Recording upload mode: "local" (default), "http", or "s3".
# # type = "local"
# # path = "./recordings"
# # force_file = true # Use WAV file recorder for media even when [sipflow]
# # is active. SipFlow captures signalling only.
# # Media upload is handled by [recording] (type = http/s3),
# # not [sipflow.upload].
# ── CDR (Call Detail Records) ─────────────────────────────────────────────────
# Call records are ALWAYS persisted to the database (rustpbx_call_records table)
# and visible in the Web Console, regardless of this section.
#
# [callrecord] is OPTIONAL — it adds a secondary raw-CDR sink on top of the
# always-on database persistence. Omit this section entirely if you only need
# database CDRs (the common case).
#
# Storage types:
# type = "local" — write detailed CDR JSON files to a local directory
# type = "s3" — upload CDR JSON to S3-compatible object storage
# type = "http" — POST CDR JSON to an HTTP webhook endpoint
# type = "database" — write to a separate, minimal CDR table
#
# [callrecord]
# type = "local"
# root = "./config/cdr"
# max_concurrent = 64
# ── SipFlow ───────────────────────────────────────────────────────────────────
# Unified SIP + RTP recording system (default).
# When enabled WITHOUT a [recording] section, SipFlow captures both SIP
# signalling and RTP audio. The console shows the SIP flow ladder and an
# audio player for each call.
#
# When [recording] force_file = true is also set, SipFlow captures SIP
# signalling ONLY. Audio is recorded to a WAV file by the [recording]
# subsystem. In [sipflow.upload], media upload is automatically skipped
# (handled by [recording]); only signalling upload (if enabled) runs.
[sipflow]
type = "local"
root = "./config/sipflow"
subdirs = "daily" # "none" | "daily" | "hourly" (sqlite engine only)
# Storage engine: "flowdb" (default, LSM-tree) or "sqlite" (legacy)
engine = "flowdb"
# FlowDB engine options (ignored when engine = "sqlite"):
# ttl_secs = 86400 # auto-expire records after N seconds (optional)
# memtable_size_mb = 64 # memtable size threshold before flush
# block_cache_capacity_mb = 128 # LRU block cache for reads
# Advanced local backend settings (sqlite engine only, defaults shown):
# flush_count = 1000
# flush_interval_secs = 5
# id_cache_size = 8192
# Optional: upload captured media as WAV after each call.
# [sipflow.upload]
# type = "s3"
# vendor = "aws"
# bucket = "my-recordings"
# region = "us-east-1"
# access_key = "AKID"
# secret_key = "SECRET"
# endpoint = "https://s3.amazonaws.com"
# root = "recordings"
# media = true # upload captured RTP as WAV (default: true)
# signaling = false # also upload SIP signalling as JSONL (default: false)
# Remote backend (single node):
# [sipflow]
# type = "remote"
# udp_addr = "192.168.1.100:3000"
# http_addr = "http://192.168.1.100:3001"
# timeout_secs = 10
# Remote cluster (multi-node, consistent hashing by call_id):
# [sipflow]
# type = "remote"
# timeout_secs = 10
# nodes = [
# { udp = "192.168.1.1:3000", http = "http://192.168.1.1:3001" },
# { udp = "192.168.1.2:3000", http = "http://192.168.1.2:3001" },
# { udp = "192.168.1.3:3000", http = "http://192.168.1.3:3001" },
# { udp = "192.168.1.4:3000", http = "http://192.168.1.4:3001" },
# ]
# 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"
# ── Commercial Addon Licenses ─────────────────────────────────────────────────
# Map each commercial addon to a named license key, then supply the actual key
# values under [licenses.keys]. The UI's "Verify" button on the Addon detail
# page will write these sections automatically.
#
# [licenses]
# [licenses.addons]
# wholesale = "enterprise" # addon id -> key name
# endpoint-manager = "enterprise"
# voicemail = "basic"
#
# [licenses.keys]
# enterprise = "LICENSE-KEY-XXXX-XXXX-XXXX"
# basic = "LICENSE-KEY-YYYY-YYYY-YYYY"