← All Tutorials

WebRTC & ViciPhone Complete Setup Guide for ViciDial

ViciDial Administration Advanced 48 min read #32

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

  1. What is ViciPhone / WebRTC?
  2. Prerequisites Checklist
  3. SSL Certificate Setup with Let's Encrypt
  4. Asterisk HTTP / WebSocket Configuration
  5. PJSIP TLS Transport Setup
  6. Asterisk Module Verification
  7. STUN/TURN Server Configuration
  8. ViciDial System Settings
  9. Phone Template Configuration
  10. User / Phone Assignment
  11. Browser Configuration & Agent Requirements
  12. Testing Your Setup
  13. Cluster / Multi-Server WebRTC
  14. Troubleshooting
  15. Performance Tuning
  16. Security Considerations
  17. Version Compatibility Matrix
  18. 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

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


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:

  1. Email address — for Let's Encrypt notifications (expiry warnings, etc.)
  2. FQDN — the fully qualified domain name (e.g., dialer.example.com)

It will then:

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:

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:

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:

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

Common mistakes:

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:

  1. Go to Admin > Templates
  2. Find your template (e.g., WEBRTC)
  3. Click to edit and verify all parameters are saved correctly
  4. 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:

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.

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:

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

  1. Log in to the ViciDial agent interface: https://dialer.example.com/agc/vicidial.php
  2. Enter user credentials and the WebRTC phone credentials
  3. Allow microphone access when prompted
  4. 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

  1. Log the agent in and ensure the webphone is registered
  2. Have the agent make a manual dial or receive an inbound call
  3. 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:

  1. Press F12 (or Ctrl+Shift+J)
  2. Go to the Console tab
  3. Look for ICE candidate messages
  4. 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

  1. Each Asterisk server needs its own SSL certificate — the certificate must match the FQDN of that specific server
  2. Each server needs its own WSS URL — configured in Admin > Servers
  3. Each server may need its own phone template — if certificate paths differ between servers
  4. The web server (Admin/Agent UI) only needs one certificate — for the main HTTPS interface
  5. Agents connect to the Asterisk server assigned to their phone — not the web server

Step-by-Step Cluster Setup

  1. DNS: Create a separate A record for each Asterisk server (dialer1.example.com, dialer2.example.com, etc.)

  2. SSL on each server: Run certbot certonly --webroot -d dialerN.example.com on each Asterisk server. Alternative: use a wildcard cert (*.example.com) via DNS-01 challenge and deploy the same cert to all servers.

  3. http.conf on each server: Set tlscertfile and tlsprivatekey to the server-specific cert paths.

  4. Per-server templates: If certificate paths differ between servers, create separate templates (e.g., WEBRTC_DIALER1, WEBRTC_DIALER2) with the matching dtlscertfile/dtlsprivatekey paths. If using a wildcard cert with identical paths, one template works for all.

  5. 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
  1. 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:

  1. Adjust qualifyfreq in the template:
; In your WebRTC template, increase qualify frequency
qualifyfreq=30
  1. 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
  1. 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:

  1. Use a headset — echo is worst with laptop speakers + built-in microphone
  2. Disable browser echo cancellation test:

In Chrome: chrome://flags/#enable-webrtc-apm-aec3 — ensure it is "Default" or "Enabled"

  1. 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

  1. Never expose port 8088 (non-TLS HTTP) to the internet — only 8089 (TLS) should be reachable
  2. Change default phone passwords — do not use trivial passwords like 1234 or the extension number
  3. Use HTTPS everywhere — redirect HTTP to HTTPS in Apache configuration
  4. Keep Asterisk updated — WebRTC vulnerabilities are patched in point releases
  5. Monitor for brute force — check Asterisk logs regularly for failed registration attempts
  6. Restrict the context in your WebRTC template — do not use context=default if default has 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

ViciDial Forum Threads

Community Guides & Projects


Tutorial 32 of the VoIP Infrastructure Series. Written March 2026. Consolidated from 30+ forum threads, official documentation, and production deployment experience.

Need expert help with your setup?

VoIP infrastructure consulting, AI voice agent integration, monitoring stacks, scaling — I've done it all in production.

Get a Free Consultation