Adding a SIP trunk in VICIdial means filling in four fields correctly under Admin → Carriers → Add A New Carrier. This post walks through each one, covers both registration-based and IP-authenticated trunks, and finishes with inbound DID routing.
What Your Provider Needs to Give You
Before touching VICIdial, get these from the carrier:
- Authentication method — username/password registration, or IP whitelist
- SIP proxy hostname or IP, and port (usually 5060)
- Codecs permitted (ulaw, alaw, g729)
- DID numbers and the format they will be presented in (E.164 with
+, national, or 10-digit) - Whether they expect the DID in the SIP
To:header or somewhere else
That last point causes more inbound failures than everything else combined. Ask explicitly.
The Four Carrier Fields
Registration String
Only used for credential-based trunks. Leave it empty for IP-authenticated ones.
register => username:password@sip.provider.com:5060/username
The trailing /username sets the extension your inbound calls will arrive on. Some providers want your DID there instead:
register => 15551234567:secretpass@sip.provider.com/15551234567
Account Entry
This is raw sip.conf content. VICIdial writes it into /etc/asterisk/sip-vicidial.conf.
Registration-based trunk:
[myprovider]
type=friend
username=15551234567
defaultuser=15551234567
secret=yourpassword
host=sip.provider.com
fromuser=15551234567
fromdomain=sip.provider.com
context=trunkinbound
insecure=port,invite
disallow=all
allow=ulaw
allow=alaw
dtmfmode=rfc2833
qualify=yes
nat=force_rport,comedia
canreinvite=no
IP-authenticated trunk — no secret, host is the carrier’s IP:
[myprovider]
type=friend
host=203.0.113.45
context=trunkinbound
insecure=port,invite
disallow=all
allow=ulaw
dtmfmode=rfc2833
qualify=yes
canreinvite=no
A few of these deserve explanation:
context=trunkinbound— this is the VICIdial inbound context. If you setcontext=default, inbound calls will hit your outbound dialplan and fail in confusing ways.insecure=port,invite— tells Asterisk not to re-authenticate inbound INVITEs from a peer you already authenticate outbound. Required for most trunks.canreinvite=no— keeps media flowing through the server. You need this for call recording. If you set it toyesto save bandwidth, your recordings will be silent.nat=force_rport,comedia— correct when the server is behind NAT. On a server with a public IP and no NAT,nat=nois cleaner.
If your server is behind NAT, you also need this in Admin → Servers → Modify → External SIP settings, or directly in the globals of sip.conf:
externip=203.0.113.10
localnet=192.168.1.0/255.255.255.0
Globals String
Usually left blank. Use it if you want a variable available across the dialplan:
TRUNKNAME=myprovider
Then reference it as ${TRUNKNAME} in the Dialplan Entry. Handy when you are swapping carriers frequently in testing.
Dialplan Entry
exten => _91NXXNXXXXXX,1,AGI(agi://127.0.0.1:4577/call_log)
exten => _91NXXNXXXXXX,n,Dial(SIP/myprovider/${EXTEN:1},,tTo)
exten => _91NXXNXXXXXX,n,Hangup()
The peer name after SIP/ must match the bracketed name in your Account Entry exactly. Case matters.
Applying and Verifying
Carrier changes are written out by the keepalive script. To force it:
/usr/share/astguiclient/ADMIN_keepalive_ALL.pl
asterisk -rx "sip reload"
Check registration:
asterisk -rx "sip show registry"
You want Registered. Common states and what they mean:
Request Sent— no response at all. Firewall blocking UDP 5060 outbound, or wrong hostname.Auth. Sent— credentials rejected. Check username, password, and whether the provider wants the DID as the username.Rejected— the provider actively refused. Usually an IP not yet whitelisted on their side.
Check peer state:
asterisk -rx "sip show peers"
asterisk -rx "sip show peer myprovider"
OK (23 ms) in the Status column means the qualify ping is working.
Firewall
Open the right ports before blaming the carrier:
# SIP signalling
firewall-cmd --permanent --add-port=5060/udp
# RTP media
firewall-cmd --permanent --add-port=10000-20000/udp
firewall-cmd --reload
Restrict these to the carrier’s IP ranges rather than leaving them open to the world. An open 5060 on a public IP will be scanned within hours.
Inbound DID Routing
Once calls arrive in trunkinbound, VICIdial routes them via its DID table. The default inbound context contains:
exten => _X.,1,AGI(agi-DID_route.agi)
exten => _X.,n,Hangup()
Then in Admin → Inbound → Show DIDs:
- Add a DID whose DID Pattern matches exactly what the carrier sends. If they send
+15551234567, the pattern must include the+or you must strip it in dialplan. - Set DID Route to
IN_GROUP. - Select your in-group.
To strip a leading + before the AGI sees it:
[trunkinbound]
exten => _+X.,1,Goto(trunkinbound,${EXTEN:1},1)
exten => _X.,1,AGI(agi-DID_route.agi)
exten => _X.,n,Hangup()
Then on the agent side, in Admin → Users → Agent Interface Options, set Agent Choose Ingroups: 1, and in the campaign set Allow Inbound and Blended: Y with your in-group ticked under Allowed Inbound Groups.
Watching an Inbound Call
asterisk -rvvvvv
sip set debug peer myprovider
Place a test call to the DID and read the INVITE. The To: header tells you exactly what string your DID pattern must match. If the INVITE never appears, the call is not reaching your server and the problem is upstream — firewall, routing, or the provider has not pointed the DID at your IP yet.
Summary
Four fields, one context name, and one matching peer name. The parts that trip people up are context=trunkinbound for inbound, canreinvite=no if you want recordings, and matching your DID pattern to exactly what arrives in the To: header rather than what you assume the carrier sends.