Skip to content

Deploying Asterisk PBX

Asterisk is the world’s most powerful open-source communications platform. Originally created by Mark Spencer in 1999, Asterisk has become the backbone of millions of telephony installations worldwide, from small business phone systems to large-scale call centers handling thousands of simultaneous calls.

As a software PBX (Private Branch Exchange), Asterisk transforms standard computing hardware into a sophisticated communications server. It supports a wide range of telephony protocols including SIP, IAX2, H.323, and integrates with traditional PSTN lines through hardware gateways.

Protocol Support

SIP, PJSIP, IAX2, WebRTC, H.323, and PSTN integration

Modern Architecture

Built on res_pjsip for robust SIP communications

Extensible Platform

ARI, AMI, AGI interfaces for custom integrations

Active Community

96.8% C codebase with GPL-2.0 license

Key Features

Asterisk provides enterprise-grade telephony capabilities that scale from home offices to enterprise deployments:

FeatureDescription
VoIP GatewayBridge between IP networks and traditional telephony
IVR SystemsInteractive Voice Response with custom menus
Conference BridgesMulti-party audio and video conferencing
VoicemailFull-featured voicemail with email integration
Call RecordingAutomatic and on-demand call recording
Queue ManagementACD with skill-based routing and callbacks
WebRTC SupportBrowser-based calling without plugins
Call Detail RecordsComprehensive CDR for billing and analytics

Prerequisites

Before deploying Asterisk on Klutch.sh, ensure you have:

  • A Klutch.sh account with an active project
  • A GitHub repository for your Asterisk configuration
  • Basic understanding of SIP telephony concepts
  • (Optional) A SIP trunk provider for PSTN connectivity

Project Structure

Organize your Asterisk deployment with proper configuration management:

  • Directoryasterisk-pbx/
    • Dockerfile
    • docker-compose.yml (local development)
    • README.md
    • Directoryconfig/
      • pjsip.conf (SIP endpoints and trunks)
      • extensions.conf (dialplan)
      • modules.conf (module loading)
      • rtp.conf (RTP media settings)
      • voicemail.conf (voicemail configuration)
      • queues.conf (call queue settings)
      • musiconhold.conf (hold music)
      • logger.conf (logging configuration)

Deployment Configuration

Dockerfile

Create a Dockerfile for your Asterisk deployment:

Dockerfile
FROM andrius/asterisk:stable
# Set Asterisk user/group IDs
ENV ASTERISK_UID=1000
ENV ASTERISK_GID=1000
# Copy custom configurations
COPY config/ /etc/asterisk/
# Expose SIP and RTP ports
EXPOSE 5060/udp 5060/tcp
EXPOSE 5038/tcp
EXPOSE 10000-10500/udp
# Default command runs Asterisk in foreground
CMD ["asterisk", "-f", "-vvv"]

PJSIP Configuration

Create your SIP configuration in config/pjsip.conf:

config/pjsip.conf
; Transport configuration
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
external_media_address=YOUR_EXTERNAL_IP
external_signaling_address=YOUR_EXTERNAL_IP
local_net=10.0.0.0/8
local_net=172.16.0.0/12
local_net=192.168.0.0/16
; WebSocket transport for WebRTC
[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0:8089
; Template for authenticated endpoints
[endpoint-auth](!)
type=endpoint
transport=transport-udp
context=internal
disallow=all
allow=ulaw
allow=alaw
allow=g722
allow=opus
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
; Template for authentication
[auth-userpass](!)
type=auth
auth_type=userpass
; Template for AOR (Address of Record)
[aor-single-reg](!)
type=aor
max_contacts=1
remove_existing=yes
qualify_frequency=60
; Example extension 1001
[1001](endpoint-auth)
auth=1001-auth
aors=1001-aor
callerid="User One" <1001>
[1001-auth](auth-userpass)
username=1001
password=securepassword123
[1001-aor](aor-single-reg)
; Example extension 1002
[1002](endpoint-auth)
auth=1002-auth
aors=1002-aor
callerid="User Two" <1002>
[1002-auth](auth-userpass)
username=1002
password=securepassword456
[1002-aor](aor-single-reg)

Dialplan Configuration

Create your dialplan in config/extensions.conf:

config/extensions.conf
[general]
static=yes
writeprotect=no
clearglobalvars=no
[globals]
OPERATOR=1001
VOICEMAIL_CONTEXT=default
[internal]
; Internal extension dialing (1XXX)
exten => _1XXX,1,NoOp(Calling internal extension ${EXTEN})
same => n,Set(CALLERID(name)=${CALLERID(name)})
same => n,Dial(PJSIP/${EXTEN},30,tTrR)
same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
same => n(busy),VoiceMail(${EXTEN}@default,b)
same => n,Hangup()
same => n(unavail),VoiceMail(${EXTEN}@default,u)
same => n,Hangup()
; Voicemail access
exten => *98,1,NoOp(Voicemail Menu)
same => n,VoiceMailMain(${CALLERID(num)}@default)
same => n,Hangup()
; Echo test
exten => *43,1,NoOp(Echo Test)
same => n,Answer()
same => n,Playback(demo-echotest)
same => n,Echo()
same => n,Playback(demo-echodone)
same => n,Hangup()
; Conference room
exten => *300,1,NoOp(Conference Room)
same => n,Answer()
same => n,ConfBridge(1)
same => n,Hangup()
; Speaking clock
exten => *60,1,NoOp(Speaking Clock)
same => n,Answer()
same => n,SayUnixTime(,,IMp)
same => n,Hangup()
; Invalid extension handler
exten => i,1,NoOp(Invalid Extension)
same => n,Playback(invalid)
same => n,Hangup()

RTP Configuration

Configure RTP media ports in config/rtp.conf:

config/rtp.conf
[general]
rtpstart=10000
rtpend=10500
rtpchecksums=no
dtmftimeout=3000
rtcpinterval=5000
; ICE support for WebRTC
icesupport=yes
stunaddr=stun.l.google.com:19302

Modules Configuration

Control module loading in config/modules.conf:

config/modules.conf
[modules]
autoload=yes
; Core SIP module
load = res_pjsip.so
load = res_pjsip_transport_websocket.so
load = res_pjsip_authenticator_digest.so
load = res_pjsip_endpoint_identifier_ip.so
load = res_pjsip_session.so
load = res_pjsip_sdp_rtp.so
load = res_pjsip_dtmf_info.so
load = chan_pjsip.so
; Applications
load = app_dial.so
load = app_playback.so
load = app_voicemail.so
load = app_confbridge.so
load = app_queue.so
load = app_record.so
; Disable legacy SIP driver
noload = chan_sip.so
; Disable unused modules
noload = chan_alsa.so
noload = chan_console.so
noload = chan_oss.so
noload = chan_phone.so
noload = chan_skinny.so
noload = chan_unistim.so
noload = chan_modem.so

Voicemail Configuration

Set up voicemail in config/voicemail.conf:

config/voicemail.conf
[general]
format=wav49|wav
serveremail=asterisk@yourdomain.com
attach=yes
skipms=3000
maxsilence=10
silencethreshold=128
maxlogins=3
emaildateformat=%A, %B %d, %Y at %r
pagerdateformat=%A, %B %d, %Y at %r
sendvoicemail=yes
envelope=yes
delete=no
minmessage=3
maxmessage=180
[default]
1001 => 1234,User One,user1@example.com
1002 => 1234,User Two,user2@example.com

Local Development

Test your configuration locally with Docker Compose:

docker-compose.yml
services:
asterisk:
build: .
container_name: asterisk-pbx
hostname: asterisk
restart: unless-stopped
ports:
- "5060:5060/udp"
- "5060:5060/tcp"
- "5038:5038/tcp"
- "10000-10500:10000-10500/udp"
volumes:
- ./config:/etc/asterisk
- asterisk-data:/var/lib/asterisk
- asterisk-logs:/var/log/asterisk
- asterisk-spool:/var/spool/asterisk
environment:
- ASTERISK_UID=1000
- ASTERISK_GID=1000
cap_add:
- NET_ADMIN
- SYS_PTRACE
volumes:
asterisk-data:
asterisk-logs:
asterisk-spool:

Deploying to Klutch.sh

  1. Push your repository to GitHub

    Commit your Dockerfile and configuration files to your GitHub repository:

    Terminal window
    git add .
    git commit -m "Initial Asterisk PBX configuration"
    git push origin main
  2. Create a new app on Klutch.sh

    Navigate to your Klutch.sh project dashboard and create a new app. Connect your GitHub repository containing the Asterisk configuration.

  3. Configure the build settings

    Klutch.sh will automatically detect your Dockerfile. Verify the following settings:

    • Build Type: Dockerfile
    • Dockerfile Path: ./Dockerfile
    • Build Context: .
  4. Set up persistent storage

    Add volumes for data persistence:

    • Configuration: Mount path /etc/asterisk, Size: 1 GB
    • Data: Mount path /var/lib/asterisk, Size: 5 GB
    • Logs: Mount path /var/log/asterisk, Size: 2 GB
    • Spool: Mount path /var/spool/asterisk, Size: 10 GB
  5. Configure networking

    In the app settings, configure the network:

    • Traffic Type: Select TCP for SIP signaling
    • Port: 5060
    • Note: RTP media ports (10000-10500) require UDP which needs special configuration
  6. Deploy the application

    Click the Deploy button to build and launch your Asterisk PBX. Monitor the build logs for any configuration issues.

SIP Trunk Configuration

Connect to a VoIP provider for PSTN calling:

config/pjsip.conf (append)
; SIP Trunk to VoIP Provider
[trunk-provider]
type=endpoint
transport=transport-udp
context=from-trunk
disallow=all
allow=ulaw
allow=alaw
direct_media=no
from_domain=sip.provider.com
outbound_auth=trunk-auth
aors=trunk-aor
[trunk-auth]
type=auth
auth_type=userpass
username=your_account
password=your_password
[trunk-aor]
type=aor
contact=sip:sip.provider.com:5060
[trunk-identify]
type=identify
endpoint=trunk-provider
match=sip.provider.com
[trunk-registration]
type=registration
transport=transport-udp
outbound_auth=trunk-auth
server_uri=sip:sip.provider.com
client_uri=sip:your_account@sip.provider.com
retry_interval=60

Add outbound routing to your dialplan:

config/extensions.conf (append)
; Outbound calling via trunk
[internal]
; US numbers (10 digit)
exten => _NXXNXXXXXX,1,NoOp(Outbound Call to ${EXTEN})
same => n,Set(CALLERID(num)=YOUR_DID)
same => n,Dial(PJSIP/${EXTEN}@trunk-provider,60)
same => n,Hangup()
; US numbers with 1 prefix
exten => _1NXXNXXXXXX,1,NoOp(Outbound Call to ${EXTEN})
same => n,Set(CALLERID(num)=YOUR_DID)
same => n,Dial(PJSIP/${EXTEN}@trunk-provider,60)
same => n,Hangup()

Asterisk Manager Interface

Enable AMI for external integrations:

config/manager.conf
[general]
enabled=yes
port=5038
bindaddr=0.0.0.0
[admin]
secret=your_ami_password
deny=0.0.0.0/0.0.0.0
permit=10.0.0.0/255.0.0.0
permit=172.16.0.0/255.240.0.0
permit=192.168.0.0/255.255.0.0
read=all
write=all
writetimeout=5000

WebRTC Integration

Enable browser-based calling with WebRTC:

config/http.conf
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/asterisk/keys/asterisk.pem
tlsprivatekey=/etc/asterisk/keys/asterisk.key
config/pjsip.conf (WebRTC endpoint)
[webrtc-phones](!)
type=endpoint
transport=transport-wss
context=internal
disallow=all
allow=opus
allow=ulaw
dtls_auto_generate_cert=yes
webrtc=yes
use_avpf=yes
ice_support=yes
media_encryption=dtls
dtls_verify=fingerprint
dtls_setup=actpass
rtcp_mux=yes
[webrtc-user](webrtc-phones)
auth=webrtc-user-auth
aors=webrtc-user-aor
callerid="WebRTC User" <2001>
[webrtc-user-auth]
type=auth
auth_type=userpass
username=webrtcuser
password=webrtcpass
[webrtc-user-aor]
type=aor
max_contacts=5
remove_existing=yes

Monitoring and Maintenance

CLI Commands

Access the Asterisk CLI for management:

CommandDescription
pjsip show endpointsList all SIP endpoints
pjsip show registrationsShow trunk registrations
core show channelsDisplay active calls
queue showShow call queue status
voicemail show usersList voicemail accounts
module showShow loaded modules
sip set debug onEnable SIP debugging

Health Checks

Monitor your Asterisk instance:

Terminal window
# Check if Asterisk is running
docker exec asterisk-pbx asterisk -rx "core show version"
# View active calls
docker exec asterisk-pbx asterisk -rx "core show channels"
# Check endpoint status
docker exec asterisk-pbx asterisk -rx "pjsip show endpoints"
# View recent calls
docker exec asterisk-pbx asterisk -rx "cdr show"

Security Best Practices

Strong Passwords

Use complex passwords for all SIP accounts and change defaults immediately

Firewall Rules

Restrict SIP access to known IP ranges and VPN connections

Fail2ban Integration

Implement Fail2ban to block brute force attempts on SIP

TLS/SRTP

Enable encryption for signaling and media when possible

Security hardening recommendations:

config/pjsip.conf (security)
; Reject requests from unknown endpoints
[global]
type=global
endpoint_identifier_order=ip,username
default_from_user=asterisk
keep_alive_interval=90
; IP-based access control
[acl]
type=acl
deny=0.0.0.0/0.0.0.0
permit=10.0.0.0/255.0.0.0
permit=192.168.0.0/255.255.0.0
; Apply ACL to transport
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
allow_reload=yes

Troubleshooting

Common issues and solutions:

IssueCauseSolution
Registration failuresWrong credentials or networkCheck pjsip.conf auth settings and firewall
No audio (one-way)NAT traversal issuesConfigure external_media_address in transport
Echo or delayCodec mismatch or network latencyUse consistent codecs, check network QoS
Calls drop after 30 secondsSIP timeout or session timerDisable session timers or increase timeout
DTMF not workingWrong DTMF modeSet dtmf_mode=rfc4733 in endpoint config

Enable verbose debugging:

config/logger.conf
[general]
exec_after_rotate=gzip -9 ${filename}.2
[logfiles]
console => notice,warning,error,debug
messages => notice,warning,error
security => security
debug => debug

Additional Resources