GuidesChat and emailAsterisk phone system

Run your own phone system with Asterisk

Asterisk 22 LTS on Debian 13, your own phone system with extensions that call each other, voicemail and an echo test, calls encrypted with TLS and SRTP, phones behind home routers, and fail2ban against SIP scanners.

Tested on Asterisk 22.11.0 on Debian 13 (trixie) on a Melonslab server Updated September 27, 2026

Recommended server for this guide

VC-S Micro · 2 vCPU · 8 GB Memory · 250 GB Storage

Month to month, no lock-in 7-day money-back guarantee

€7.99/mo

Deploy now
On this page

What you will set up

Asterisk is the open source telephone exchange behind many office phone systems. Phones and SIP apps register with it under an extension number, and it connects calls between them, records voicemail and answers with menus.

This guide sets up plain Asterisk, configured in text files, with no web interface: two extensions, 101 and 102, that call each other, voicemail when nobody answers, and an echo test on 600. Phones connect over TLS on port 5061 with a Let's Encrypt certificate, and the audio is encrypted with SRTP.

Debian 13 has no Asterisk package, and the Asterisk project publishes no container image, so step 1 builds the current long-term support release, Asterisk 22, from source. It is supported with bug fixes until October 2028 and with security fixes until October 2029. Asterisk runs under systemd as a user of its own, asterisk, not as root.

Every step below was run on a fresh Melonslab VC-P Alloy (2 vCPU, 8 GB) with Debian 13:

  • Asterisk 22.11.0 was built in about 6 minutes.
  • Two SIP apps registered over TLS with the Let's Encrypt certificate: one on a computer behind a home router, over IPv4, and one over IPv6 from the server itself.
  • They called each other in both directions, and called the echo test. The audio was encrypted with SRTP, went both ways with no lost packets, and a test tone sent into the echo test came back.
  • A caller who got no answer left a voicemail, and the mailbox's owner logged in with the PIN and played it.
  • With the NAT setting in step 4 switched off, the app behind the home router got no audio back at all.
  • Wrong passwords, unknown user names and calls from unregistered apps were all refused, and fail2ban blocked the address.
  • When the certificate was renewed during a call, Asterisk waited for the call to end before it restarted.
  • Everything came back by itself after a reboot.

Asterisk used about 75 MB of memory, and the whole server about 450 MB.

Before you start

You need:

  • a Melonslab server with Debian 13;
  • a name for it, such as sip.example.com, with an A record and an AAAA record pointing at it;
  • a SIP phone or app for each extension that supports TLS and SRTP. In the app's account settings, look for TLS as the transport and SRTP or SDES as the media encryption. Our tests used baresip, which is in Debian and runs on Linux.

Set up SSH keys, automatic security updates and ufw as in steps 1 to 4 of the security guide.

The examples use sip.example.com for the server. Replace it with your own name throughout.

1. Build Asterisk

As root, install what the build needs:

apt update
apt install -y build-essential pkg-config libedit-dev libjansson-dev libsqlite3-dev uuid-dev libxml2-dev libssl-dev libsrtp2-dev libcurl4-openssl-dev libsystemd-dev bzip2 patch wget curl

libsrtp2-dev gives Asterisk encrypted audio, and libsystemd-dev lets it tell systemd when it has started.

Download Asterisk 22, check the download against its checksum, and unpack it. The newest release is listed on the download page. Our test used 22.11.0:

cd /usr/local/src
curl -fsSLO https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-22.11.0.tar.gz
curl -fsSLO https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-22.11.0.sha256
sha256sum -c asterisk-22.11.0.sha256
tar xzf asterisk-22.11.0.tar.gz
cd asterisk-22.11.0

sha256sum prints asterisk-22.11.0.tar.gz: OK. Then build and install it:

./configure
make menuselect.makeopts
make -j2
make install

configure downloads pjproject, the SIP library Asterisk builds in, and make install downloads the English voice prompts. The build took about 6 minutes on our test server. make install does not create any configuration, so /etc/asterisk is still empty. Create the user Asterisk runs as:

adduser --system --group --home /var/lib/asterisk --no-create-home asterisk

2. Get a certificate

Phones check the server's certificate when they connect over TLS. Certbot gets one from Let's Encrypt, and needs port 80 for it:

apt install -y certbot
ufw allow 80/tcp
certbot certonly --standalone -d sip.example.com

Certbot renews the certificate by itself. Asterisk cannot read it where Certbot keeps it, so a hook copies it to Asterisk after every renewal. Create /etc/letsencrypt/renewal-hooks/deploy/asterisk:

#!/bin/sh
# Copy the renewed certificate to Asterisk, and restart it once no calls are active.
install -o asterisk -g asterisk -m 600 /etc/letsencrypt/live/sip.example.com/fullchain.pem /etc/letsencrypt/live/sip.example.com/privkey.pem /etc/asterisk/keys/
asterisk -rx "core stop when convenient" >/dev/null 2>&1 &

Asterisk only reads the certificate when it starts. core stop when convenient waits until no calls are active, and systemd starts Asterisk again 4 seconds later, so a renewal never cuts off a call. Make the hook executable and run it once, to copy the certificate you just got:

mkdir -p /etc/asterisk/keys
chmod 755 /etc/letsencrypt/renewal-hooks/deploy/asterisk
/etc/letsencrypt/renewal-hooks/deploy/asterisk

3. Set up the basics

Create these four files in /etc/asterisk. asterisk.conf makes Asterisk drop root and run as the asterisk user:

[options]
runuser = asterisk
rungroup = asterisk

modules.conf loads every module that has a configuration file. The others decline to load, which the log shows as harmless lines such as app_queue declined to load:

[modules]
autoload = yes

logger.conf writes notices, errors and security events to /var/log/asterisk/messages, which fail2ban reads in step 8:

[logfiles]
console => notice,warning,error
messages => notice,warning,error,security

rtp.conf sets the UDP ports the audio uses. Each call uses a few ports, so 10,000 is plenty:

[general]
rtpstart = 10000
rtpend = 20000

4. Create the extensions

Make a password for each extension. It only goes into the phone once, so make it long:

openssl rand -hex 16

Create /etc/asterisk/pjsip.conf, with a password of your own for each of 101 and 102:

[global]
type = global
user_agent = PBX

[tls-v4]
type = transport
protocol = tls
bind = 0.0.0.0:5061
cert_file = /etc/asterisk/keys/fullchain.pem
priv_key_file = /etc/asterisk/keys/privkey.pem
method = sslv23

[tls-v6]
type = transport
protocol = tls
bind = [::]:5061
cert_file = /etc/asterisk/keys/fullchain.pem
priv_key_file = /etc/asterisk/keys/privkey.pem
method = sslv23

[phone](!)
type = endpoint
context = phones
disallow = all
allow = g722,ulaw,alaw
media_encryption = sdes
direct_media = no
rtp_symmetric = yes
force_rport = yes
rewrite_contact = yes

[auth](!)
type = auth
auth_type = digest

[aor](!)
type = aor
max_contacts = 1
remove_existing = yes
qualify_frequency = 30

[101](phone)
auth = 101
aors = 101
callerid = Anna <101>
mailboxes = 101@default

[101](auth)
username = 101
password = the-password-for-101

[101](aor)

[102](phone)
auth = 102
aors = 102
callerid = Bo <102>
mailboxes = 102@default

[102](auth)
username = 102
password = the-password-for-102

[102](aor)

What the parts do:

  • The two transports listen for TLS on port 5061, one for IPv4 and one for IPv6. There is no plain SIP on port 5060 at all. method = sslv23 lets phones use TLS 1.2 or 1.3. Without it, Asterisk only offers TLS 1.0, which today's phones and apps refuse. TLS 1.0 and 1.1 are refused either way.
  • user_agent = PBX keeps the Asterisk version out of every answer the server sends.
  • The (!) sections are templates, and each extension takes its settings from them in brackets, such as [101](phone). To add extension 103, copy the three sections for 102 and change the number, name and password.
  • media_encryption = sdes makes SRTP compulsory: a phone that does not offer encrypted audio cannot call.
  • The NAT settings. A phone behind a home router announces its private address, such as 192.168.1.20, which cannot be reached from the internet. rtp_symmetric sends the audio back to the address the phone's audio actually comes from, force_rport and rewrite_contact do the same for its SIP messages, and direct_media = no keeps the audio going through the server. In our test, with rtp_symmetric switched off, the app behind the home router sent 599 packets of audio and received none.
  • qualify_frequency = 30 checks every 30 seconds that each phone is still there. That also keeps the connection through the phone's router open, so incoming calls reach it.

There is no guest access: only the extensions in this file can register or call, each with its password.

5. Write the dialplan and voicemail

The dialplan decides what happens to each number dialled. Create /etc/asterisk/extensions.conf:

[phones]
exten => _10[12],1,Dial(PJSIP/${EXTEN},20)
 same => n,VoiceMail(${EXTEN}@default,u)
 same => n,Hangup()

exten => 600,1,Answer()
 same => n,Playback(beep)
 same => n,Echo()
 same => n,Hangup()

exten => 700,1,VoiceMailMain(${CALLERID(num)}@default)
 same => n,Hangup()
  • 101 and 102 ring for 20 seconds, then go to voicemail. _10[12] matches both. To add 103, change it to _10[1-3].
  • 600 is the echo test: after the beep, you hear what you say.
  • 700 plays your own voicemail, after you enter your PIN.

Create /etc/asterisk/voicemail.conf, with a PIN of your own for each mailbox:

[general]
format = wav

[default]
101 => 482913,Anna
102 => 750264,Bo

6. Start Asterisk

The configuration holds passwords, so only the asterisk user may read it:

chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk /var/log/asterisk /var/spool/asterisk
chmod 750 /etc/asterisk /var/spool/asterisk
chmod 640 /etc/asterisk/*.conf

Asterisk comes with a systemd unit. Two of its settings are commented out: RuntimeDirectory, without which the asterisk user cannot create its control socket after a reboot, and UMask, which keeps new voicemail from being readable by other users. Install it with both switched on, and start Asterisk:

cp /usr/local/src/asterisk-22.11.0/contrib/systemd/asterisk.service /etc/systemd/system/
sed -i -e 's/^#RuntimeDirectory=/RuntimeDirectory=/' -e 's/^#UMask=0002/UMask=0027/' /etc/systemd/system/asterisk.service
systemctl daemon-reload
systemctl enable --now asterisk

Open the ports for SIP over TLS and for the audio:

ufw allow 5061/tcp
ufw allow 10000:20000/udp

asterisk -rx runs a command in Asterisk and prints the answer. Check the transports:

asterisk -rx "pjsip show transports"
Transport:  tls-v4                    tls      0      0  0.0.0.0:5061
Transport:  tls-v6                    tls      0      0  [::]:5061

asterisk -r opens the Asterisk console itself, where you can type the same commands. exit leaves it, and Asterisk keeps running.

7. Connect the phones

Set up each phone or app with:

SettingValue
Server or domainsip.example.com
User name101
Passwordthe password for 101 from step 4
TransportTLS, port 5061
Media encryptionSRTP (SDES), required

In baresip, the line in ~/.baresip/accounts is:

<sip:101@sip.example.com;transport=tls>;auth_pass=the-password-for-101;mediaenc=srtp-mand

When both are connected, the server lists them:

asterisk -rx "pjsip show contacts"
  Contact:  101/sip:101-0x560957bdac10@198.51.100.7:8790; c837cce61c Avail         2.576
  Contact:  102/sip:102-0x56380d153890@[2001:db8:5::20]: 51a3c650e8 Avail        41.843

The address for 101 is the public address of its home router, not the private one the app announced: that is rewrite_contact at work. Call 600 and speak. You hear yourself after the beep. Then call 102 from 101. During the call, this shows the audio in both directions:

asterisk -rx "pjsip show channelstats"
 BridgeId ChannelId ........ UpTime.. Codec.   Count    Lost Pct  Jitter   Count    Lost Pct  Jitter RTT....
 d801b11e 101-00000003       00:00:15 g722      781       0    0   0.002    787       0    0   0.001   0.002
 d801b11e 102-00000004       00:00:15 g722      787       0    0   0.001    781       0    0   0.002   0.000

The first Count is the packets the server received from that phone, and the second those it sent to it. Both should grow during the call. If 102 does not answer within 20 seconds, the caller reaches its voicemail, and 102 hears it by calling 700.

To call ordinary phone numbers, you also need a SIP trunk from a telephone operator, which this guide does not cover.

8. Keep SIP scanners out

Programs scan the internet for SIP servers, and try common extension numbers and passwords, to make calls on someone else's account. This setup already gives them little to work with: there is nothing on port 5060, where they look first, the passwords are long and random, and there is no guest access. A wrong password and an unknown user name get the same answer, 401 Unauthorized, so a scanner cannot even tell which extensions exist.

fail2ban blocks addresses that keep trying. Install it:

apt install -y fail2ban

Create /etc/fail2ban/jail.d/asterisk.conf:

[asterisk]
enabled = true
port = 5061
systemctl restart fail2ban
fail2ban-client status asterisk

fail2ban blocks an address on port 5061 for 10 minutes once it finds 10 failures from it within 10 minutes. Asterisk logs each failed attempt on several lines, and fail2ban counts every one, so in practice two or three attempts are enough. In our test, an app with a wrong password was blocked within a second, because it retried straight away.

Blocked attempts show up in the log as lines like these:

NOTICE[68430] res_pjsip/pjsip_distributor.c: Request 'REGISTER' from '<sip:101@sip.example.com>' failed for '198.51.100.7:8801' (callid: 9900c3ec2e06cd87) - Failed to authenticate
NOTICE[68430] res_pjsip/pjsip_distributor.c: Request 'INVITE' from '<sip:guest@sip.example.com>' failed for '198.51.100.7:21435' (callid: 2456639b85f6257e) - No matching endpoint found

To see them:

grep "failed for" /var/log/asterisk/messages

While we tested, nothing but our own apps reached port 5061. For comparison, we opened plain SIP on UDP port 5060 for an hour: in that time, one address sent it two malformed packets, which Asterisk dropped.

9. Back up and update

Your configuration, the voicemail and Asterisk's small database are all you need to keep:

umask 077
tar czf /root/asterisk-backup.tar.gz /etc/asterisk /var/spool/asterisk/voicemail /var/lib/asterisk/astdb.sqlite3

The archive holds the passwords and the private key, so keep it somewhere safe, away from the server.

Debian's security updates cover the libraries Asterisk uses, such as OpenSSL, but not Asterisk itself or the pjproject built into it. New releases of Asterisk 22 come out every 4 to 6 weeks, and are listed on Asterisk's releases page on GitHub. To update, repeat step 1 with the new version number, from the download to make install, and then run systemctl restart asterisk. make install leaves your configuration as it is. We could not test an update, since 22.11.0 was the newest release when we wrote this.

Troubleshooting

A phone that worked cannot connect any more. fail2ban has blocked it, often because of a typing mistake in its password. fail2ban-client status asterisk lists the blocked addresses, and fail2ban-client set asterisk unbanip 198.51.100.7 lets one in again. Fix the password in the phone first, or it is blocked again straight away.

The phone reports a TLS or certificate error. Check that it connects to the name on the certificate, sip.example.com, and not to the IP address, and that /etc/asterisk/keys holds the certificate files. openssl s_client -connect sip.example.com:5061 shows the certificate the server sends.

Calls connect, but there is no sound one way. Check that ufw allows 10000:20000/udp and that rtp_symmetric = yes is set. If the phone's router has a setting called SIP ALG, switch it off: it rewrites SIP messages and can break calls. In the Asterisk console, rtp set debug on shows each audio packet as it arrives and leaves, and rtp set debug off stops it.

A call fails at once with 488 Not Acceptable Here. The phone did not offer encrypted audio. Set its media encryption to SRTP, or SDES, and make it required.

asterisk -rx answers "Unable to connect to remote asterisk". Asterisk is not running, or the RuntimeDirectory line is missing from its unit. systemctl status asterisk and /var/log/asterisk/messages show why.

Run it on your own server

VC-S Micro

€7.99/mo

vCPU
2
Memory
8 GB
Storage
250 GB
Transfer
10 TB
Standard
HDD · RAID 10
  • Full root access
  • Native /64 IPv6
  • RAID-protected storage
  • Malmö, Sweden
  • Month to month, no lock-in
  • 7-day money-back guarantee
All guides