Using Realtime

The Asterisk Realtime Architecture (ARA) enables you to store the configuration files (that would normally be found in /etc/asterisk) and their configuration options in a database table. There are two types of realtime: static and dynamic.

The static version is similar to the traditional method of reading a configuration file, except that the data is read from the database instead.

The dynamic realtime method, which loads and updates the information as it is required, is used for things such as SIP/IAX2 user and peer objects and voicemail.

Making changes to static information requires a reload, just as if you had changed a text file on the system, but dynamic information is polled by Asterisk as needed, so no reload is required when changes are made to this data. Realtime is configured in the extconfig.conf file located in the /etc/asterisk directory. This file tells Asterisk what to load from the database and where to load it from, allowing certain files to be loaded from the database and other files to be loaded from the standard configuration files.

Static Realtime

Static realtime is useful when you want to load from a database the configuration that you would normally place in the configuration files in /etc/asterisk. The same rules that apply to flat files on your system still apply when using static realtime. For example, after making changes to the configuration you must either run the reload command from the Asterisk CLI, or reload the module associated with the configuration file (e.g., using module reload

When using static realtime, we tell Asterisk which files we want to load from the database using the following syntax in the extconfig.conf file:

; /etc/asterisk/extconfig.conf
filename.conf => driver,database[,table]


If the table name is not specified, Asterisk will use the name of the file as the table name instead.

The static realtime module uses a specifically formatted table to read the configuration of static files in from the database. Table 16.2, “Table layout and description of ast_config” illustrates the columns as they should be defined in your database:

Table 16.2. Table layout and description of ast_config

Column nameColumn typeDescription
idSerial, auto-incrementingAn auto-incrementing unique value for each row in the table.
cat_metricIntegerThe weight of the category within the file. A lower metric means it appears higher in the file (see the sidebar ).
var_metricIntegerThe weight of an item within a category. A lower metric means it appears higher in the list (see the sidebar ). This is useful for things like codec order in sip.conf, or iax.conf where you want disallow=all to appear first (metric of 0), followed by allow=ulaw (metric of 1), then allow=gsm (metric of 2).
filenameVarchar 128The filename the module would normally read from the hard drive of your system (e.g., musiconhold.conf, sip.conf, iax.conf, etc.).
categoryVarchar 128The section name within the file, such as [general]. Do not include the square brackets around the name when saving to the database.
var_nameVarchar 128The option on the left side of the equals sign (e.g., disallow is the var_name in disallow=all).
var_valVarchar 128The value of an option on the right side of the equals sign (e.g., all is the var_val in disallow=all).
commentedIntegerAny value other than 0 will evaluate as if it were prefixed with a semicolon in the flat file (commented out).

A simple file we can load from static realtime is the musiconhold.conf[149] file. Let’s start by moving this file to a temporary location:

$ cd /etc/asterisk
$ mv musiconhold.conf musiconhold.conf.old

In order for the classes to be removed from memory, we need to restart Asterisk. Then we can verify that our classes are blank by running moh show classes:

*CLI> core restart now
*CLI> moh show classes

Let’s put the [default] class back into Asterisk, but now we’ll load it from the database. Connect to your database and execute the following INSERT statements:

> INSERT INTO ast_config (filename,category,var_name,var_val)
  VALUES ('musiconhold.conf','default','mode','files');

> INSERT INTO ast_config (filename,category,var_name,var_val)
  VALUES ('musiconhold.conf','default','directory','/var/lib/asterisk/moh');

You can verify that your values have made it into the database by running a SELECT statement:

asterisk=# SELECT filename,category,var_name,var_val FROM ast_config;

 filename         | category       | var_name     | var_val
 musiconhold.conf | default        | mode         | files
 musiconhold.conf | default        | directory    | /var/lib/asterisk/moh
(2 rows)

There’s one last thing to modify in the extconfig.conf file in the /etc/asterisk directory to tell Asterisk to get the data for musiconhold.conf from the database using the ODBC connection. The first column states that we’re using the ODBC drivers to connect (res_odbc.conf) and that the connection name is asterisk (as defined with [asterisk] in res_odbc.conf). Add the following line to the end of the extconfig.conf file, and then save it:

musiconhold.conf => odbc,asterisk,ast_config

Then connect to the Asterisk console and perform a reload:

*CLI> module reload

You can now verify that your music on hold classes are loading from the database by running moh show classes:

*CLI> moh show classes
Class: general
        Mode: files
        Directory: /var/lib/asterisk/moh

And there you go: musiconhold.conf loaded from the database. If you have issues with the reload of the module loading the data into memory, try restarting Asterisk. You can perform the same steps in order to load other flat files from the database, as needed.

Dynamic Realtime

The dynamic realtime system is used to load objects that may change often, such as SIP/IAX2 users and peers, queues and their members, and voicemail messages. Likewise, when new records are likely to be added on a regular basis, we can utilize the power of the database to let us load this information on an as-needed basis.

All of realtime is configured in the /etc/asterisk/extconfig.conf file, but dynamic realtime has well-defined configuration names. Defining something like SIP peers is done with the following format:

; extconfig.conf
sippeers => driver,database[,table]

The table name is optional. If it is omitted, Asterisk will use the predefined name (i.e., sippeers) to identify the table in which to look up the data.


Remember that we have both SIP peers and SIP users: peers are end-points we send calls to, and a user is something we receive calls from. A friend is shorthand that defines both.

In our example, we’ll be using the ast_sippeers table to store our SIP peer information. So, to configure Asterisk to load all SIP peers from our database using realtime, we would define something like this:

; extconfig.conf
sippeers => odbc,asterisk,ast_sipfriends

To also load our SIP users from the database, we would define the sipusers object like so:

sipusers => odbc,asterisk,ast_sipfriends

You may have noticed we used the same table for both the sippeers and sipusers. This is because there will be a type field (just as if we were defining the type in the sip.conf file) that will let us define a type of user, peer, or friend. If you unload and then load it back into memory (i.e., using module unload followed by module load after configuring extconfig.conf, you will be greeted with some warnings telling you which columns you’re missing for the realtime table. Since we’ve enabled sippeers and sipusers in extconfig.conf, we will get the following on the console (which has been trimmed due to space requirements):

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'name', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'ipaddr', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'port', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'regseconds', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'defaultuser', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'fullcontact', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'regserver', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'useragent', but that column does not exist!

WARNING: Realtime table ast_sipfriends@asterisk requires column 
'lastms', but that column does not exist!

As you can see, we are missing several columns from the table ast_sipfriends, which we’ve defined as connecting to the asterisk object as defined in res_odbc.conf. The next step is to create our ast_sipfriends table with all the columns listed by the warning messages, in addition to the following: the type column, which is required to define users, peers, and friends; the secret column, which is used for setting a password; and the host column, which allows us to define whether the peer is dynamically registering to us or has a static IP address. Table 16.3, “Minimal sippeers/sipusers realtime table” lists all of the columns that should appear in our table, and their types.

Table 16.3. Minimal sippeers/sipusers realtime table

Column nameColumn type
typeVarchar 6
nameVarchar 128
secretVarchar 128
contextVarchar 128
hostVarchar 128
ipaddrVarchar 128
portVarchar 5
defaultuserVarchar 128
fullcontactVarchar 128
regserverVarchar 128
useragentVarchar 128

For each peer you want to register, you need to insert data in the columns type, name, secret, context, host, and defaultuser. The rest of the columns will be populated automatically when the peer registers.

The port, regseconds, and ipaddr fields are required to let Asterisk store the registration information for the peer so it can determine where to send the calls. (Note that if the peer is static, you will have to populate the ipaddr field yourself.) The port field is optional and defaults to the standard port defined in the [general] section, and the regseconds will remain blank. Table 16.4, “Example information used to populate the ast_sipfriends table” lists some sample values that we’ll use to populate our ast_sipfriends table.

Table 16.4. Example information used to populate the ast_sipfriends table

Column nameValue

Prior to registering your peer, though, you need to enable realtime caching in sip.conf. Otherwise, the peer will not be loaded into memory, and the registration will not be remembered. If your peers only place calls and don’t need to register to your system, you don’t need to enable realtime caching because the peers will be checked against the database each time they place a call. However, if you load your peers into memory, the database will only need to be contacted on initial registration, and after the registration expires.

Additional options in sip.conf exist for realtime peers. These are defined in the [general] section and described in Table 16.5, “Realtime options in sip.conf”.

Table 16.5. Realtime options in sip.conf

Configuration optionDescription
rtcachefriendsCaches peers in memory on an as-needed basis after they have contacted the server. That is, on Asterisk start, the peers are not loaded into memory automatically; only after a peer has contacted the server (e.g., via a registration or phone call) is it loaded in memory. Values are yes or no.
rtsavesysnameWhen a peer registers to the system, saves the systemname (as defined in asterisk.conf) into the regserver field within the database. (See Setting the systemname for Globally Unique IDs for more information.) Using regserver is useful when you have multiple servers registering peers to the same table. Values are yes or no.
rtupdateSends registration information such as the IP address, the origination port, the registration period, and the username of the user-agent to the database when a peer registers to Asterisk. Values are yes or no, and the default is yes.
rtautoclearAutomatically expires friends on the same schedule as if they had just registered. This causes a peer to be removed from memory when the registration period has expired, until that peer is requested again (e.g., via registration or placing a call). Values are yes, no, or an integer value that causes the peers to be removed from memory after that number of seconds instead of the registration interval.
ignoreregexpireWhen enabled, peers are not removed from memory when the registration period expires. Instead, the information is left in memory so that if a call is requested to an endpoint that has an expired registration, the last known information (IP address, port, etc.) will be tried.

After enabling rtcachefriends=yes in sip.conf and reloading (using module reload, you can register your peer to Asterisk using realtime, and the peer should then be populated into memory. You will be able to verify this by executing the sip show peers command on the Asterisk console:

Name/username              Host         Dyn Port Status      Realtime
0000FFFF0008/0000FFFF0008  D  5060 Unmonitored Cached RT

If you were to look at the table in the database directly, you would see something like this:

| type   | name         | secret  | context   | host    | ipaddr       |
| friend | 0000FFFF0008 | welcome | LocalSets | dynamic | | 
| port | regseconds | defaultuser  | fullcontact                         |
| 5060 | 1283928895 | 0000FFFF0008 | sip:0000FFFF0008@ |
| regserver | useragent       | lastms |
| NULL      | Zoiper rev.6739 |      0 | 

There are many more options for that we can define for SIP friends, such as the caller ID; adding that information is as simple as adding a callerid column to the table. See the sip.conf.sample file for more options that can be defined for SIP friends.

[149] The musiconhold.conf file can also be loaded via dynamic realtime, but we’re using it statically as it’s a simple file that makes a good example.