Running FreePBX Node.js services on RHEL 6

This was a bit of a challenge because FreePBX expects certain minimum versions of nodejs, and then tries to build modules that require a C++ version 11 compiler. As usual, tracking down all the info I needed took longer than doing the actual install:

# Get the repo for the C++ compiler and assembler
wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo
# Install the C++ compiler and assembler
yum -q -y install 'devtoolset-2-gcc-c++' 'devtoolset-2-binutils'
# Ensure the new compiler and assembler are enabled by default
echo 'source scl_source enable devtoolset-2' > /etc/profile.d/devtoolset-2.sh
# Get the repo for Node
wget -qO- https://rpm.nodesource.com/setup_11.x | bash -
# Install Node
yum -q -y install nodejs
# If you've already installed FreePBX 14, you'll need to re-install the UCP module that uses Node
fwconsole ma downloadinstall ucp
# If you've already installed FreePBX 15, you'll need to reinstall the core so the FastAGI server works
fwconsole ma downloadinstall core

# Get the repo for the C++ compiler and assembler wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo # Install the C++ compiler and assembler yum -q -y install 'devtoolset-2-gcc-c++' 'devtoolset-2-binutils' # Ensure the new compiler and assembler are enabled by default echo 'source scl_source enable devtoolset-2' > /etc/profile.d/devtoolset-2.sh # Get the repo for Node wget -qO- https://rpm.nodesource.com/setup_11.x | bash - # Install Node yum -q -y install nodejs # If you've already installed FreePBX 14, you'll need to re-install the UCP module that uses Node fwconsole ma downloadinstall ucp # If you've already installed FreePBX 15, you'll need to reinstall the core so the FastAGI server works fwconsole ma downloadinstall core

You should be able to confirm everything installed ok like so:

node --version
npm --version
fwconsole pm2 --list

node --version npm --version fwconsole pm2 --list

And you should see something like this:

$ node --version
v11.12.0
$ npm --version
6.7.0
$ fwconsole pm2 --list
+--------------+-------+--------+----------+---------------------+-----+---------+
| Process Name | PID   | Status | Restarts | Uptime              | CPU | Mem     |
+--------------+-------+--------+----------+---------------------+-----+---------+
| core-fastagi | 25667 | online | 1        | 12 hours, 5 minutes | 0%  | 12.09MB |
| ucp          | 25025 | online | 1        | 12 hours, 7 minutes | 0%  | 33.86MB |
+--------------+-------+--------+----------+---------------------+-----+---------+

$ node --version v11.12.0 $ npm --version 6.7.0 $ fwconsole pm2 --list +--------------+-------+--------+----------+---------------------+-----+---------+ | Process Name | PID | Status | Restarts | Uptime | CPU | Mem | +--------------+-------+--------+----------+---------------------+-----+---------+ | core-fastagi | 25667 | online | 1 | 12 hours, 5 minutes | 0% | 12.09MB | | ucp | 25025 | online | 1 | 12 hours, 7 minutes | 0% | 33.86MB | +--------------+-------+--------+----------+---------------------+-----+---------+

Asterisk voicemail notifications with MP3

I found a lovely script for sending voicemail notifications in MP3 format instead of wav. It’s a bit of a hack, since Asterisk only provides you with an entire, MIME encoded email message as input. Anyway, I improved it somewhat and wanted to share. This version adds call info and an image to the MP3 file, and is more elegant IMHO – e.g. use of pushd/popd or mktemp.
Continue reading “Asterisk voicemail notifications with MP3”

FreePBX hangs at login

Have you ever clicked on your FreePBX link, get prompted for a password, and then sit staring at your browser “connecting to…” your server forever? Restarting Apache doesn’t work, restarting MySQL doesn’t work, even restarting Asterisk doesn’t work. Meanwhile everything else is running just fine, but you need to restart the entire server before FreePBX starts working again.
Continue reading “FreePBX hangs at login”

Creating a FreePBX module

The process of creating a module for FreePBX is, in theory, documented in a number of wiki pages, but these are worse than nothing. Full of outdated information — some of it labeled as such, some of it not — as well as broken links and vague promises of information “to be determined,” this collection of pages does more harm than good. Here, then, are some pointers to get a module working, presented as a list of files you need to have in your module’s directory.

module.xml
One of the few well documented pages in the wiki, this determines how the module is displayed within the FreePBX menu structure, as well as information on version, change logs, etc. that will be displayed in the module administration page.
install.php
Any code that needs to be executed when the module is installed should be placed here. This includes database setup; the wiki will tell you that install.sql fulfills this purpose, but it doesn’t. Within this file you have access to the $db object, which is a PEAR::DB object. Note that this file gets executed during upgrades as well. So for example if you add a column to an existing FreePBX database table, make sure to catch any errors that might happen if the column already exists from a previous install.
uninstall.php
Similarly, this file is used to clean up after the module is uninstalled. Again, uninstall.sql is not processed properly so all database cleanup should be in this file.
functions.inc.php
This file is necessary if you want to interact with other FreePBX modules; for example, to add a drop-down box while editing an extension. How is this done? During the initialisation stage of the page, before anything is output, config.php runs through the list of installed modules and includes all their functions.inc.php files. It then checks for a function called modulename_configpageinit and executes it if found.
Within this function you can call addguifunc to specify a function to be run when the page displays, and addprocessfunc for one that is run after the page has been submitted for changes. The simple act of adding a drop-down box to a page requires you to prepare a list of items at the initialisation stage (using addoptlist and addoptlistitem) and then refer to that list during page output in your GUI function to actually output the drop-down box (using the gui_selectbox object.) To save the value, your process function is called, and you are given the chance to do what you like with the POST request.
page.modulename.php
This is one of the many things in the wiki marked as “deprecated” with no mention of what replaces it. So I’ve continued to use it for the module’s own page. Unlike other modules’ pages, when you’re creating your own module’s page it is largely included as-is, meaning you can write it like most any PHP page. If you want to do anything “AJAX” in your pages, you’ll need to exit from the page when you return an XML or JSON value; this will prevent FreePBX from tacking it’s own stuff onto the output.

Configure a Cisco 7960 phone for use with Asterisk

This one’s sure to get some hits from Google.

First, if you need to upgrade the phone’s firmware, follow the directions on this page at Cisco. The phones come from Cisco configured to use SCCP instead of SIP, and you’ll almost always want to change the firmware. If you know what you’re doing, you’ll have that done in an hour. I read all these posts from people getting confused and agonizing over the firmware upgrade; 90% of their problems could have been avoided by following that document to the letter.

Anyway, once the phone’s firmware is upgraded you should do a factory reset on the phone. To do that, reboot it by pushing * + Settings + 6 together. As soon as the reboot starts, hold down the # key. After a second it will come up with a message about the factory reset key being detected. Type 123456789*0# and it will ask if you want to keep network settings. Push 2 for no.

Now your phone is wiped out. Most of the configuration files are detailed extensively elsewhere, but the important ones are SIPDefault.cnf and SIP<mac address>.cnf where <mac address> is of course the MAC address of your phone in uppercase. Here’s what you can get away with as a bare minimum (note that these directives can be put in either file, as far as I know):

image_version: "P0S3-07-4-00" ; your firmware image file
proxy1_address: "asterisk.example.com" ; you can put an ip address in as well
proxy_register: 1 ; you can't take incoming calls if you aren't registered
nat_enable: 1 ; obviously don't use this if you're not behind NAT
nat_received_processing: 1 ; same as the last one
telnet_level: 2 ; to get access to all functions in the telnet shell

line1_name: "username" ; your asterisk username from sip.conf
line1_authname: "username" ; this will be the same 99% of the time
line1_password: "secret" ; also from sip.conf
user_info: "none" ; I'm not 100% certain this is necessary

Something important to note is that these values get saved in the phone. That’s why we did the reset. If you don’t explicitly set a value to be empty (“”) it will use the value already in the phone, not the default value.

I spent a day getting “401 Unauthorized” messages back from Asterisk before I added those 2 NAT settings. I’m not sure what the problem was, because Asterisk was getting registration requests from the phone, but for some reason it was responding with 401 until I changes settings on the phone.

I’ll add for the record that getting into the phone via telnet can be very useful. The default password is “cisco” and debug sip-messages followed by register 1 1 is your friend. Also, erase protflash will remove all the setting stored in flash memory, forcing the phone to reget the settings from TFTP. Much better than doing a reboot to reload the config files.