Chapter 3. Installing Asterisk

I long to accomplish great and noble tasks, but it is my chief duty to accomplish humble tasks as though they were great and noble. The world is moved along, not only by the mighty shoves of its heroes, but also by the aggregate of the tiny pushes of each honest worker.

Helen Keller

In this chapter we’re going to walk through the installation of Asterisk from the source code. Many people shy away from this method, claiming that it is too difficult and time-consuming. Our goal here is to demonstrate that installing Asterisk from source is not actually that difficult to do. More importantly, we want to provide you with the best Asterisk platform on which to learn.

In this book we will be helping you build a functioning Asterisk system from scratch. Towards that goal, in this chapter we will build a base platform for your Asterisk system. Since we are installing from source, there is potentially a lot of variation in how you can do this. Our goal here is to deliver a standard sort of platform, suitable for explorations in many areas. It is possible to strip Asterisk down to the very basics, and run a very lean machine, however that exercise is left up to the reader. The process we discuss here is designed to get you up and running quickly and simply, without short-changing you on access to interesting features.

Most of the commands you see are going to be best handled with a series of copy-paste operations (n fact, we strongly recommend you have an electronic version of this book handy for that very purpose)1. While it looks like a lot of typing, the commands we take you through can get you from start to finish in less than 30 minutes, so it’s really not as complex as it might appear. We run some prerequisites, some compilation, and some post-install config, and Asterisk is ready to go.

For the sake of brevity, these steps will be performed on a CentOS 7 system. This is functionally equivalent to RHEL, and similar enough to Fedora that the steps should be quite similar. For other platforms such as Debian/Ubuntu and so forth, the instructions will also be similar, but you will need to adjust as needed for your platform2.

The first part of the installation instructions will not deal with Asterisk as such, but rather some of the dependencies that either Asterisk requires, or are necessary for some of the more useful features (such as database integration). We’ll try to keep the instructions general enough that they should be useful on any distribution of your choice.

These instructions assume that you are an experienced Linux administrator3. A fully working Asterisk system will consist of enough discrete parts that you will find it challenging to deal with all of it if you have little or no Linux background. We’d still encourage you to dive right in, but please allow for the fact that there will be a steep learning curve if you don’t already have solid Linux command line experience.

Note

If you want to learn the Linux command line, one of the best books we’ve found is The Linux Command Line by William Shotts, which has been released under a Creative Commons license, and dives straight into all the knowledge you need to use the Linux shell effectively. It can be found at linuxcommand.org. You could memorize the book from front to back, and pretty much everything you’d learned would be something any seasoned Linux administrator would agree was worth knowing.

Another fantastic book is of course the legendary UNIX and Linux System Administration Handbook by Dan Mackin, Ben Whaley, Trent R. Hein, Garth Snyder, and Evi Nemeth. Highly recommended.

You should also note that because of Asterisk’s history, it is able to integrate with a multitude of telephony technologies, however these days, someone new to Asterisk is going to want to learn SIP integration before worrying about more complex, obsolete or peripheral channel types. Once you are comfortable with Asterisk in a pure SIP environment, it’ll be much easier to look at integrating other channel types.

Linux Installation

Asterisk is developed using Linux, and unless you’re very comfortable with porting software between various platforms, that is what you’re going to want to use.

In this book, we’re going to use CentOS as the platform. If you would prefer a different Linux distro, it is expected that you have sufficient Linux skills to understand what some of the differences may be. These days, it’s so easy and cheap to fire up an instance of any common distribution, so there’s no real harm in using CentOS to learn, and then migrate to whatever you prefer when you’re ready.

We recommend installing the Minimal version of CentOS, since the installation process we will be going through handles all the prerequisites. This also ensures you’re not installing anything you don’t need.

Choosing Your Platform

OK, so strictly speaking we’ve already chosen your platform for you, however there are several different ways to get a CentOS server up and running:

PlatformProsCons
Digital OceanaUp and running in minutes. Inexpensive to operate. Doesn’t require any resources on your local system. Accessible from anywhere. Can be used in a production environment. Fantastic for quick prototyping projects.You pay as long as it’s running. The IP address is only yours for as long as the system is running. Requires some DevOps skills if you want to deploy in production. No firewall in place by default.
VirtualBox (or other PC-based platform)Free to use. No external exposure. Excellent for small lab projects.Requires more horsepower on your system. Requires storage space on your local system. Not easy to deploy into a production environment.
AWSInexpensive to operate. Doesn’t require any resources on your local system. Accessible from anywhere. Can be used in a production environment. Scales to enormous sizes.You pay for as long as it’s running. Somewhat more skills required to gather all the resources you need. You pay as long as it’s running.
Physical HardwareDedicated platform. Can be shipped and installed anywhere. Complete control over all aspects of environment, hardware, network, and so forth.Risk of component failure. Power consumption. Noise. Potential costs for hosting. No inherent redundancy.
Other (really anything that’ll run CentOS 7 should be fine)You can use an environment that you’re familiar with.You’re on your own.
Other Linux (you don’t actually have to run CentOS)You can run the exact environment you want.You need to have strong Linux admin skills.

a Or really any OpenStack-based service.

For the purposes of learning, we recommend one of two simple ways to get going:

  1. If you are running Windows as your desktop: Download VirtualBox, then download the CentOS 7 Minimal ISO, and install on your local machine.

  2. If you are comfortable working with SSH-based, keyed connections to remote systems: Create a DigitalOcean CentOS droplet.

This book was developed and tested using both VirtualBox and DigitalOcean.

VirtualBox Steps

Grab a copy of VirtualBox from the https://www.virtualbox.org/wiki/Downloads website and install it.

Download the Minimal ISO from the https://www.centos.org/download/ website.

Get yourself a copy of PuTTY if you’re using Windows (https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html)

Create a New virtual machine with the following characteristics:

  • Type: Linux

  • Version: Red Hat (64-bit)

  • Memory size: 2048 MB

  • Hard disk: Create a virtual hard disk now

  • File Location: Pick a good spot for storing your virtual machine images

  • File size: 16 GB is fine for what we’re doing here, but something larger would be needed for production.

Once the basic machine has been defined, you’ll need to tweak it as follows:

  • Storage: Under the Storage Tree, Controller: IDE ...

    You should see the CD/DVD has a tiny disc icon labeled 'Empty'

    Click on it and to the right under Attributes, there’ll be another tiny disc icon

    If you click on that, it’ll ask you to Choose Optical Virtual Disk File

    Locate on your hard drive the Minimal ISO you downloaded from CentOS, and choose it

    The Storage Tree should now show the CentOS ISO

  • Network: Adaptor 1

    Attached to: Bridged Adaptor

Start up the machine you’ve just created, and it should take you through a basic installation of CentOS. Here are a few items you’ll want to specify (for anything else, the defaults should do):

  • Date and Time: Adjust to your timezone if you wish.

  • Network and Host Name: Ethernet - toggle from off to on (it should immediately grab an IP address from your network - if not set one manually). Press the 'Done' button.

  • Installation destination: It may require you to confirm the target, but you shouldn’t need to change anything. Press the 'Done' button.

  • That’s it. Begin Installation.

While the installation is taking place, set the root password, and also create a user named ‘astmin’

  • Make the astmin user an administrator

The installation will take a few minutes. Grab a coffee!

Once the install is done, the installer will ask you to 'Reboot‘. The reboot should only take 15 seconds or so.

Congratulations, you’re system is ready. Login as root.

DigitalOcean

You’ll obviously need a DigitalOcean account if you’re going to use this method. Once you’ve got that sorted, you can log in and create a new droplet as follows:

  • CentOS 7 (lastest version, 64-bit)

  • 4GB 2vCPUs (we don’t really need the 4GB RAM, but it is good to have the 2xCPUs (you can probably get away with 2GB 1vCPU, if you’re really cost-conscious)

  • Data center closest to you

Once that’s up and running, go ahead and log in as the default user (as of this writing, it’s centos).

Warning

Note that DigitalOcean instances do not have a firewall by default. Instead, they provide a firewall as a part of their environment. The system you build will therefore not have any native firewall in place, and will be subject to external attacks shortly after you complete configuration (you’ll see this on the Asterisk console). We’ll be discussing security and anti-fraud in more detail later on in this book.

Dependencies

The system you’ve just built isn’t really much more than a basic bootstrapped system. In order to prepare it for an Asterisk installation, there are a few things we’ll need to install first.

The following commands can be typed from the command line, or added to a simple shell script and run that way.

sudo yum -y update &&
sudo yum -y install epel-release &&
sudo yum -y install python-pip &&
sudo yum -y install vim wget &&
sudo pip install alembic ansible &&
sudo pip install --upgrade pip &&
sudo mkdir /etc/ansible &&
sudo chown astmin:astmin /etc/ansible &&
sudo echo "[starfish]" >> /etc/ansible/hosts &&
sudo echo "localhost ansible_connection=local" >> /etc/ansible/hosts &&
mkdir -p ~/ansible/playbooks

We’ve installed Ansible simply because it’s a quick and easy way to get all the dependencies met. We’ve written a playbook to perform the following operations:

  1. Install vim, wget and MySQL-python

  2. Install the MySQL community-edition repository

  3. Install mysql-server

  4. Tweak some variables in the mysql-server installation

  5. Start the mysql-server daemon

  6. Modify some MySQL credentials (create users, set passwords)

  7. Create a MySQL database/schema for Asterisk to use

  8. Apply some security best practices (remove anonymous user, test database, etc)

  9. Create asterisk user

  10. Create astmin user

  11. Install dependencies for ODBC

  12. Install some diagnostic tools

  13. Tweak the firewall to allow SIP and RTP traffic

  14. Edit some ODBC config files

This can all be done manually, but it’s just a lot of typing, and ansible is really good at streamlining this.

Create an ansible playbook in the file ~/ansible/playbooks/starfish.yml.

Note

# The libmyodbc8a.so file is versioned, so, if you don’t have version 8 of UnixODBC:

  • run the playbook the first time (to install the UnixODBC library),

  • find out what file was installed at /usr/lib64/libmyodbc<version>a.so,

  • edit the playbook as appropriate (provide the correct filename)

  • save and re-run the playbook (which will then update the configuration files to point to the correct library)

Here’s the playbook:

---
- hosts: starfish
  become: yes
  vars:
# Use these on the first run of this playbook
    current_mysql_root_password: ""
    updated_mysql_root_password: "YouNeedAReallyGoodPassword"
    current_mysql_asterisk_password: ""
    updated_mysql_asterisk_password: "YouNeedAReallyGoodPasswordHereToo"
# Comment the above out after the first run

# Uncomment these for subsequent runs
#    current_mysql_root_password: "YouNeedAReallyGoodPassword"
#    updated_mysql_root_password: ""
#    current_mysql_asterisk_password: "YouNeedAReallyGoodPasswordHereToo"
#    updated_mysql_asterisk_password: ""

  tasks:

  - name: Install epel-release
    yum:
      name: epel-release
      state: present

  - name: Install other dependencies
    yum:
      name: ""
      state: present
    with_items:
      - vim
      - wget
      - MySQL-python

  - name: Install the MySQL repo.
    yum:
      name: http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
      state: present

  - name: Install mysql-server
    yum:
      name: mysql-server
      state: present


#  - name: Update sshd config for enhanced login security
#    lineinfile:
#      dest: /etc/ssh/sshd_config
#      regexp: ""
#      line: ""
#      state: present
#    with_items:
#      - regexp: "^(#PubkeyAuthentication|PubkeyAuthentication)"
#        line: "PubkeyAuthentication yes"
#      - regexp: "^(#PasswordAuthentication|PasswordAuthentication)"
#        line: "PasswordAuthentication no"
#      - regexp: "^(#PermitRootLogin|PermitRootLogin)"
#        line: "PermitRootLogin no"
#      - regexp: "^(#UseDNS|UseDNS)"
#        line: "UseDNS no"
#  - name: Restart sshd
#     service:
#       name: sshd
#       state: restarted
#       enabled: yes

  - name: Override variables for MySQL (RedHat).
    set_fact:
      mysql_daemon: mysqld
      mysql_packages: ['mysql-server']
      mysql_log_error: /var/log/mysqld.err
      mysql_syslog_tag: mysqld
      mysql_pid_file: /var/run/mysqld/mysqld.pid
      mysql_socket: /var/lib/mysql/mysql.sock
    when: ansible_os_family == "RedHat"

  - name: Ensure MySQL server is running
    service:
      name: mysqld
      state: started
      enabled: yes

  - name: update mysql root password for localhost root account from local servers
    mysql_user:
      login_user: root
      login_password: ""
      name: root
      host: ""
      password: ""
    with_items:
        - localhost

  - name: update mysql root password for all other local root accounts
    mysql_user:
      login_user: root
      login_password: ""
      name: root
      host: ""
      password: ""
    with_items:
        - ""
        - 127.0.0.1
        - ::1
        - localhost.localdomain

  - name: create asterisk database
    mysql_db:
      login_user: root
      login_password: ""
      name: asterisk
      state: present

  - name: asterisk mysql user
    mysql_user:
      login_user: root
      login_password: ""
      name: asterisk
      host: ""
      password: ""
      priv: "asterisk.*:ALL"
    with_items:
        - ""
        - 127.0.0.1
        - ::1
        - localhost
        - localhost.localdomain

  - name: remove anonymous user
    mysql_user:
      login_user: root
      login_password: ""
      name: ""
      state: absent
      host: ""
    with_items:
        - localhost
        - ""
        - 127.0.0.1
        - ::1
        - localhost.localdomain

  - name: remove test database
    mysql_db:
      login_user: root
      login_password: ""
      name: test
      state: absent

  - user:
      name: asterisk
      state: present
      createhome: yes

  - group:
      name: asterisk
      state: present

  - user:
      name: astmin
      groups: asterisk,wheel
      state: present

  - name: Install other dependencies
    yum:
      name: ""
      state: present
    with_items:
      - unixODBC
      - unixODBC-devel
      - mysql-connector-odbc
      - MySQL-python
      - tcpdump
      - ntp
      - ntpdate

#   Tweak the firewall for UDP/SIP
  - firewalld:
      port: 5060/udp
      permanent: true
      state: enabled

#   Tweak firewall for UDP/RTP
  - firewalld:
      port: 10000-20000/udp
      permanent: true
      state: enabled

  - name: Ensure NTP is running
    service:
      name: ntpd
      state: started
      enabled: yes

# The libmyodbc8a.so file is versioned, so if you don't have version 8, see what the
# /usr/lib64/libmyodbc<version>a.so file is, and refer to that instead 
# on your 'Driver64' line, and then run the playbook again
  - name: update odbcinst.ini
    lineinfile:
      dest: /etc/odbcinst.ini
      regexp: ""
      line: ""
      state: present
    with_items:
      - regexp: "^Driver64"
        line: "Driver64 = /usr/lib64/libmyodbc8a.so"
      - regexp: "^Setup64"
        line: "Setup64 = /usr/lib64/libodbcmyS.so"

  - name: create odbc.ini
    blockinfile:
      path: /etc/odbc.ini
      create: yes
      block: |
        [asterisk]
        Driver = MySQL
        Description = MySQL connection to 'asterisk' database
        Server = localhost
        Port = 3306
        Database = asterisk
        UserName = asterisk
        Password = 
        #Socket = /var/run/mysqld/mysqld.sock
        Socket = /var/lib/mysql/mysql.sock
...

Run the playbook with the following command:

$ ansible-playbook ~/ansible/playbooks/starfish.yml

Sit back and watch the magic happen.

Once ansible has completed the assigned tasks, verify that ODBC can connect to the database using the asterisk user credentials.

$ echo “select 1” | isql -v asterisk asterisk <password>

You should see a result something like this:

+---------------------------------------+
| Connected!                            |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
+---------------------------------------+
SQL> select 1
+---------------------+
| 1                   |
+---------------------+
| 1                   |
+---------------------+
SQLRowCount returns 1
1 rows fetched

If you do not see the Connected! message, you need to troubleshoot your database and ODBC installation. The first thing you should do is make sure you can log into the database from the command line using the Asterisk user (mysql -u asterisk -p). Most ODBC problems tend to end up being credentials problems (i.e. wrong password or user name), so work backwards to ensure all the credentials work as they should, and double check that you didn’t get any problem messages from Ansible.

The system is now prepared, and we’re ready to download and install Asterisk.

Asterisk installation

Asterisk comes in a tarball, as source code, and it must be downloaded, extracted, and compiled. This is not difficult to do, so long as you have all the dependencies correct. Between the writing of this book and your reading of it there may have been some changes to the various dependencies, so your install process may have run slightly differently. It’s often difficult to know the difference between an error message that can safely be ignored, and one that is indicating a critical problem, however in general, you should have identified and resolved any errors in the previous processes before arriving at this step. If you’re dependencies are sorted, the Asterisk install will tend to go smoothly.

Download and Prerequisites

Log out of the system, and log back in as user astmin5.

Type the following commands from the shell in order to download the Asterisk source code:

Note

When you see us write <TAB> in a filename, what we mean is that you should press the TAB button on your keyboard and allow autocomplete to fill in what it can. The rest of the typing then follows.

$ mkdir ~/src
$ cd ~/src
$ wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-15-current.tar.gz
$ tar zxvf asterisk-15-current.tar.gz
$ cd asterisk-15.<TAB>                  # tab should auto-complete (unless it has more than one match)

We can now run a few prerequisites that the Asterisk team have defined, and also have the environment checked:

$ cd contrib/scripts (or cd ~/src/asterisk-15.<TAB>/contrib/scripts  # again, depending on the current version)
$ sudo ./install_prereq install    # asterisk has a few prerequisites that this simplifies
$ cd ../.. 
$ ./configure

Asterisk is now ready to compile and install, however there are a few tweaks worth making to the configuration before compilation.

Compiling and Installing

$ make menuselect

You will see a menu that presents various options you can select for the compiler. Use the arrow and tab keys to move around, and the enter key to select/deselect. For the most part, the defaults should be fine, but we want to make a few tweaks to the sound files, in order to ensure we have all the sounds we want, in the best format.

Note

At this point you can also select other languages you wish to have on your system. We recommend you select the WAV and G722 formats.

Under Core Sound Packages:

  • De-select [*] CORE-SOUNDS-EN-GSM

  • Select [*] CORE-SOUNDS-EN-WAV

  • Select [*] CORE-SOUNDS-EN-G722

Under Extras Sound Packages:

  • Select [*] EXTRA-SOUNDS-EN-WAV

  • Select [*] EXTRA-SOUNDS-EN-G722

Save and Exit.

Three more commands and Asterisk is installed:

$ make                # this will take several minutes to complete (depending on the speed of your system)
$ sudo make install   # you must run this with escalated privileges
$ sudo make config    # this too
Warning

When the ‘make config’ command has completed, it will suggest some commands to install the sample configuration files. For the purposes of this book, you do not want to do this. We will be building the necessary files by hand, so the sample files will only serve to disrupt and confuse that process. Having said that, the sample files are useful, and we will discuss them a bit more later in this chapter (and throughout the book, since they are excellent reference material).

Reboot the system.

Once the boot is complete, log back in as the astmin user, and temporarily set selinux to ‘Permissive’ (it will reset back to ‘Enforcing’ after each boot, so until we’ve sorted out the SELinux portion of the install, this has to happen on every boot:

$ sudo setenforce Permissive

$ sudo sestatus

Which should show Current mode: permissive

Verify that Asterisk is running with the following command:

$ ps -ef | grep asterisk

You want to see the /user/sbin/asterisk daemon running (currently as user root, but we’ll fix that shortly)

Asterisk is now installed and is running, however there are a few configuration settings we’ll need to make before the system is in any way useful.

Initial Configuration

Asterisk stores its configuration files in the /etc/asterisk folder by default. The asterisk process itself doesn’t need any configuration files in order to run, however it will not be usable in any way, since none of the features it provides have been specified. We’re going to handle a few of the initial configuration tasks now.

Note

Asterisk configuration files use the semicolon (;) character for comments, primarily because the hash character (#) is a valid character on a telephone number pad.

The modules.conf file allows you a fine-grained control over what modules asterisk will (and will not) load. It’s usually not necessary to explicitly define each module in this file, but you could if you wanted to. We’re going to create a very simple file like this:

$ sudo chown asterisk:asterisk /etc/asterisk

$ sudo -u asterisk vim /etc/asterisk/modules.conf

[modules]
autoload=yes
preload=res_odbc.so
preload=res_config_odbc.so

We’re using ODBC to load many of the configurations of other modules, and we this this connector available before Asterisk attempts to load anything else, so we’ll pre-load it.

Note

Don’t worry about the vim error on exit. So long as the file saves with the owner as asterisk, all is well.

Next up, we’re going to tweak the logger.conf file just a bit from the defaults.

$ sudo -u asterisk vim /etc/asterisk/logger.conf

[general]
exec_after_rotate=gzip -9 ${filename}.2;
[logfiles]
;debug => debug
;security => security
console => notice,warning,error,verbose
;console => notice,warning,error,debug
messages => notice,warning,error
full => notice,warning,error,debug,verbose,dtmf,fax
;full-json => [json]debug,verbose,notice,warning,error,dtmf,fax
;syslog keyword : This special keyword logs to syslog facility
;syslog.local0 => notice,warning,error

You will noted that many lines are commented out. They’re simply there as a reference, because you’ll find when debugging your system you may want to frequently tweak this. It’s easier to have a few handy lines prepared and commented out, rather than having to look up the syntax each time.

The next file, asterisk.conf, defines various folders needed for normal operation, as well as parameters needed to run as the asterisk user:

$ sudo -u asterisk vim /etc/asterisk/asterisk.conf

[directories](!)
astetcdir => /etc/asterisk
astmoddir => /usr/lib/asterisk/modules
astvarlibdir => /var/lib/asterisk
astdbdir => /var/lib/asterisk
astkeydir => /var/lib/asterisk
astdatadir => /var/lib/asterisk
astagidir => /var/lib/asterisk/agi-bin
astspooldir => /var/spool/asterisk
[options]
astrundir => /var/run/asterisk
astlogdir => /var/log/asterisk
astsbindir => /usr/sbin
runuser = asterisk    ; The user to run as. The default is root.
rungroup = asterisk   ; The group to run as. The default is root

We’ll configure more files later on, but these are all we need for the time-being.

Let’s update the ownership of the files so the asterisk user has proper access to them.

$ sudo chown -R asterisk:asterisk {/etc,/var/lib,/var/spool,/var/log,/var/run}/asterisk

We also may need to add a rule to the /etc/tmpfiles.d folder, to allow Asterisk to create a socket at runtime.

$ sudo vim /etc/tmpfiles.d/asterisk.conf

d /var/run/asterisk 0775 asterisk asterisk

(see man tmpfiles.d for more information).

Next up, we’re going to initialize the database with the tables Asterisk needs for ODBC-based configuration.

The Asterisk source files include a contribution which the Digium folks maintain as part of Asterisk, in order to version-control the database tables needed. This greatly simplifies keeping the database correct through the upgrade process.

Navigate to the relevant directory, and make a copy of the configuration file.

$ cd ~/src/asterisk-15.<TAB>/contrib/ast-db-manage

$ cp config.ini.sample config.ini

Now, we’re going to open the file and give it the credentials for our database (which are defined in the ansible playbook named starfish.yml, under the variable named current_mysql_asterisk_password, which we used at the beginning of this chapter):

$ vim config.ini

Find the lines that looks similar to this:

#sqlalchemy.url = postgresql://user:pass@localhost/asterisk
sqlalchemy.url = mysql://user:pass@localhost/asterisk

# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic

Make a copy of it, comment it out, and edit it with the correct credentials:

#sqlalchemy.url = postgresql://user:pass@localhost/asterisk
#sqlalchemy.url = mysql://user:pass@localhost/asterisk
sqlalchemy.url = mysql://asterisk:YouNeedAReallyGoodPasswordHereToo@localhost/asterisk

# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic

Now, with that very simple bit of configuration, we can use alembic to automagically configure the database perfectly for Asterisk (this used to be somewhat painful to do in past versions of Asterisk).

$ alembic -c ./config.ini upgrade head

Note

Alembic is not used by Asterisk, so the configuration you’ve just performed does not allow Asterisk to use the database. All it does it run a script which creates the schema and tables which Asterisk will use (you could do this manually as well, but trust us, you want Alemic to handle this). It’s part of the install/upgrade process. It’s especially useful if you have live tables, with real data in them, and want to be able to upgrade and retain the relevant configuration.

Log into the database now, and review all the tables that have been created:

$ mysql -u asterisk -p

mysql> use asterisk;

mysql> show tables;

You should see a list similar to this:

| alembic_version_config      |
| extensions                  |
| iaxfriends                  |
| meetme                      |
| musiconhold                 |
| 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                   |

We’re not going to configure anything in the database as of yet. We’ve got some more base configuration to do first.

Exit the database CLI.

Now that we’ve got the database structure to handle Asterisk config, we’re going to tell Asterisk how to connect to the database.

$ sudo -u asterisk vim /etc/asterisk/res_odbc.conf

Once again, you’ll need the credentials you defined in your ansible playbook.

[asterisk]
enabled => yes
dsn => asterisk
username => asterisk
password => YouNeedAReallyGoodPasswordHereToo
pre-connect => yes

selinux Tweaks

We’re going to install some selinux tools, and make a few changes to the selinux configuration so that the system will boot properly.

Note

OK, so a common thing is to simply edit the /etc/selinux/config, and set enforcing=disabled. We do not recommend this, but doing so completely disables selinux, and renders the following steps unnecessary.

$ sudo yum -y install setools setroubleshoot setroubleshoot-server

$ sudo vim /etc/selinux/config

You’re going to change the line SELINUX=enforcing to SELINUX=permissive. This will ensure the log files show potential selinux errors, without actually blocking the relevant processes.

Next, we’re going to give Asterisk ownership of the /etc/odbc.ini file.

$ sudo chown asterisk:asterisk /etc/odbc.ini

$ sudo semanage fcontext -a -t asterisk_etc_t /etc/odbc.ini

$ sudo restorecon -v /etc/odbc.ini

$ sudo ls -Z /etc/odbc.ini

If all is well, you should see now that the file context for this file has been set to asterisk_etc_t:

-rw-r--r--. asterisk asterisk system_u:object_r:asterisk_etc_t:s0 /etc/odbc.ini

There are a few more selinux errors we’ve seen during the writing of the book here. They may have been corrected by the time you read this, but there should be no harm in running them:

$ sudo /sbin/restorecon -vr /var/lib/asterisk/*

$ sudo /sbin/restorecon -vr /etc/asterisk*

Reboot the system, and we’re going to check the log for any nasty selinux errors before we set it to enforcing.

$ sudo grep -i sealert /var/log/messages

There may be a few messages in there complaining about things Asterisk doesn’t need, but so long as it’s not full of errors complaining about all sorts of important Asterisk components, you should be good to go.

Edit the /etc/selinux/config file again, this time setting SELINUX=enforcing. Save and reboot once more.

Verify that Asterisk is running.

$ ps -ef | grep asterisk

OK, we’re nearly done with the installation now.

Firewall Tweaks

A couple of small fiirewall tweaks prepares our system for SIP (and SIP Secure).

$ sudo firewall-cmd --zone=public --add-service=sips --permanent

$ sudo firewall-cmd --zone=public --add-service=sip --permanent

Final Tweaks

We’ve got the base Asterisk system ready to roll. We are going to put some data into the configuration files so that in the next chapter we can begin to work with our new Asterisk system.

Since we’re going to use the pjsip channel for all of our calling, we’re going to tell Asterisk to look for pjsip configuration in the database:

$ sudo -u asterisk vim /etc/asterisk/sorcery.conf

[res_pjsip] ; Realtime PJSIP configuration wizard
; eventually more modules will use sorcery to connect to the
; database, but currently only PJSIP uses this
endpoint=realtime,ps_endpoints
auth=realtime,ps_auths
aor=realtime,ps_aors
domain_alias=realtime,ps_domain_aliases
contact=realtime,ps_contacts

[res_pjsip_endpoint_identifier_ip]
identify=realtime,ps_endpoint_id_ips

$ sudo -u asterisk vim /etc/asterisk/extconfig.conf

[settings] ; older mechanism for connecting all other modules to the database
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

$ sudo -u asterisk vim /etc/asterisk/modules.conf

[modules]
autoload=yes
preload=res_odbc.so
preload=res_config_odbc.so
noload=chan_sip.so ; deprecated SIP module from days gone by

We now have to place one bit of config into the pjsip.conf file, which defines the transport mechanism.

$ sudo -u asterisk vim /etc/asterisk/pjsip.conf

[transport-udp]
type=transport
protocol=tls
bind=0.0.0.0

Finally, let’s log into the database, and define some sample configurations for PJSIP:

$ mysql -D asterisk -u asterisk -p

mysql>

insert into asterisk.ps_aors (id, max_contacts) values ('0000f30A0A01', 1);
insert into asterisk.ps_aors (id, max_contacts) values ('0000f30B0B02', 1);
insert into asterisk.ps_auths (id, auth_type, password, username) values ('0000f30A0A01', 'userpass', 'not very secure', '0000f30A0A01');
insert into asterisk.ps_auths (id, auth_type, password, username) values ('0000f30B0B02', 'userpass', 'hardly to be trusted', '0000f30B0B02');
insert into asterisk.ps_endpoints (id, transport, aors, auth, context, disallow, allow, direct_media) values ('0000f30A0A01', 'transport-udp', '0000f30A0A01', '0000f30A0A01', 'sets', 'all', 'ulaw', 'no');
insert into asterisk.ps_endpoints (id, transport, aors, auth, context, disallow, allow, direct_media) values ('0000f30B0B02', 'transport-udp', '0000f30B0B02', '0000f30B0B02', 'sets', 'all', 'ulaw', 'no');
exit

Let’s reboot, and then we’ll log into our new Asterisk system and have a look at what we’ve created.

Validating Your New Asterisk System

We don’t need to dive too deeply into the system at this point, since all the chapters that follow will be doing exactly that.

So, all we need to do is verify that we can log into the system, and that the pjsip endpoints we’ve created are there.

$ sudo asterisk -rvvvv

*CLI> pjsip show endpoints

You should see the two endpoints we created listed as follows:

 Endpoint:  <Endpoint/CID.....................................>  <State.....>  <Channels.>
    I/OAuth:  <AuthId/UserName...........................................................>
        Aor:  <Aor............................................>  <MaxContact>
      Contact:  <Aor/ContactUri..........................> <Hash....> <Status> <RTT(ms)..>
  Transport:  <TransportId........>  <Type>  <cos>  <tos>  <BindAddress..................>
   Identify:  <Identify/Endpoint.........................................................>
        Match:  <criteria.........................>
    Channel:  <ChannelId......................................>  <State.....>  <Time.....>
        Exten: <DialedExten...........>  CLCID: <ConnectedLineCID.......>
==========================================================================================
 Endpoint:  0000f30A0A01                                         Not in use    0 of inf
     InAuth:  1/0000f30A0A01
  Transport:  transport-udp             udp      0      0  0.0.0.0:5060

 Endpoint:  0000f30B0B02                                         Unavailable   0 of inf
     InAuth:  2/0000f30B0B02
  Transport:  transport-udp             udp      0      0  0.0.0.0:5060
Objects found: 2

If you don’t see the two endpoints listed, you’ve got a configuration issue. You’re going to have to work backwards to ensure you don’t have any errors which prevent Asterisk from connecting to the database and instantiating these two endpoints.

Common Installation Errors

The following conditions (in no particular order) cause the majority of installation errors:

  • Syntax errors. In some cases, substituting a tab for a space can be enough to break something. UnixODBC, for example, has proven to be sensitive to missing spaces between key = value definitions. The best advice we can give here is to use copy/paste whenever possible, as opposed to manual input.

  • Permissions problems. These can be annoying to resolve, but error messages will generally provide the clues you need. The /var/log/messages file is often a gold mine for useful clues.

  • Missing steps. A missed step might not have any noticeable effects until many steps later. Double check everything, and verify functionality before moving on.

  • Credentials problems. Always verify that the users and passwords you create work manually, before using them in a configuration file.

It’s not possible nor necessary to dig into every warning and error message you might see, but if we’ve provided a test to run, and it doesn’t produce anything like we said it should, you should probably work through that step again until you’ve figured out what’s going on.

Some Final Words

Now that we’ve got Asterisk installed, we can start the next task, which is to configure Asterisk to make calls.

Initial Configuration

Warning

Running make samples on a system that already has configuration files will overwrite the existing files.

Some notes about Asterisk and the shell

1 It’s been released under a Creative Commons license, so if you have purchased a hard copy (and we thank you!), you can also download a soft copy for searching and copying/pasting.

2 Asterisk should run on pretty much any Linux platform, and if you are familiar with the basic process of installing software on a Linux machine, you should find Asterisk a fairly straightforward installation.

3 By which we mostly mean that you are comfortable administering a system exclusively from the shell.

4 After you read our book, of course.

5 On a DigitalOcean instance, you’ll need to ensure your SSH key is in the file /home/astmin/.ssh/authorized_keys.