WebRTC & ViciPhone Complete Setup Guide for ViciDial
The definitive guide — consolidating 30+ forum threads, scattered blog posts, and hard-won production experience into one coherent, copy-paste-ready reference.
Table of Contents
- What is ViciPhone / WebRTC?
- Prerequisites Checklist
- SSL Certificate Setup with Let's Encrypt
- Asterisk HTTP / WebSocket Configuration
- PJSIP TLS Transport Setup
- Asterisk Module Verification
- STUN/TURN Server Configuration
- ViciDial System Settings
- Phone Template Configuration
- User / Phone Assignment
- Browser Configuration & Agent Requirements
- Testing Your Setup
- Cluster / Multi-Server WebRTC
- Troubleshooting
- Performance Tuning
- Security Considerations
- Version Compatibility Matrix
- Quick-Start Checklist
1. What is ViciPhone / WebRTC?
Overview
ViciPhone is a browser-based SIP softphone purpose-built for ViciDial. It uses WebRTC (Web Real-Time Communication) so that agents can make and receive calls directly inside their web browser — no desktop softphone installation required, no Java applets, no Flash, no browser plugins of any kind.
How It Works — The Protocol Stack
Agent's Browser ViciDial / Asterisk
================ ====================
JavaScript WebRTC API
|
v
SIP-over-WebSocket ---[WSS:8089]---> Asterisk HTTP Server
(Signaling) (res_http_websocket)
| |
v v
DTLS-SRTP ---[UDP:10000-20000]---> RTP Engine
(Encrypted Media) (res_srtp)
|
v
ICE / STUN / TURN
(NAT Traversal)
Call flow: Browser opens WSS connection to Asterisk:8089 for SIP signaling. DTLS handshake establishes encryption keys. SRTP carries encrypted voice audio. ICE uses STUN/TURN to traverse NATs for the RTP media path.
Key technologies: WSS (SIP signaling), DTLS (key exchange), SRTP (encrypted media), ICE/STUN (NAT traversal), TURN (relay for restrictive NATs), Opus (high-quality codec). All except TURN and Opus are strictly required.
Benefits for Remote Agents
- Zero software installation — agents only need a modern browser (Chrome, Firefox, Edge)
- Works from anywhere — home office, co-working space, mobile (with headset)
- Encrypted by default — WebRTC mandates DTLS-SRTP; there is no unencrypted mode
- Centralized management — no per-agent softphone configuration; everything is server-side
- Lower training cost — agents log in to the same web interface they already use
- Firewall-friendly — WSS runs over standard HTTPS port patterns; TURN handles restrictive networks
ViciPhone Implementations
There are several WebRTC phone implementations for ViciDial:
| Project | Maintainer | URL | Notes |
|---|---|---|---|
| ViciPhone (official) | ViciDial Group | phone.viciphone.com | Default in recent ViciBox builds |
| ViciPhone v3 | vicimikec | github.com/vicimikec/ViciPhone | Community fork, self-hosted |
| ViciPhone v2.1 | ccabrerar | github.com/ccabrerar/ViciPhone | Improved version with fixes |
| CyburPhone | carpenox | github.com/carpenox/CyburPhone | CyburDial/Dialer.one project |
| PBXWebPhone | chornyitaras | github.com/chornyitaras/PBXWebPhone | Alternative WebRTC phone |
All of them use the same underlying WebRTC stack (SIP.js or JsSIP) and connect to Asterisk via the same WSS transport — the server-side configuration is identical regardless of which phone front-end you choose.
2. Prerequisites Checklist
Before you begin, verify every item on this list. Missing even one prerequisite will result in a non-functional WebRTC setup.
Server Requirements
| Requirement | Details | How to Check |
|---|---|---|
| ViciDial/ViciBox version | ViciBox 8.1+ (SVN 2800+) for native WebRTC support. ViciBox 10+ recommended. ViciBox 11 (SVN 3543+) or ViciBox 12 (latest) strongly recommended | cat /etc/vicibox-version or Admin > System Settings |
| Asterisk version | Asterisk 13+ minimum. Asterisk 16 or 18 recommended. Asterisk 20 with PJSIP for newest features | asterisk -rx 'core show version' |
| Operating system | ViciBox (openSUSE Leap 15.x), AlmaLinux 8/9, Rocky Linux 8/9, or CentOS 7+ | cat /etc/os-release |
| Public IP address | Static public IP on the server (or static NAT mapping) | curl -4 ifconfig.me |
| FQDN (domain name) | Valid domain name pointing to server's public IP via DNS A record | dig +short dialer.example.com |
| RAM | Minimum 4 GB for small deployments; 8+ GB for 50+ WebRTC agents | free -h |
Network / Firewall Requirements
| Port | Protocol | Direction | Purpose |
|---|---|---|---|
| 443 | TCP | Inbound | HTTPS for web interface (Apache) |
| 8089 | TCP | Inbound | WSS (WebSocket Secure) for SIP signaling |
| 10000-20000 | UDP | Inbound + Outbound | RTP/SRTP media streams |
| 3478 | UDP | Outbound | STUN (NAT discovery) |
| 5349 | TCP/UDP | Outbound | STUN/TURN over TLS |
| 80 | TCP | Inbound | Let's Encrypt ACME challenge (temporary, during cert issuance) |
Firewall verification:
# Check which ports are currently listening
ss -tlnp | grep -E '443|8089|8088'
# Test if port 8089 is reachable from outside (run from a different machine)
nc -zv dialer.example.com 8089
# Verify RTP port range
ss -ulnp | head -20
Software Dependencies
# Verify Asterisk modules are compiled with required support
asterisk -rx 'module show like websocket'
asterisk -rx 'module show like srtp'
asterisk -rx 'module show like crypto'
# Verify SSL/TLS support
openssl version
# Verify certbot is available (or can be installed)
which certbot 2>/dev/null || echo "certbot not installed"
What Will NOT Work
- Self-signed SSL certificates — modern browsers reject them for WebRTC; you must have a CA-signed certificate
- IP addresses instead of FQDN — WebSocket Secure requires a valid hostname with a matching certificate
- Asterisk 11 or earlier — does not support WebSocket transport
- HTTP (non-HTTPS) agent interface — browsers block microphone access on non-HTTPS pages
- Asterisk compiled without SRTP/PJSIP — if Asterisk was compiled with
--without-srtpor without pjproject support, WebRTC will not work
3. SSL Certificate Setup with Let's Encrypt
SSL is the foundation of WebRTC. Without a valid, CA-signed TLS certificate, nothing works: browsers will refuse the WSS connection, reject the DTLS handshake, and block microphone access on HTTP pages.
3A. ViciBox 11+ / ViciBox 12 — Using vicibox-ssl (Recommended)
ViciBox 11 and 12 include the vicibox-ssl utility that automates the entire SSL setup for both Apache and Asterisk.
# Run the SSL setup wizard
vicibox-ssl
The wizard will prompt you for:
- Email address — for Let's Encrypt notifications (expiry warnings, etc.)
- FQDN — the fully qualified domain name (e.g.,
dialer.example.com)
It will then:
- Request a certificate from Let's Encrypt
- Configure Apache to use the new certificate
- Configure Asterisk's
http.conffor WSS with the certificate - Create a ViciPhone WebRTC template automatically
- Set up automatic renewal via systemd timer
Verify it works:
# Check that Apache is serving HTTPS
curl -sI https://dialer.example.com | head -5
# Check that Asterisk WSS is listening
ss -tlnp | grep 8089
# Verify the certificate
echo | openssl s_client -connect dialer.example.com:443 -servername dialer.example.com 2>/dev/null | openssl x509 -noout -dates
If vicibox-ssl completes without errors, skip to Section 4 to verify the Asterisk configuration.
3B. ViciBox 8-10 / openSUSE Leap — Manual Certbot
Install Certbot
# openSUSE Leap 15.x (ViciBox)
zypper install certbot
# If zypper certbot package is outdated, use snap:
zypper install snapd
systemctl enable --now snapd
ln -s /var/lib/snapd/snap /snap
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
Request the Certificate
Option A: Webroot mode (Apache running, recommended)
# Ensure Apache is running and serving on port 80
systemctl status apache2
# Request the certificate using the web root
certbot certonly --webroot \
--webroot-path /srv/www/htdocs \
--email [email protected] \
--agree-tos \
--no-eff-email \
-d dialer.example.com
Option B: Standalone mode (if port 80 is free)
# Temporarily stop Apache if it is using port 80
systemctl stop apache2
# Request the certificate
certbot certonly --standalone \
--email [email protected] \
--agree-tos \
--no-eff-email \
-d dialer.example.com
# Restart Apache
systemctl start apache2
Certificate Files Location
After successful issuance, your certificates are at:
/etc/letsencrypt/live/dialer.example.com/
cert.pem # Server certificate only
chain.pem # Intermediate CA certificate
fullchain.pem # Server cert + intermediate (use for Apache)
privkey.pem # Private key
Configure Apache SSL
Edit the ViciBox Apache SSL configuration:
File: /etc/apache2/vhosts.d/1111-default-ssl.conf
<VirtualHost *:443>
ServerName dialer.example.com
DocumentRoot /srv/www/htdocs
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/dialer.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/dialer.example.com/privkey.pem
# Modern TLS settings
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
<Directory /srv/www/htdocs>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Restart Apache:
systemctl restart apache2
Set Up Auto-Renewal
# Test renewal (dry run)
certbot renew --dry-run
# Enable the systemd timer for automatic renewal
systemctl enable --now certbot-renew.timer
# Alternatively, add a cron job
# This runs renewal check twice daily (standard practice)
echo "0 3,15 * * * root certbot renew --quiet --deploy-hook 'systemctl restart apache2 && asterisk -rx \"core restart now\"'" >> /etc/crontab
Verify it works:
# Check certificate validity and expiry
echo | openssl s_client -connect dialer.example.com:443 2>/dev/null | openssl x509 -noout -subject -dates
# Expected output:
# subject=CN = dialer.example.com
# notBefore=Mar 13 00:00:00 2026 GMT
# notAfter=Jun 11 00:00:00 2026 GMT
3C. AlmaLinux / Rocky Linux / CentOS — Certbot with dnf
# Install certbot
dnf install epel-release -y
dnf install certbot python3-certbot-apache mod_ssl -y
# Request certificate (auto-configures Apache)
certbot --apache -d dialer.example.com --email [email protected] --agree-tos --no-eff-email
# Enable auto-renewal
systemctl enable --now certbot-renew.timer
Certificate files are at /etc/letsencrypt/live/dialer.example.com/. Apache SSL config goes in /etc/httpd/conf.d/ssl.conf with the same SSLCertificateFile (fullchain.pem) and SSLCertificateKeyFile (privkey.pem) directives shown in 3B above.
Common SSL Pitfalls
| Problem | Cause | Solution |
|---|---|---|
| "Could not bind to port 80" | Apache or nginx already using port 80 | Use --webroot mode instead of --standalone |
| "DNS problem: NXDOMAIN" | Domain A record not pointing to server | Verify: dig +short dialer.example.com returns your IP |
| "Timeout during connect" | Firewall blocking port 80 | Open TCP/80 inbound temporarily for ACME challenge |
| "Too many certificates already issued" | Let's Encrypt rate limit (50/week per domain) | Wait, or use staging server for testing: --staging |
| "Lack of sufficient authorization" | Certbot ACMEv1 end-of-life | Update certbot: zypper update certbot or reinstall via snap |
| Certificate renews but services not reloaded | No deploy hook | Add --deploy-hook to restart Apache and Asterisk |
4. Asterisk HTTP / WebSocket Configuration
Asterisk's built-in HTTP server handles the WebSocket connections from browsers. This is where the WSS (WebSocket Secure) listener lives.
Configuration File: /etc/asterisk/http.conf
;
; Asterisk HTTP Server Configuration
; This enables the WebSocket Secure (WSS) listener for WebRTC
;
[general]
;
; Enable the built-in HTTP server
enabled = yes
;
; Bind to all interfaces
bindaddr = 0.0.0.0
;
; HTTP port (used internally, not exposed to agents)
bindport = 8088
;
; Enable static HTTP content serving
enablestatic = yes
;
; Enable TLS (required for WSS)
tlsenable = yes
;
; WSS bind address and port
; Use 0.0.0.0 to listen on all interfaces
; Port 8089 is the standard for Asterisk WSS
tlsbindaddr = 0.0.0.0:8089
;
; SSL certificate and private key
; These MUST be from a valid CA (Let's Encrypt), NOT self-signed
;
; For Let's Encrypt certificates:
tlscertfile = /etc/letsencrypt/live/dialer.example.com/fullchain.pem
tlsprivatekey = /etc/letsencrypt/live/dialer.example.com/privkey.pem
;
; Session timeout for HTTP connections (seconds)
; sessionlimit = 100
;
; TLS cipher suite (optional, for hardened security)
; tlscipher = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256
Important notes on certificate paths:
- Some guides use
cert.pemfortlscertfile. Usingfullchain.pemis better because it includes the intermediate CA certificate, which some browsers need to complete the chain of trust. - If you are using vicibox-ssl, the paths may differ (e.g.,
/etc/apache2/ssl.crt/vicibox.crt). Use whatever path vicibox-ssl configured. - The private key file must be readable by the Asterisk process. Check permissions:
ls -la /etc/letsencrypt/live/dialer.example.com/
# privkey.pem should be readable by root (Asterisk typically runs as root on ViciBox)
Apply the Configuration
# Reload the HTTP server without a full Asterisk restart
asterisk -rx 'module reload http'
# If that does not pick up TLS changes, restart Asterisk
asterisk -rx 'core restart now'
# Wait for Asterisk to fully restart, then re-run keepalives
/usr/share/astguiclient/ADMIN_keepalive_ALL.pl
Verify It Works
# Check that the HTTP server is running and listening
asterisk -rx 'http show status'
Expected output:
HTTP Server Status:
Prefix:
Server: Asterisk
Server Enabled and Bound to 0.0.0.0:8088
HTTPS Server Enabled and Bound to 0.0.0.0:8089
Enabled URI's:
/httpstatus => Asterisk HTTP General Status
/phoneprov/... => Asterisk HTTP Phone Provisioning Tool
/static/... => Asterisk HTTP Static Delivery
/ws => Asterisk HTTP WebSocket
The critical line is: /ws => Asterisk HTTP WebSocket — if this is missing, the res_http_websocket module is not loaded.
# Verify WSS port is actually listening
ss -tlnp | grep 8089
# Expected output:
# LISTEN 0 128 0.0.0.0:8089 0.0.0.0:* users:(("asterisk",pid=XXXX,fd=XX))
# Test the TLS certificate on port 8089 from the server itself
openssl s_client -connect localhost:8089 -servername dialer.example.com </dev/null 2>/dev/null | head -20
# Test from an external machine
openssl s_client -connect dialer.example.com:8089 -servername dialer.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -dates
5. PJSIP TLS Transport Setup
If your ViciDial installation uses PJSIP (which is the case for ViciBox 12 with Asterisk 18+, and recommended for new deployments), you need to configure the WSS transport in pjsip.conf.
Note: Most ViciDial installations still use chan_sip (the traditional SIP module), not PJSIP. If your system uses chan_sip, skip this section — the SIP template configuration in Section 9 handles everything via ViciDial's template system. Check which you are using:
# Check if chan_sip is loaded
asterisk -rx 'module show like chan_sip'
# Check if chan_pjsip is loaded
asterisk -rx 'module show like chan_pjsip'
PJSIP Transport Configuration
File: /etc/asterisk/pjsip.conf (or included file)
Add the WSS transport:
;
; WebSocket Secure Transport for WebRTC
;
[transport-wss]
type = transport
protocol = wss
bind = 0.0.0.0
;
; Note: For WSS transports, certificate configuration is handled
; by http.conf (the Asterisk HTTP server). The WSS transport
; piggybacks on the HTTP TLS listener. You do NOT need to
; specify cert/key paths here — they are inherited from http.conf.
;
; Other transport parameters (like local_net, external_media_address,
; etc.) are ignored for WSS transports.
PJSIP WebRTC Endpoint Example
If using PJSIP endpoints directly (not through ViciDial phone templates), you define three objects (endpoint, aor, auth) with the same name. The key setting is webrtc = yes which is a convenience shortcut (Asterisk 16+) that enables:
rtcp_mux = yesuse_avpf = yesice_support = yesuse_received_transport = yesmedia_encryption = dtlsdtls_verify = fingerprintdtls_setup = actpass
Verify PJSIP Transport
# Show all PJSIP transports
asterisk -rx 'pjsip show transports'
# Expected output should include transport-wss
# Transport: <TransportId........location> <Type> <cos> <tos> <BindAddress>
# ==========================================================================================
# Transport: transport-wss wss 0 0 0.0.0.0:0
6. Asterisk Module Verification
WebRTC requires several Asterisk modules to be compiled and loaded. If any module is missing, the setup will fail silently or with cryptic errors.
Required Modules
| Module | Purpose | Critical? |
|---|---|---|
res_http_websocket.so |
WebSocket protocol support for Asterisk HTTP server | Yes — without this, no /ws URI |
res_pjsip_transport_websocket.so |
WSS transport for PJSIP channel driver | Yes (if using PJSIP) |
res_crypto.so |
Cryptographic operations (TLS, DTLS) | Yes |
res_srtp.so |
SRTP encryption for media streams | Yes — WebRTC mandates encrypted media |
res_rtp_asterisk.so |
RTP/SRTP engine with ICE support | Yes |
codec_opus.so |
Opus codec (high-quality WebRTC audio) | Recommended |
res_pjsip.so |
PJSIP SIP channel driver | Only if using PJSIP |
chan_sip.so |
Traditional SIP channel driver | Only if using chan_sip |
How to Check
# Check all WebSocket-related modules
asterisk -rx 'module show like websocket'
# Expected output:
# Module Description Use Count Status
# res_http_websocket.so HTTP WebSocket Support 2 Running
# res_pjsip_transport_websocket.so PJSIP WebSocket Transport Support 1 Running
# Check crypto and SRTP modules
asterisk -rx 'module show like crypto'
# res_crypto.so Cryptographic Digital Signatures 1 Running
asterisk -rx 'module show like srtp'
# res_srtp.so Secure RTP (SRTP) 1 Running
# Check Opus codec
asterisk -rx 'module show like opus'
# codec_opus.so OPUS Coder/Decoder 0 Running
# (If missing, Opus is not compiled — see below)
# Check RTP engine
asterisk -rx 'module show like res_rtp'
# res_rtp_asterisk.so Asterisk RTP Stack 9 Running
# Quick one-liner to check all critical modules
asterisk -rx 'module show' | grep -E 'websocket|srtp|crypto|opus|res_rtp'
If a Module Is Missing
First check /etc/asterisk/modules.conf for noload lines blocking required modules. If the module file does not exist on disk, Asterisk needs recompilation. For ViciBox, this is handled by the ViciBox build system. For custom installations, the key configure flags are: --with-pjproject-bundled --with-ssl --enable-asteriskssl --with-srtp --enable-srtp --enable-opus.
Verify It Works
# Load a missing module manually (temporary, for testing)
asterisk -rx 'module load res_http_websocket.so'
# Confirm the /ws URI is now available
asterisk -rx 'http show status' | grep ws
# Should show: /ws => Asterisk HTTP WebSocket
7. STUN/TURN Server Configuration
Why STUN/TURN Is Needed
WebRTC uses ICE (Interactive Connectivity Establishment) to find a working network path for RTP media between the browser and Asterisk. This matters because:
- Agents are typically behind home routers with NAT
- The browser needs to know its public IP address to tell Asterisk where to send audio
- STUN (Session Traversal Utilities for NAT) discovers the agent's public IP/port mapping
- TURN (Traversal Using Relays around NAT) relays media through a server when direct connections fail (symmetric NAT, restrictive firewalls)
Without STUN: One-way audio or no audio at all. Without TURN: Agents behind strict corporate firewalls will have no audio.
7A. Using Public STUN Servers (Simplest)
Google operates free, high-availability STUN servers. These are sufficient for most deployments where agents are on standard home/office networks.
Currently working Google STUN servers (verified 2025-2026):
| Server | Port | Protocol |
|---|---|---|
stun.l.google.com |
19302 | UDP |
stun1.l.google.com |
19302 | UDP |
stun2.l.google.com |
19302 | UDP |
stun3.l.google.com |
19302 | UDP |
stun4.l.google.com |
19302 | UDP |
stun.l.google.com |
5349 | TCP/TLS |
Other public STUN servers:
| Server | Port |
|---|---|
stun.stunprotocol.org |
3478 |
stun.voip.blackberry.com |
3478 |
stun.sipnet.ru |
3478 |
Configure Asterisk to Use STUN
File: /etc/asterisk/rtp.conf
[general]
;
; RTP port range
; WebRTC agents each need a pair of RTP ports
; Range of 10000 supports ~5000 concurrent WebRTC calls
;
rtpstart = 10000
rtpend = 20000
;
; Enable ICE support (required for WebRTC)
;
icesupport = yes
;
; STUN server for NAT traversal
; Asterisk will use this to discover its own public IP for ICE candidates
;
stunaddr = stun.l.google.com:19302
;
; TURN server (optional but recommended)
; Uncomment and configure if you have a TURN server
;
; turnaddr = turn.example.com:3478
; turnusername = vicidial
; turnpassword = secretpassword
;
; Strict RTP protection
; Set to "yes" to learn the remote RTP address from the first packet
; Helps with NAT traversal
;
strictrtp = yes
;
; RTP timeout (seconds)
; Hang up calls with no RTP traffic after this duration
;
rtptimeout = 60
rtpholdtimeout = 300
Apply the configuration:
asterisk -rx 'module reload res_rtp_asterisk.so'
7B. Setting Up Your Own coturn Server (Recommended for Production)
For production deployments with 20+ agents, especially if any agents are behind corporate firewalls or symmetric NAT, deploy your own TURN server using coturn.
Install coturn
# Debian/Ubuntu # AlmaLinux/Rocky # openSUSE
apt install coturn -y # dnf install coturn -y # zypper install coturn
Configure coturn
File: /etc/turnserver.conf
listening-port=3478
tls-listening-port=5349
listening-ip=0.0.0.0
external-ip=203.0.113.50
min-port=49152
max-port=65535
realm=dialer.example.com
server-name=dialer.example.com
lt-cred-mech
user=vicidial:YourSecureTurnPassword123
cert=/etc/letsencrypt/live/dialer.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/dialer.example.com/privkey.pem
fingerprint
log-file=/var/log/turnserver.log
verbose
no-multicast-peers
no-cli
total-quota=100
Start and Test
systemctl enable --now coturn
# On Debian/Ubuntu, also set TURNSERVER_ENABLED=1 in /etc/default/coturn
ss -ulnp | grep 3478 # Verify port is listening
Test with: https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ — enter turn:dialer.example.com:3478 with credentials above and click "Gather candidates." You should see relay candidates.
Configure Asterisk to Use Your TURN Server
Add to /etc/asterisk/rtp.conf in the [general] section:
turnaddr = dialer.example.com:3478
turnusername = vicidial
turnpassword = YourSecureTurnPassword123
Then reload: asterisk -rx 'module reload res_rtp_asterisk.so'
Verify ICE Is Working
# In the Asterisk CLI, during an active WebRTC call:
asterisk -rx 'rtp show settings'
# Check for ICE candidates in SIP debug
asterisk -rx 'sip set debug on'
# Look for lines containing "a=candidate" in SDP
8. ViciDial System Settings
Now that the server infrastructure (SSL, Asterisk, STUN) is configured, set up ViciDial's web interface to use WebRTC.
8A. System Settings
Navigate to: Admin > System Settings
| Field | Value | Notes |
|---|---|---|
| Webphone URL | https://dialer.example.com/agc/viciphone.php |
For built-in ViciPhone. If using ViciPhone v3: https://dialer.example.com/ViciPhone/viciphone.php. If using CyburPhone: https://dialer.example.com/CyburPhone/cyburphone.php. If using the hosted version: https://phone.viciphone.com/viciphone.php |
| Default Webphone | Y |
Sets webphone as default for all new phones |
| Webphone Systemkey | (leave default or set a key) | Shared key between ViciDial and the webphone app |
| Enable WebRTC Phone | 1 (or Y) |
Enables the WebRTC phone functionality system-wide |
8B. Server Settings
Navigate to: Admin > Servers > [Your Server]
For each Asterisk server in your system, configure:
| Field | Value | Notes |
|---|---|---|
| External Server IP | 203.0.113.50 |
The server's public IP address. If behind NAT/firewall, use the external IP that forwards port 8089 to this server |
| Web Socket URL | wss://dialer.example.com:8089/ws |
Must be WSS (not WS), must use the FQDN (not IP), must end with /ws, port 8089 is the Asterisk TLS HTTP port |
| Active Asterisk Server | Y |
Must be active |
Critical: The Web Socket URL format is very specific:
wss://FQDN:8089/ws
wss://— WebSocket Secure protocol (notws://orhttps://)FQDN— Fully qualified domain name matching the SSL certificate (not an IP address):8089— Port configured astlsbindaddrinhttp.conf/ws— The WebSocket URI path in Asterisk (always/ws)
Common mistakes:
- Using
ws://instead ofwss://— will not work with TLS - Using an IP address instead of FQDN — certificate mismatch
- Using
:8088instead of:8089— 8088 is non-TLS HTTP - Omitting
/ws— Asterisk will not recognize the connection - Adding a trailing slash (
/ws/) — may cause connection issues
8C. Install the WebPhone (If Self-Hosting)
If you want to self-host ViciPhone rather than using the hosted phone.viciphone.com:
ViciPhone v3 (vicimikec):
# ViciBox (openSUSE)
cd /srv/www/htdocs
git clone https://github.com/vicimikec/ViciPhone.git
chown -R wwwrun:www ViciPhone/
chmod -R 755 ViciPhone/
# AlmaLinux/Rocky/CentOS
cd /var/www/html
git clone https://github.com/vicimikec/ViciPhone.git
chown -R apache:apache ViciPhone/
chmod -R 755 ViciPhone/
Set the Webphone URL in System Settings to:
https://dialer.example.com/ViciPhone/viciphone.php
CyburPhone (Dialer.one):
# ViciBox (openSUSE)
cd /srv/www/htdocs
git clone https://github.com/carpenox/CyburPhone.git
chown -R wwwrun:www CyburPhone/
chmod -R 755 CyburPhone/
# AlmaLinux/Rocky/CentOS
cd /var/www/html
git clone https://github.com/carpenox/CyburPhone.git
chown -R apache:apache CyburPhone/
chmod -R 755 CyburPhone/
Set the Webphone URL in System Settings to:
https://dialer.example.com/CyburPhone/cyburphone.php
Verify It Works
# Test that the webphone page loads
curl -sI https://dialer.example.com/ViciPhone/viciphone.php | head -5
# Should return: HTTP/1.1 200 OK
# Or in a browser, navigate to the webphone URL directly
# You should see a phone interface (it will not connect without credentials)
9. Phone Template Configuration
The SIP phone template defines how WebRTC phones register and negotiate media with Asterisk. This is the most error-prone step — every parameter matters.
Creating the WebRTC Template
Navigate to: Admin > Templates > Add a New Template
Enter a Template ID (e.g., WEBRTC or SIP_generic_WSS) and set the Template Contents to:
type=friend
host=dynamic
context=default
trustrpid=yes
sendrpid=no
qualify=yes
qualifyfreq=60
transport=ws,wss,udp
encryption=yes
avpf=yes
icesupport=yes
rtcp_mux=yes
directmedia=no
canreinvite=no
disallow=all
allow=ulaw,opus,vp8,h264
nat=force_rport,comedia
force_avp=yes
dtlsenable=yes
dtlsverify=no
dtlscertfile=/etc/letsencrypt/live/dialer.example.com/fullchain.pem
dtlsprivatekey=/etc/letsencrypt/live/dialer.example.com/privkey.pem
dtlssetup=actpass
Key Parameters Explained
| Parameter | Why It Matters |
|---|---|
transport=ws,wss,udp |
WSS for WebRTC; UDP as fallback for standard SIP phones |
encryption=yes + avpf=yes |
Mandatory for WebRTC SRTP and RTCP feedback |
icesupport=yes + rtcp_mux=yes |
ICE for NAT traversal; mux reduces port usage |
directmedia=no + canreinvite=no |
Force media through Asterisk — prevents one-way audio behind NAT |
nat=force_rport,comedia |
Critical for NAT: forces symmetric RTP using received port |
dtlsenable=yes + dtlsverify=no |
DTLS key exchange for SRTP. Verify=no because browsers use ephemeral certs |
dtlscertfile / dtlsprivatekey |
Points to your Let's Encrypt certificate for DTLS handshake |
dtlssetup=actpass |
Server offers both active/passive DTLS roles (WebRTC standard) |
qualifyfreq=60 |
Detect dead connections quickly (some use 600 but 60 catches drops faster) |
Codec Selection
For voice-only call centers, use allow=ulaw,opus. Putting ulaw first avoids transcoding for PSTN trunks. Opus (6-128 kbps variable) gives excellent quality but requires codec_opus.so compiled into Asterisk. G.722 is a good wideband middle ground. vp8/h264 are only needed for video calling.
Verify the Template
After saving the template, verify it appears in the template list:
- Go to Admin > Templates
- Find your template (e.g.,
WEBRTC) - Click to edit and verify all parameters are saved correctly
- Check that the certificate paths are correct:
# Verify certificate files exist at the paths specified in the template
ls -la /etc/letsencrypt/live/dialer.example.com/fullchain.pem
ls -la /etc/letsencrypt/live/dialer.example.com/privkey.pem
10. User / Phone Assignment
With the template created, assign WebRTC phones to your agents.
10A. Configure an Existing Phone for WebRTC
Navigate to: Admin > Phones > [Select Phone]
| Field | Value | Notes |
|---|---|---|
| Set As Webphone | Y |
Marks this phone entry as a browser-based phone |
| Webphone Auto-Answer | Y |
Phone automatically answers incoming calls (no manual "accept" click needed). Set to N if agents should manually answer |
| Use External Server IP | Y |
Uses the External Server IP from server settings for WebSocket connection. Must be Y for WebRTC to work |
| Template ID | WEBRTC |
The template you created in Section 9. Select from dropdown |
| Server IP | (server IP) | The Asterisk server this phone connects to |
| Active | Y |
Phone must be active |
10B. Create a New WebRTC Phone
Navigate to: Admin > Phones > Add a New Phone
| Field | Value |
|---|---|
| Extension | 8000 (or your numbering scheme) |
| Dialplan Number | 8000 (match extension) |
| Voicemail ID | 8000 (match extension) |
| Phone Login | agent1_phone (unique identifier) |
| Phone Password | (auto-generated or set manually) |
| Server IP | (select your Asterisk server) |
| Protocol | SIP |
| Set As Webphone | Y |
| Webphone Auto-Answer | Y |
| Use External Server IP | Y |
| Template ID | WEBRTC |
| Active | Y |
10C. Assign Phone to User
Navigate to: Admin > Users > [Select User]
| Field | Value |
|---|---|
| Phone Login | (enter the Phone Login from the phone entry) |
| Phone Pass | (enter the Phone Password from the phone entry) |
When the agent logs into the ViciDial agent interface, they will enter:
- User — their ViciDial username
- Pass — their ViciDial password
- Phone Login — the phone login assigned to them
- Phone Pass — the phone password assigned to them
If Webphone Auto-Answer is set to Y and the phone is correctly configured, the webphone should automatically connect when the agent logs in.
Verify Phone Registration
When an agent logs in with a WebRTC phone:
# Check SIP registrations (chan_sip)
asterisk -rx 'sip show peers' | grep -i webrtc
# Check PJSIP registrations
asterisk -rx 'pjsip show endpoints' | grep -i webrtc
# Check a specific peer
asterisk -rx 'sip show peer 8001'
# Look for: Status: OK (XXX ms)
# And: Addr->IP: 0.0.0.0 (WebSocket connections show differently than UDP)
11. Browser Configuration & Agent Requirements
Supported Browsers
| Browser | Version | WebRTC Support | Notes |
|---|---|---|---|
| Google Chrome | 80+ | Full | Recommended. Best WebRTC implementation |
| Chromium | 80+ | Full | Same engine as Chrome |
| Microsoft Edge | 80+ (Chromium-based) | Full | Works well |
| Mozilla Firefox | 78+ | Full | Works, but Chrome is generally more reliable for ViciPhone |
| Safari | 14.1+ | Partial | WebRTC support improved but still less reliable than Chrome. Not recommended for production |
| Opera | 67+ | Full | Chromium-based, works |
| Brave | Any | Full | Chromium-based, but shield/privacy features may block WebSocket connections — configure exceptions |
Recommendation: Use Google Chrome (latest stable) for all agents. It has the most mature and tested WebRTC implementation.
Browser Requirements and Settings
1. HTTPS Requirement
The ViciDial agent interface must be loaded via HTTPS. Browsers block getUserMedia() (microphone access) on non-HTTPS pages.
- Correct:
https://dialer.example.com/agc/vicidial.php - Wrong:
http://dialer.example.com/agc/vicidial.php
2. Microphone Permissions
When the agent first logs in and the webphone activates, the browser will prompt for microphone access. The agent must click "Allow."
To pre-configure in Chrome (useful for managed deployments):
chrome://settings/content/microphone
Add https://dialer.example.com to the "Allowed" list.
3. Pop-up / Notification Permissions
ViciPhone may open in a pop-up window or iframe. Ensure pop-ups are allowed for the dialer domain:
chrome://settings/content/popups
Add https://dialer.example.com to "Allowed."
4. Disable Extensions That Block WebSocket/WebRTC
Ad blockers (uBlock Origin, AdBlock Plus), privacy extensions (Privacy Badger, WebRTC Leak Prevent), and VPN extensions can all break WebRTC. Solution: create a dedicated browser profile with no extensions, or whitelist the dialer domain.
5. Hardware Requirements for Agents
| Component | Minimum | Recommended |
|---|---|---|
| Headset | USB headset with microphone | Jabra/Plantronics USB headset with noise cancellation |
| Internet | 1 Mbps up/down per agent | 5+ Mbps up/down per agent |
| CPU | Dual-core, any modern processor | Quad-core |
| RAM | 4 GB | 8 GB |
| OS | Any (Chrome runs on Windows, macOS, Linux, ChromeOS) | Windows 10+, macOS 12+, or ChromeOS |
Agent Quick-Start Instructions
Give agents these essentials: (1) Open Chrome, navigate to https://dialer.example.com/agc/vicidial.php, (2) Enter user/pass and phone login/pass, (3) Click Allow when Chrome asks for microphone access, (4) Webphone shows "Registered" and they are ready. Troubleshooting: ensure HTTPS (lock icon), allow microphone in address bar, disable ad blockers/VPN extensions, press Ctrl+Shift+J to check console for errors.
12. Testing Your Setup
Follow this sequence exactly. Each step depends on the previous one succeeding.
Step 1: Verify SSL Certificate on Port 443 (Apache)
# From the server itself
echo | openssl s_client -connect localhost:443 -servername dialer.example.com 2>/dev/null | openssl x509 -noout -subject -dates -issuer
# Expected:
# subject=CN = dialer.example.com
# notBefore=...
# notAfter=... (should be in the future)
# issuer=C = US, O = Let's Encrypt, CN = R3 (or similar)
# From an external machine
echo | openssl s_client -connect dialer.example.com:443 2>/dev/null | openssl x509 -noout -subject -dates
If this fails: Fix SSL certificate first (Section 3). Nothing else will work without it.
Step 2: Verify SSL Certificate on Port 8089 (Asterisk WSS)
# From the server
echo | openssl s_client -connect localhost:8089 -servername dialer.example.com 2>/dev/null | openssl x509 -noout -subject -dates
# From an external machine
echo | openssl s_client -connect dialer.example.com:8089 2>/dev/null | openssl x509 -noout -subject -dates
If this fails:
- Check
http.conf— aretlscertfileandtlsprivatekeypaths correct? - Is Asterisk running?
systemctl status asterisk - Is port 8089 open in the firewall?
Step 3: Verify WebSocket Endpoint
# Check that Asterisk is serving the /ws endpoint
asterisk -rx 'http show status' | grep ws
# Must show: /ws => Asterisk HTTP WebSocket
# Test WebSocket connectivity with curl (basic TLS check)
curl -v -k --no-buffer \
--header "Connection: Upgrade" \
--header "Upgrade: websocket" \
--header "Sec-WebSocket-Version: 13" \
--header "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
https://dialer.example.com:8089/ws 2>&1 | head -30
# You should see a "101 Switching Protocols" response (or at minimum a TLS handshake success)
# A "Connection refused" or "SSL handshake failure" indicates a problem
Step 4: Verify Phone Registration
- Log in to the ViciDial agent interface:
https://dialer.example.com/agc/vicidial.php - Enter user credentials and the WebRTC phone credentials
- Allow microphone access when prompted
- Watch for the webphone panel to show "Registered" or "Connected"
On the server, simultaneously check:
# Watch SIP registrations in real time (chan_sip)
asterisk -rx 'sip show peers' | grep -E '8001|webrtc'
# Or watch the console for registration events
asterisk -r
> sip set debug peer 8001
> (log in from the browser)
> (you should see REGISTER messages flowing)
Step 5: Make a Test Call
- Log the agent in and ensure the webphone is registered
- Have the agent make a manual dial or receive an inbound call
- Verify two-way audio: both parties can hear each other
During the call, check:
# Show active channels
asterisk -rx 'core show channels verbose' | grep -i ws
# Check RTP statistics for the call
asterisk -rx 'rtp show stats'
# Look for the WebSocket transport indicator
asterisk -rx 'sip show channels' | grep -i ws
Step 6: Network/ICE Verification
Open the browser's developer console during a call:
- Press
F12(orCtrl+Shift+J) - Go to the Console tab
- Look for ICE candidate messages
- In Chrome, navigate to
chrome://webrtc-internals/for detailed WebRTC statistics:- ICE candidate pairs
- DTLS state
- Audio codec in use
- Packet loss / jitter
- Bytes sent/received
Complete Test Flowchart
[Start]
|
v
[1] SSL on 443? ----NO----> Fix Apache SSL config (Section 3)
|YES
v
[2] SSL on 8089? ---NO----> Fix http.conf TLS settings (Section 4)
|YES
v
[3] /ws endpoint? --NO----> Load res_http_websocket module (Section 6)
|YES
v
[4] Phone registers? -NO--> Check template, phone config, WSS URL (Sections 8-10)
|YES
v
[5] Two-way audio? --NO---> Check STUN/TURN, NAT, rtp.conf (Section 7)
|YES
v
[SUCCESS - WebRTC is working]
13. Cluster / Multi-Server WebRTC
In a ViciDial cluster (multiple Asterisk servers behind a single web interface), WebRTC requires additional configuration because each Asterisk server handles its own WebSocket connections and media.
Key Principles
- Each Asterisk server needs its own SSL certificate — the certificate must match the FQDN of that specific server
- Each server needs its own WSS URL — configured in Admin > Servers
- Each server may need its own phone template — if certificate paths differ between servers
- The web server (Admin/Agent UI) only needs one certificate — for the main HTTPS interface
- Agents connect to the Asterisk server assigned to their phone — not the web server
Step-by-Step Cluster Setup
DNS: Create a separate A record for each Asterisk server (
dialer1.example.com,dialer2.example.com, etc.)SSL on each server: Run
certbot certonly --webroot -d dialerN.example.comon each Asterisk server. Alternative: use a wildcard cert (*.example.com) via DNS-01 challenge and deploy the same cert to all servers.http.conf on each server: Set
tlscertfileandtlsprivatekeyto the server-specific cert paths.Per-server templates: If certificate paths differ between servers, create separate templates (e.g.,
WEBRTC_DIALER1,WEBRTC_DIALER2) with the matchingdtlscertfile/dtlsprivatekeypaths. If using a wildcard cert with identical paths, one template works for all.Server settings in ViciDial: In Admin > Servers, for each server set:
| Server | External Server IP | Web Socket URL |
|---|---|---|
| dialer1 | 203.0.113.10 | wss://dialer1.example.com:8089/ws |
| dialer2 | 203.0.113.11 | wss://dialer2.example.com:8089/ws |
| dialer3 | 203.0.113.12 | wss://dialer3.example.com:8089/ws |
- Phone assignment: Each phone's Server IP determines which Asterisk server it connects to. Ensure the phone's Template ID matches the correct template for that server, and Use External Server IP is set to
Y.
14. Troubleshooting
Error: "WebSocket connection failed" / "conn.failed"
Symptoms: Phone shows "Connection Failed" or "conn.failed" immediately upon login.
Diagnostic steps:
# 1. Is Asterisk running?
systemctl status asterisk
# 2. Is port 8089 listening?
ss -tlnp | grep 8089
# 3. Is the certificate valid?
echo | openssl s_client -connect dialer.example.com:8089 2>/dev/null | openssl x509 -noout -dates
# 4. Is the /ws endpoint available?
asterisk -rx 'http show status' | grep ws
# 5. Is the firewall blocking?
iptables -L -n | grep 8089
# Or on firewalld:
firewall-cmd --list-ports | grep 8089
Common causes and fixes:
| Cause | Fix |
|---|---|
| Port 8089 not open in firewall | iptables -A INPUT -p tcp --dport 8089 -j ACCEPT or firewall-cmd --add-port=8089/tcp --permanent && firewall-cmd --reload |
| TLS not enabled in http.conf | Set tlsenable=yes and restart Asterisk |
| Wrong certificate path in http.conf | Verify paths exist: ls -la /etc/letsencrypt/live/... |
res_http_websocket.so not loaded |
asterisk -rx 'module load res_http_websocket.so' |
| Self-signed certificate | Browser silently rejects it. Use Let's Encrypt |
| Certificate expired | certbot renew && systemctl restart asterisk |
| Wrong WSS URL in server settings | Must be wss://FQDN:8089/ws — check capitalization, port, path |
Error: "488 Not Acceptable Here"
Symptoms: Phone registers but calls fail with SIP 488 error. Sometimes occurs on the welcome call immediately after login.
Cause: Codec mismatch between the WebRTC phone and Asterisk. The SDP offer contains codecs that Asterisk cannot accept.
Fixes:
# 1. Check what codecs Asterisk has available
asterisk -rx 'core show codecs'
# 2. Verify the phone template allows compatible codecs
# In ViciDial Admin > Templates > your WebRTC template
# Must include: allow=ulaw (minimum)
# Recommended: allow=ulaw,opus
# 3. If using Opus but codec_opus is not compiled:
asterisk -rx 'module show like opus'
# If missing, either recompile Asterisk with --enable-opus
# or remove opus from the allow list in the template
# 4. If Asterisk was compiled without pjproject bundled:
# The 488 error can occur because SRTP/DTLS negotiation fails
# Solution: recompile with --with-pjproject-bundled
Error: "481 Subscription does not exist"
Symptoms: Phone registers successfully, works for a period (often exactly 10 minutes = 600 seconds), then drops with a 481 error. Agent is kicked from the session.
Cause: SIP registration expires and the re-registration fails. The WebRTC client's registerExpires timer (default 600 seconds in sip.js) does not align with Asterisk's expectations.
Fixes:
- Adjust qualifyfreq in the template:
; In your WebRTC template, increase qualify frequency
qualifyfreq=30
- Modify the webphone JavaScript (if self-hosted):
In the ViciPhone/CyburPhone sip.js or configuration file, find registerExpires and increase it:
// Change from default
registerExpires: 600
// To a longer duration
registerExpires: 3600
- Check Asterisk's default registration timeout:
asterisk -rx 'sip show settings' | grep -i registra
# defaultexpiry: Should be >= 3600
# maxexpiry: Should be >= 3600
In /etc/asterisk/sip.conf:
[general]
defaultexpiry=3600
maxexpiry=7200
minexpiry=60
One-Way Audio on WebRTC Calls
Symptoms: Agent can hear the other party but the other party cannot hear the agent (or vice versa).
This is the most common WebRTC issue. It is almost always a NAT traversal problem.
Diagnostic flowchart:
One-way audio?
|
v
Is nat=force_rport,comedia in template? ---NO---> Add it
|YES
v
Is directmedia=no in template? ---NO---> Add it
|YES
v
Is icesupport=yes in template? ---NO---> Add it
|YES
v
Is stunaddr configured in rtp.conf? ---NO---> Add stun.l.google.com:19302
|YES
v
Are UDP ports 10000-20000 open? ---NO---> Open them in firewall
|YES
v
Is externip set in sip.conf? ---NO---> Add externip=YOUR_PUBLIC_IP
|YES
v
Is the agent behind symmetric NAT? ---MAYBE---> Deploy a TURN server (Section 7B)
|NO
v
Check browser console for ICE failures (chrome://webrtc-internals/)
Quick fixes to try:
# 1. Ensure externip is set in sip.conf
grep externip /etc/asterisk/sip.conf
# Should show: externip=YOUR_PUBLIC_IP
# If missing, add it:
# externip=203.0.113.50
# localnet=192.168.0.0/255.255.0.0 (your internal network)
# 2. Verify RTP ports are open
iptables -L -n | grep -E '10000|20000'
# Add if missing:
iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT
# 3. Check for STUN connectivity from the server
# Install stun client if available
stun stun.l.google.com:19302
Phone Registers Then Drops After 10 Minutes
See the "481 Subscription does not exist" section above. This is the same issue — the SIP registration expires.
Additional check: Ensure the browser tab stays active. Some browsers throttle background tabs, which can prevent re-registration keepalives.
Chrome setting to prevent tab throttling:
chrome://flags/#calculate-native-win-occlusion
Set to "Disabled" — prevents Chrome from throttling backgrounded windows.
Echo / Feedback on WebRTC Calls
Cause: Usually the agent's headset or speakers feeding back into the microphone. Can also be caused by Asterisk mixing media incorrectly.
Fixes:
- Use a headset — echo is worst with laptop speakers + built-in microphone
- Disable browser echo cancellation test:
In Chrome: chrome://flags/#enable-webrtc-apm-aec3 — ensure it is "Default" or "Enabled"
- Asterisk-side: Ensure RTCP feedback is working:
; In template
avpf=yes
rtcp_mux=yes
"ViciPhone Fails: res_pjsip_transport_websocket.so Not Running"
Symptoms: ViciPhone cannot connect. Asterisk log shows the PJSIP WebSocket transport module failed to load.
Cause: Asterisk was compiled without PJSIP support, or pjproject is not bundled.
Fix:
# Check if the module file exists
find / -name "res_pjsip_transport_websocket.so" 2>/dev/null
# If the file exists but is not loaded:
asterisk -rx 'module load res_pjsip_transport_websocket.so'
# If the file does not exist, Asterisk needs recompilation with:
# --with-pjproject-bundled
"SRTP UNPROTECT failed" in Asterisk Logs
Calls connect but audio is garbled or silent. Cause: DTLS key exchange failure. Fixes: verify res_srtp.so is loaded, check certificate file permissions, ensure dtlsverify=no in template, try certbot renew --force-renewal.
Complete Error Reference Table
| Error Message | Section | Primary Cause | Quick Fix |
|---|---|---|---|
conn.failed / WebSocket failed |
Network | Port 8089 blocked or cert issue | Open port, check cert |
488 Not Acceptable Here |
Codec | Codec mismatch or no SRTP | Fix template codecs, check pjproject |
481 Subscription does not exist |
Registration | Registration timeout | Increase qualifyfreq and registerExpires |
| One-way audio | NAT | Missing STUN/NAT config | Add stunaddr, set externip, open RTP ports |
| No audio at all | NAT/SRTP | DTLS handshake failed | Check cert paths, verify res_srtp loaded |
| Echo/feedback | Audio | Headset bleed-through | Use quality headset, check AEC settings |
| Phone shows "Unregistered" | Auth | Wrong credentials or template | Verify phone login/pass, check template |
SSL_shutdown() failed |
TLS | Certificate or TLS version mismatch | Update cert, check tlscipher in http.conf |
Conference number not found |
MeetMe | Agent cannot enter conference | Check DAHDI: dahdi_cfg -v, modprobe dahdi |
| SRTP UNPROTECT failed | Encryption | Key exchange failure | Verify cert permissions, set dtlsverify=no |
15. Performance Tuning
Codec Optimization
| Codec | Bandwidth per Agent | CPU Load | Quality | Recommendation |
|---|---|---|---|---|
| Opus (narrowband) | ~12 kbps | Low | Good | Best balance for WebRTC voice |
| Opus (wideband) | ~24 kbps | Medium | Excellent | High-quality, slight CPU increase |
| Opus (fullband) | ~48 kbps | Medium-High | Outstanding | Overkill for call center voice |
| G.711 ulaw | 64 kbps | Very Low | Good | Zero transcoding to PSTN trunks |
| G.722 | 64 kbps | Low | Very Good | Wideband without high CPU |
Recommendation for call centers:
; Template: prioritize ulaw for PSTN compatibility, Opus for quality
disallow=all
allow=ulaw,opus
Why ulaw first: Most PSTN trunks use G.711 (ulaw/alaw). If you prioritize Opus, Asterisk must transcode every call from Opus to G.711 before sending to the trunk. This adds CPU load and latency. By offering ulaw first, the WebRTC client and Asterisk negotiate ulaw when possible, and the trunk path requires zero transcoding.
If you prioritize quality over CPU: Put Opus first:
disallow=all
allow=opus,ulaw
Bandwidth Requirements
| Agents | Codec | Bandwidth (Up + Down) | Notes |
|---|---|---|---|
| 1 | G.711 ulaw | ~128 kbps | 64 kbps each direction |
| 1 | Opus (narrowband) | ~24 kbps | 12 kbps each direction |
| 10 | G.711 ulaw | ~1.3 Mbps | |
| 10 | Opus | ~240 kbps | |
| 50 | G.711 ulaw | ~6.4 Mbps | |
| 50 | Opus | ~1.2 Mbps | |
| 100 | G.711 ulaw | ~12.8 Mbps | |
| 100 | Opus | ~2.4 Mbps |
Add ~20% overhead for SIP signaling, RTCP, and packet headers.
Server Sizing for WebRTC
| Concurrent WebRTC Agents | CPU Cores | RAM | Notes |
|---|---|---|---|
| 1-20 | 4 | 4 GB | Minimal deployment |
| 20-50 | 8 | 8 GB | Standard deployment |
| 50-100 | 12+ | 16 GB | Monitor CPU during peak. Transcoding (Opus to ulaw) is the bottleneck |
| 100-200 | 16+ | 32 GB | Consider splitting across multiple Asterisk servers |
| 200+ | Cluster | Cluster | Use ViciDial's native cluster support with multiple telephony servers |
Asterisk Tuning for WebRTC Scale
For 50+ agents, increase file descriptor limits (each WebSocket uses one): add LimitNOFILE=65536 in a systemd override for the Asterisk service. In http.conf, increase sessionlimit from the default 100 to 500+ for large deployments. With rtcp_mux=yes, each call uses 1 RTP port; the default range of 10000-20000 supports ~10,000 concurrent calls.
16. Security Considerations
TLS Configuration Hardening
In /etc/asterisk/http.conf:
; Use strong cipher suites only
; Disable weak ciphers (RC4, DES, 3DES, export-grade)
tlscipher = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256
; Disable older TLS versions (if your Asterisk version supports this)
; Note: Asterisk http.conf does not have a direct TLS version setting,
; but the cipher selection above effectively enforces TLS 1.2+
fail2ban for WebSocket (WSS)
Create a fail2ban filter at /etc/fail2ban/filter.d/asterisk-websocket.conf matching failed registration patterns (Registration from .* failed for '<HOST>'), and a jail at /etc/fail2ban/jail.d/asterisk-websocket.conf:
[asterisk-websocket]
enabled = true
filter = asterisk-websocket
action = iptables-allports[name=asterisk-wss, protocol=all]
logpath = /var/log/asterisk/messages
maxretry = 5
findtime = 300
bantime = 3600
Rate Limiting WebSocket Connections
# iptables: limit to 10 new connections per minute per source IP on port 8089
iptables -A INPUT -p tcp --dport 8089 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 8089 -m state --state NEW -m recent --update --seconds 60 --hitcount 10 -j DROP
iptables -A INPUT -p tcp --dport 8089 -j ACCEPT
# firewalld alternative:
firewall-cmd --add-rich-rule='rule family=ipv4 port port=8089 protocol=tcp limit value=10/m accept' --permanent
Certificate Monitoring
# Daily cron: alert if cert expires within 14 days
0 6 * * * root openssl x509 -checkend 1209600 -noout -in /etc/letsencrypt/live/dialer.example.com/fullchain.pem || echo "SSL cert expiring" | mail -s "CERT ALERT" [email protected]
General Security Best Practices
- Never expose port 8088 (non-TLS HTTP) to the internet — only 8089 (TLS) should be reachable
- Change default phone passwords — do not use trivial passwords like
1234or the extension number - Use HTTPS everywhere — redirect HTTP to HTTPS in Apache configuration
- Keep Asterisk updated — WebRTC vulnerabilities are patched in point releases
- Monitor for brute force — check Asterisk logs regularly for failed registration attempts
- Restrict the
contextin your WebRTC template — do not usecontext=defaultifdefaulthas unrestricted dialing. Use a restrictive context that only allows ViciDial-managed calls
17. Version Compatibility Matrix
ViciBox Versions
| ViciBox | openSUSE Leap | Asterisk | WebRTC Support | ViciDial SVN | Notes |
|---|---|---|---|---|---|
| 8.0 | 42.3 | 13.x | Basic | ~2600+ | First WebRTC support. Requires manual setup |
| 8.1 | 42.3 | 13.x | Improved | ~2800+ | Added vicibox-ssl and ViciPhone template |
| 9.0 | 15.1 | 13.x | Good | ~3100+ | Better SSL handling |
| 10.0 | 15.3 | 13.x | Good | ~3400+ | vicibox-ssl improvements |
| 11.0 | 15.5 | 16.30 | Very Good | 3543+ | Asterisk 16 with simplified webrtc=yes |
| 12.0 | 15.6 | 18.x | Excellent | Latest | PJSIP native, Asterisk 18 LTS, recommended |
Asterisk Versions
| Asterisk | SIP Driver | WebRTC | Simplified Config | LTS Until | Notes |
|---|---|---|---|---|---|
| 11 | chan_sip only | No | N/A | EOL | Does NOT support WebSocket. Cannot use WebRTC |
| 13 | chan_sip + chan_pjsip | Yes | No | EOL | First version with WebSocket support. Manual DTLS/SRTP config required |
| 16 | chan_sip + chan_pjsip | Yes | webrtc=yes |
EOL (Oct 2025) | Added webrtc=yes convenience option for PJSIP endpoints |
| 18 | chan_sip + chan_pjsip | Yes | webrtc=yes |
Oct 2027 | Current LTS. Recommended for production |
| 20 | chan_pjsip (chan_sip removed) | Yes | webrtc=yes |
Oct 2028 | chan_sip is gone — PJSIP only. Check ViciDial compatibility before upgrading |
| 21 | chan_pjsip | Yes | webrtc=yes |
Short-term | Not recommended for ViciDial (short-term release) |
Browser Compatibility
| Browser | Minimum Version | WebRTC | Audio Codecs | Notes |
|---|---|---|---|---|
| Chrome | 80+ | Full | Opus, G.711, G.722 | Best support. Recommended |
| Firefox | 78+ | Full | Opus, G.711 | Works well |
| Edge | 80+ (Chromium) | Full | Same as Chrome | Same engine as Chrome |
| Safari | 14.1+ | Partial | Opus, G.711 | Improved but less reliable. Use with caution |
| Safari iOS | 14.5+ | Partial | Opus, G.711 | Mobile WebRTC. Battery drain concern |
| Chrome Android | 80+ | Full | Opus, G.711 | Works but agents need good headset |
Key version notes: webrtc=yes shortcut and dtls_auto_generate_cert are available from Asterisk 16+. chan_sip WebSocket support was removed in Asterisk 20 (PJSIP only). Opus may require separate compilation depending on build options.
18. Quick-Start Checklist
Use this as a rapid reference after reading the full guide. Check off each item as you complete it.
Pre-Flight
[ ] Domain name (FQDN) resolves to server IP
[ ] DNS A record verified: dig +short dialer.example.com
[ ] Firewall ports open: 443/tcp, 8089/tcp, 10000-20000/udp
[ ] Asterisk version >= 13 (16+ recommended)
[ ] ViciDial SVN >= 2800 (3543+ recommended)
SSL Certificate
[ ] Certbot installed
[ ] Certificate issued: certbot certonly --webroot ...
[ ] Apache configured with fullchain.pem and privkey.pem
[ ] Apache restarted and HTTPS working
[ ] Auto-renewal configured (certbot-renew.timer or cron)
Asterisk Configuration
[ ] /etc/asterisk/http.conf: tlsenable=yes, port 8089, cert paths
[ ] Asterisk restarted: asterisk -rx 'core restart now'
[ ] http show status shows /ws endpoint
[ ] Port 8089 listening: ss -tlnp | grep 8089
[ ] SSL cert valid on 8089: openssl s_client -connect localhost:8089
Modules
[ ] res_http_websocket.so loaded
[ ] res_crypto.so loaded
[ ] res_srtp.so loaded
[ ] res_rtp_asterisk.so loaded
[ ] codec_opus.so loaded (recommended)
STUN/TURN
[ ] rtp.conf: icesupport=yes
[ ] rtp.conf: stunaddr=stun.l.google.com:19302
[ ] (Optional) coturn installed and running for TURN relay
ViciDial Configuration
[ ] System Settings: Webphone URL set
[ ] System Settings: Enable WebRTC Phone = Y
[ ] Server Settings: External Server IP = public IP
[ ] Server Settings: Web Socket URL = wss://FQDN:8089/ws
[ ] Template created with all WebRTC parameters
[ ] Template: certificate paths correct and files exist
Phone Setup
[ ] Phone: Set As Webphone = Y
[ ] Phone: Use External Server IP = Y
[ ] Phone: Template ID = your WebRTC template
[ ] Phone: Webphone Auto-Answer = Y (optional)
[ ] Phone assigned to user
Testing
[ ] Agent logs in via HTTPS
[ ] Browser allows microphone
[ ] Webphone shows "Registered"
[ ] Test call: two-way audio confirmed
[ ] Stress test: multiple agents simultaneously
Appendix A: Troubleshooting Decision Tree
Agent cannot use WebRTC phone
|
+-- Can agent load https://dialer.example.com ?
| |
| +-- NO --> Fix Apache SSL / DNS / firewall port 443
| |
| +-- YES
| |
| +-- Does browser ask for microphone permission?
| |
| +-- NO --> Page is loading via HTTP not HTTPS, or
| | browser extension is blocking
| |
| +-- YES (agent clicks Allow)
| |
| +-- Does webphone show "Registered"?
| |
| +-- NO --> "conn.failed" or "connection error"
| | |
| | +-- Is port 8089 open? (ss -tlnp | grep 8089)
| | | +-- NO --> Fix http.conf / restart Asterisk
| | |
| | +-- Is cert valid on 8089? (openssl s_client)
| | | +-- NO --> Fix cert path in http.conf
| | |
| | +-- Is WSS URL correct in server settings?
| | | +-- NO --> Fix: wss://FQDN:8089/ws
| | |
| | +-- Is res_http_websocket loaded?
| | +-- NO --> module load res_http_websocket.so
| |
| +-- YES (registered)
| |
| +-- Can agent make/receive calls?
| |
| +-- NO --> 488 error?
| | +-- YES --> Fix codec template (allow=ulaw)
| |
| +-- YES but no audio / one-way audio
| | |
| | +-- Check STUN config in rtp.conf
| | +-- Check externip in sip.conf
| | +-- Check RTP port firewall (10000-20000/udp)
| | +-- Check nat=force_rport,comedia in template
| | +-- Try deploying TURN server
| |
| +-- YES, two-way audio works
| |
| +-- Drops after 10 minutes?
| | +-- Increase qualifyfreq and registerExpires
| |
| +-- SUCCESS
Appendix B: Useful Diagnostic Commands
# === Certificate Checks ===
# Check Apache SSL cert
echo | openssl s_client -connect dialer.example.com:443 2>/dev/null | openssl x509 -noout -subject -dates
# Check Asterisk WSS cert
echo | openssl s_client -connect dialer.example.com:8089 2>/dev/null | openssl x509 -noout -subject -dates
# Check cert expiry (days remaining)
echo | openssl s_client -connect dialer.example.com:443 2>/dev/null | openssl x509 -noout -enddate
# === Asterisk Status ===
# HTTP/WebSocket status
asterisk -rx 'http show status'
# SIP peers (look for WebRTC phones)
asterisk -rx 'sip show peers'
# Active channels (look for WS transport)
asterisk -rx 'core show channels verbose'
# Module status
asterisk -rx 'module show like websocket'
asterisk -rx 'module show like srtp'
asterisk -rx 'module show like crypto'
asterisk -rx 'module show like opus'
# RTP settings
asterisk -rx 'rtp show settings'
# === Network ===
# Check listening ports
ss -tlnp | grep -E '443|8088|8089'
ss -ulnp | grep -E '10000|20000|3478'
# Test port reachability from external
nc -zv dialer.example.com 8089
# === Debugging (enable temporarily) ===
# SIP debug (very verbose)
asterisk -rx 'sip set debug on'
# Disable when done
asterisk -rx 'sip set debug off'
# PJSIP debug
asterisk -rx 'pjsip set logger on'
asterisk -rx 'pjsip set logger off'
References and Sources
Official Documentation
- Asterisk WebRTC Client Configuration: https://docs.asterisk.org/Configuration/WebRTC/Configuring-Asterisk-for-WebRTC-Clients/
- Asterisk ICE Configuration: https://docs.asterisk.org/Configuration/Miscellaneous/Interactive-Connectivity-Establishment-ICE-in-Asterisk/
- ViciBox SSL Documentation: https://docs.vicibox.com/en/latest/networking/vicibox-ssl.html
- Let's Encrypt / Certbot: https://certbot.eff.org/
ViciDial Forum Threads
- WebRTC on ViciBox 8.0 (30+ replies): https://www.vicidial.org/VICIDIALforum/viewtopic.php?t=38057
- WebRTC Problems: https://www.vicidial.org/VICIDIALforum/viewtopic.php?f=4&t=39839
- 488 Not Acceptable on WebRTC: https://www.vicidial.org/VICIDIALforum/viewtopic.php?f=4&t=40029
- ViciPhone official thread: https://www.vicidial.org/VICIDIALforum/viewtopic.php?f=3&t=35875
- ViciBox 8.1 WebRTC feature: https://www.vicidial.org/VICIDIALforum/viewtopic.php?f=8&t=38750
- Cluster mode with WebRTC: https://www.vicidial.org/VICIDIALforum/viewtopic.php?f=4&t=41396
Community Guides & Projects
- ViciPhone.com config guide: https://viciphone.com/?page_id=353
- Dialer.one install guide: https://dialer.one/index.php/how-to-install-a-webphone-viciphone-on-your-vicidial-server/
- Dialer.one debug guide: https://dialer.one/index.php/how-to-debug-webphones-for-vicidial/
- ViciPhone v3: https://github.com/vicimikec/ViciPhone | CyburPhone: https://github.com/carpenox/CyburPhone
- coturn: https://github.com/coturn/coturn | coturn guide: https://www.metered.ca/blog/coturn/
Tutorial 32 of the VoIP Infrastructure Series. Written March 2026. Consolidated from 30+ forum threads, official documentation, and production deployment experience.