After an exhaustive investigation throughout the internet, various Google searches later, we found out that information about Asterisk in RealTime is too old. Most of it was from about 2005 or 2015 at best. Apparently, nobody has been interested on transmitting the knowledge of this interesting way of programming Asterisk.
Read our tutorials and guides on how to implement new tools and technologies for your business with VitalPBX here.
Due to what was expressed beforehand, we gave ourselves the task of searching all of the available information and compile it all in one single guide that will make life easier to everyone interested on implementing Asterisk Real Time. The best kind of knowledge is the one that is shared with everyone.
1.-Recommendations
- We do not recommend the utilization of the Dial Plan in Real Time. If we have a Dial Plan that is too big, each time that we make a call, the database queries could overload the system.
- On this guide we are using Debian 11 (Bullseye), however, you would be able to use Ubuntu if you so desire.
- Take into account that Asterisk has already deprecated the following applications:
- meetme, from various versions ago, this was substituted with confbridge which currently does not support Real-Time.
- SIP, on version 19 of Asterisk, SIP has been deprecated, however, on this guide we will cover this type of devices.
- Never do this implementation on a production server. Test everything, and make sure that it is suited to your usage.
2.- Installation
On this guide we will be implying that you already have a machine with Debiam 11 NetInst, for which we will start with the installation process of Asterisk 19 and its dependencies. To enter the Debian 11 console, you can start an SSH client, e.g. PuTTY.
2.1.- Install Debian 11 and Update
Install Debian 11.3 and update it to the latest version and some dependence
root@localhost:~# apt update -y
root@localhost:~# apt full-upgrade -y
root@localhost:~# apt -y install build-essential git curl wget libnewt-dev libssl-dev libncurses5-dev subversion libsqlite3-dev libjansson-dev libxml2-dev uuid-dev default-libmysqlclient-dev
2.2.- Firewall Configuration (Optional)
Before installing the firewall, be careful not to block SSH port 22, as you could lose connection to the server.
Debian usually ships without the firewall installed. We recommend installing it and allowing the following ports:.
root@localhost:~# apt install firewalld -y
root@localhost:~# systemctl start firewalld
root@localhost:~# systemctl enable firewalld root@localhost:~# firewall-cmd --zone=public --add-port=5060-5061/udp --permanent root@localhost:~# firewall-cmd --zone=public --add-port=5060-5061/tcp --permanent root@localhost:~# firewall-cmd --zone=public --add-port=10000-20000/udp --permanent
root@localhost:~# firewall-cmd --reload
2.3.- Installing Asterisk 19
Create the user ‘asterisk’
root@localhost:~# groupadd asterisk
root@localhost:~# useradd -r -d /var/lib/asterisk -g asterisk asterisk
Now we start the install process of Asterisk 19
root@localhost:~# cd /usr/src root@localhost:/usr/src# wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-19-current.tar.gz root@localhost:/usr/src# tar -zxvf asterisk-19-current.tar.gz root@localhost:/urs/src# cd asterisk-19.4.1 root@localhost:/urs/src/asterisk-19.4.1# ./contrib/scripts/get_mp3_source.sh root@localhost:/urs/src/asterisk-19.4.1# contrib/scripts/install_prereq install root@localhost:/urs/src/asterisk-19.4.1# ./configure --libdir=/usr/lib64 --with-jansson-bundled --with-pjproject-bundled
Then, we proceed to make menuselect
root@localhost:/urs/src/asterisk-19.4.1# make menuselect
Here, we can also select different audios and codecs if you like, for example, opus. After selecting everything we need, we proceed to Save & Exit.
Now we will proceed with the following
root@localhost:/urs/src/asterisk-19.4.1# make && make install root@localhost:/urs/src/asterisk-19.4.1# make samples root@localhost:/urs/src/asterisk-19.4.1# make config
root@localhost:/urs/src/asterisk-19.4.1# ldconfig root@localhost:/urs/src/asterisk-19.4.1# chown -R asterisk.asterisk /etc/asterisk root@localhost:/urs/src/asterisk-19.4.1# chown -R asterisk.asterisk /var/{lib,log,spool}/asterisk root@localhost:/urs/src/asterisk-19.4.1# chown -R asterisk.asterisk /usr/lib/asterisk root@localhost:/urs/src/asterisk-19.4.1# systemctl enable asterisk root@localhost:/urs/src/asterisk-19.4.1# systemctl start asterisk root@localhost:/urs/src/asterisk-19.4.1# asterisk -rvvvvvvvvvvvvvvvvvvv Asterisk 19.4.1, Copyright (C) 1999 - 2021, Sangoma Technologies Corporation and others.
Created by Mark Spencer <markster@digium.com>
Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type 'core show license' for details.
=========================================================================
Connected to Asterisk 19.4.1 currently running on vitalpbx (pid = 42979)
vitalpbx*CLI>
Now, to configure Asterisk to run as asterisk user, run the following command:
root@localhost:/urs/src/asterisk-19.4.1# nano /etc/default/asterisk
This will open a file, in the file comment out following two lines:
AST_USER=”asterisk”
AST_GROUP=”asterisk”
The default configuration file used by asterisk is /etc/asterisk/asterisk.conf. You can open the file and see if any change is required.
root@localhost:/urs/src/asterisk-19.4.1# nano /etc/asterisk/asterisk.conf
runuser = asterisk ; The user to run as.
rungroup = asterisk ; The group to run as.
CONGRATULATIONS! You have successfully installed Asterisk 19!
2.3.- Installing Mariadb and dependencies.
For Asterisk Real-Time to work, it is necessary to install MariaDB, since the Real-Time application works with data bases and is connected through ODBC.
root@localhost:/urs/src/asterisk-19.4.1# apt install -y unixodbc odbcinst mariadb-client mariadb-server odbc-mariadb root@localhost:/urs/src/asterisk-19.4.1# systemctl enable mariadb root@localhost:/urs/src/asterisk-19.4.1# systemctl start mariadb
From version 12, the creation of the tables for Asterisk Real-Time is done using alembic. With the same application, it is possible to migrate to the latest version of Asterisk and update the tables created with version 11 or prior. First, we need to install some dependencies:
root@localhost:/urs/src/asterisk-19.4.1# apt install python3-pip -y
Afterwards, we install alembic and some dependency using pip:
root@localhost:/urs/src/asterisk-19.4.1# pip install mysql-connector-python
root@localhost:/urs/src/asterisk-19.4.1# pip install alembic
root@localhost:/urs/src/asterisk-19.4.1# pip install mysqlclient
root@localhost:/urs/src/asterisk-19.4.1# pip install "importlib_metadata==1.5.2"
root@localhost:/urs/src/asterisk-19.4.1# pip install "zipp==1.2.0"
root@localhost:/urs/src/asterisk-19.4.1# pip install "configparser==3.8.1"
Since the creation/update of the tables is based of a configuration file, we modify it:
root@localhost:/urs/src/asterisk-19.4.1# cd /usr/src/asterisk-19.4.1/contrib/ast-db-manage/ root@vitalpbx:/usr/src/asterisk-19.4.1/contrib/ast-db-manage# mv config.ini.sample config.ini root@vitalpbx:/usr/src/asterisk-19.4.1/contrib/ast-db-manage# nano config.ini
We change the following line:
sqlalchemy.url = mysql://user:pass@localhost/asterisk
with:
sqlalchemy.url = mysql://root:@localhost/asterisk
The syntax of the line is: Database engine, user, password, domain/IP, database. With this line, we create the connection to the database. We Save changes and proceed to the creation of the database:
root@vitalpbx:/usr/src/asterisk-19.4.1/contrib/ast-db-manage# mysql -u root MariaDB [(none)]> create database asterisk; MariaDB [(none)]> exit;
We create/update the tables with the following command:
root@vitalpbx:/usr/src/asterisk-19.4.1/contrib/ast-db-manage# alembic -c config.ini upgrade head
We enter MariaDB once again:
root@vitalpbx:/usr/src/asterisk-19.4.1/contrib/ast-db-manage# mysql -u root MariaDB [(none)]> use asterisk; MariaDB [(asterisk)]> show tables; +-----------------------------+ | Tables_in_asterisk | +-----------------------------+ | alembic_version_config | | extensions | | iaxfriends | | meetme | | musiconhold | | musiconhold_entry | | ps_aors | | ps_asterisk_publications | | ps_auths | | ps_contacts | | ps_domain_aliases | | ps_endpoint_id_ips | | ps_endpoints | | ps_globals | | ps_inbound_publications | | ps_outbound_publishes | | ps_registrations | | ps_resource_list | | ps_subscription_persistence | | ps_systems | | ps_transports | | queue_members | | queue_rules | | queues | | sippeers | | voicemail | +-----------------------------+ 26 rows in set (0.00 sec)
Now, we create a username that has the privileges to work with the created database:
MariaDB [asterisk]> grant all privileges on asterisk.* to 'asterisk'@'localhost' identified by 'asterisk'; Query OK, 0 rows affected (0.00 sec) MariaDB [asterisk]> FLUSH Privileges; MariaDB [asterisk]> exit;
2.4.- Asterisk Configurations
Now, we proceed to the configuration of ODBC and Asterisk so that Real-Time works properly. The odbcinst.ini file, available on the etc folder, we leave it with the default configurations. We create the odbc.ini file, where we configure the connection to the Asterisk Database:
root@localhost:~# nano /etc/odbc.ini [asterisk] Description = MySQL Asterisk Driver = MariaDB Unicode Database = asterisk Server = localhost User = asterisk Password = asterisk Port = 3306 Socket = /var/run/mysqld/mysqld.sock
root@localhost:~# nano /etc/odbcinst.ini [MariaDB Unicode]
Driver=libmaodbc.so
Description=MariaDB Connector/ODBC(Unicode)
Threading=0
UsageCount=1
We save changes and verify that the connection is working properly:
root@localhost:~# isql asterisk asterisk asterisk +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> quit;
Perfect! Now, we proceed to the Asterisk configurations and the the following to the end:
root@localhost:~# nano /etc/asterisk/res_odbc.conf [asterisk] enabled => yes dsn => asterisk username => asterisk password => asterisk pre-connect => yes sanitysql => select 1 max_connections => 20 connect_timeout => 5 negative_connection_cache => 600
Now, we configure the Asterisk file, extconfig.conf
root@localhost:~# nano /etc/asterisk/extconfig.conf ; ; Static and realtime external configuration ; engine configuration ; ; See https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration ; for basic table formatting information. ; [settings] ps_endpoints => odbc,asterisk ps_auths => odbc,asterisk ps_aors => odbc,asterisk ps_domain_aliases => odbc,asterisk ps_endpoint_id_ips => odbc,asterisk ps_contacts => odbc,asterisk voicemail => odbc,asterisk queues => odbc,asterisk queue_members => odbc,asterisk sipusers => odbc,asterisk sippeers => odbc,asterisk extensions => odbc,asterisk
As you can see, we are configuring the PJSIP Devices (everything that starts with ps), Voicemail, SIP Devices, Queues, Queue Members, and extensions for Real-Time.
Now, we configure the Asterisk file, pjsip.conf. We add to the end the following lines.
root@localhost:~# nano /etc/asterisk/pjsip.conf [system] type=system timer_t1=500 timer_b=32000 disable_tcp_switch=yes
[transport-tcp] type=transport protocol=tcp bind=0.0.0.0:5060 allow_reload=yes
[transport-udp] type=transport protocol=udp bind=0.0.0.0:5060 allow_reload=yes
[transport-tls] type=transport protocol=tls bind=0.0.0.0:5061 allow_reload=yes verify_client=no verify_server=no method=tlsv1
[transport-ws] type=transport protocol=ws bind=0.0.0.0:5060 allow_reload=yes
[transport-wss] type=transport protocol=wss bind=0.0.0.0:5061 allow_reload=yes
Afterwards, we add the following configurations to the end of the sorcery.conf file under /etc/asterisk/..
root@localhost:~# nano /etc/asterisk/sorcery.conf [res_pjsip] endpoint=realtime,ps_endpoints auth=realtime,ps_auths aor=realtime,ps_aors domain_alias=realtime,ps_domain_aliases
[res_pjsip_endpoint_identifier_ip] identify=realtime,ps_endpoint_id_ips
Before restarting Asterisk so it takes into account the changes, we need to make sure that the modules related to Real-Time are loaded correctly on Asterisk.
So, we will add the following modules:
preload => res_odbc.so
preload => res_config_odbc.so
load => func_realtime.so
load => pbx_realtime.so
root@localhost:~# nano /etc/asterisk/modules.conf ; ; Asterisk configuration file ; ; Module Loader configuration file ; [modules] autoload=yes preload => res_odbc.so preload => res_config_odbc.so load => func_realtime.so load => pbx_realtime.so
Now, we restart Asterisk and check that the connection is working.
root@localhost:~# systemctl restart asterisk root@localhost:~# asterisk -rvvvvvvvvvvvv localhost*CLI> odbc show ODBC DSN Settings ----------------- Name: asterisk DSN: asterisk Number of active connections: 1 (out of 20) Logging: Disabled localhost*CLI>
2.5.- Adding PJSIP Devices
So now we are going to add some PJSIP extensions. For which we have to add entries with the data to our Asterisk database created previously.
Add an extension with a PJSIP Device.
root@localhost:~# mysql -u root MariaDB [(none)]> use asterisk;
MariaDB [(asterisk)]> insert into ps_aors (id, max_contacts, qualify_frequency) values (100, 2, 30); MariaDB [(asterisk)]> insert into ps_auths (id, auth_type, password, username) values (100, 'userpass', 100, 100); MariaDB [(asterisk)]> insert into ps_endpoints (id, transport, aors, auth, context, disallow, allow, direct_media, deny, permit, mailboxes) values (100, 'transport-udp', '100', '100', 'testing', 'all', 'ulaw,alaw,gsm', 'no', '0.0.0.0/0', '0.0.0.0/0', '100@default');
MariaDB [(asterisk)]> insert into ps_aors (id, max_contacts, qualify_frequency) values (101, 2, 30);
MariaDB [(asterisk)]> insert into ps_auths (id, auth_type, password, username) values (101, 'userpass', 101, 101);
MariaDB [(asterisk)]> insert into ps_endpoints (id, transport, aors, auth, context, disallow, allow, direct_media, deny, permit, mailboxes) values (101, 'transport-udp', '101', '101', 'testing', 'all', 'ulaw,alaw,gsm', 'no', '0.0.0.0/0', '0.0.0.0/0', '101@default');
MariaDB [(asterisk)]> exit;
We repeat these lines with different extension numbers to create new extensions.
To verify that everything is working fine, we perform the following test:
root@localhost:~# asterisk -rvvvvvvvvvvvvvvvvvv localhost*CLI> pjsip show endpoints Endpoint: <Endpoint/CID.....................................> I/OAuth: <AuthId/UserName...........................................................> Aor: Contact: <Aor/ContactUri..........................> <RTT(ms)..> Transport: Identify: <Identify/Endpoint.........................................................> Match: Channel: Exten: CLCID: ========================================================================================== Endpoint: 100 Unavailable 0 of inf InAuth: 100/100 Aor: 100 2 Transport: transport-udp udp 0 0 0.0.0.0:5060
Endpoint: 101 Unavailable 0 of inf
InAuth: 101/101
Aor: 101 2
Transport: transport-udp udp 0 0 0.0.0.0:5060 Objects found: 2
2.6.- Adding a Dial Plan
As mentioned in the beginning, this guide is not recommended to be used with the dial plan in a dynamic form. We have also performed various tests, and it does not seem to work properly and Asterisk restarts.
Now that we have at least two extensions added, we would like to make a call between them. For this, we need to create a static Dial Plan which we configure on the extensions.conf file, located under the /etc/asterisk directory.
root@localhost:~# nano /etc/asterisk/extensions.conf [general] [testing] exten => _1XX,1,NoOp()
same => n,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})})
same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
same => n(unavail),Voicemail(${EXTEN}@default,u)
same => n,Hangup()
same => n(busy),VoiceMail(${EXTEN}@default,b)
same => n,Hangup()
;Retrieve Voicemail message exten => *97,1,NoOp(Retrieve VM from Extension ${CALLERID(number)}) same => n,Answer() same => n,VoiceMailMain(${CALLERID(num)}@default)
We restart the Dial Plan
root@localhost:~# asterisk -rvvvvvvvvvvvvvvvvvvvv localhost*CLI> dialplan reload
Congratulations! We can now perform a call between two extensions with Asterisk Real-Time.
2.7.- Adding Voicemail
It is possible that extensions have their own voicemail in Real-Time. To have this option, it is necessary to do the following:
root@localhost:~# mysql -u root MariaDB [(none)]> use asterisk; MariaDB [(asterisk)]> insert into voicemail (context, mailbox, password, attach, saycid, envelope) values ('default', '100', '100', 'yes', 'yes', 'yes'); MariaDB [(asterisk)]> insert into voicemail (context, mailbox, password, attach, saycid, envelope) values ('default', '101', '101', 'yes', 'yes', 'yes'); MariaDB [(none)]> exit;
2.8.- Adding Queues
Coming up, we will be implementing Queues in Real-Time. These got two components: the first one is the queue parameter, and the second is the static or dynamic agents.
We will add the parameters of the queue table, and a static member. To add static members, we will do it through the Dial Plan.
root@localhost:~# mysql -u root MariaDB [(none)]> use asterisk; MariaDB [(asterisk)]> insert into queues (name, musiconhold, timeout, ringinuse, queue_holdtime, retry, wrapuptime, strategy) values ('Q500', 'default', '15', 'no', '30', '5', '5', 'ringall'); MariaDB [(asterisk)]> insert into queue_members (queue_name, interface, membername, penalty, wrapuptime) values ('Q500', 'Local/101@testing/n', '101', '0', '5'); MariaDB [(none)]> exit;
We verify all is working properly.
root@localhost:~# asterisk -rvvvvvvvvvvvvvvvvvvvvvvv localhost*CLI> queue show Q500 Q500 has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0%, SL2:0.0% within 0s Members: 101 (Local/101@testing/n) (ringinuse disabled) (realtime) (Not in use) has taken no calls yet No Callers localhost*CLI>exit
Now, we will modify the Dial Plan to be able to call the Queue. We will add the following to the Dial Plan made on section 3.6.
root@localhost:~# nano /etc/asterisk/extensions.conf ;Call Queue Q500 exten => 500,1,NoOp(Queue: Testing 500) same => n,Playback(queue-youarenext) same => n(qconnect),NoOp(Connecting to Queue) same => n,Queue(Q500,c,,,30) same => n,Hangup() ;Agent Login & Logout exten => *5001,1,NoOp(Queue: Add Agent ${CALLERID(number)} in Queue 500) same => n,AddQueueMember(Q500,Local/${CALLERID(number)}@testing/n,0,,${CALLERID(number)},) same => n,Playback(agent-loginok) exten => *5002,1,NoOp(Queue: Remove Agent ${CALLERID(number} in Queue 500) same => n,RemoveQueueMember(Q500,Local/${CALLERID(number)}@testing/n) same => n,Playback(agent-loggedoff)
We restart the Dial Plan
root@localhost:~# asterisk -rvvvvvvvvvvvvvvvvvvvv localhost*CLI> dialplan reload
Now we can call from extension 100 to extension 500 and it should give us a message that your call is now the first in line, and afterwards, start ringing on extension 101.
Afterwards, we call from extension 101 to 500, and we will see that it will leave us on queue for 30 seconds and the call will hang up. This is happening due to there not being available agents, and we have a maximum hold time of 30 seconds. If the extension that we are calling to extension 500 has 2 lines, it is possible that it still rings, but we will ignore this for this test.
Now, we will add extension 100 dynamically to the Queue, by dialing *5001 from this extension. And then, we call to the Queue with extension 101, and we will see that extension 100 starts to ring.
To remove extension 100 from the Queue, we just need to dial *5002.
Congratulations! You have just implemented Queues in Real-Time!
We hope that you have enjoyed this implementation of Asterisk Real Time, and if you wish to have more information, you can visit our website, vitalpbx.com.