Building Asterisk and FreePBX on fenoras2

Contents

Desiring more control over my landline phone and the E-Help Winnipeg line, both of which are supplied using SIP from VeVoIP, this week I decided to sww what would be needed to build both Asterisk and FreePBX on my home server. Not wanting to disturb my home server unnecessarily, I created a virtual machine on raven that’s essentially a clone of penguin and proceeded to build the programs there.

Most of these steps came from the version 14 installation instructions for CentOS 7 page at freebpx.org.

Compiling and installing Asterisk

Note: If you build a shell script using these commands, you should start it with the following lines:

1
2
3
#!/bin/bash
set -e
set -o pipefail
  1. Add a user to own asterisk

    adduser asterisk -m -c "Asterisk User"
    
  2. Install additional required dependencies

    echo -n "Generating list of installed packages ... "
    rpm -qa | sort >/r/rpm.packages.list; echo "done"
    for PACKAGE in audiofile-devel cronie cronie-anacron crontabs git \
      gnutls-devel gtk2-devel httpd kernel-devel libtiff-devel libuuid-devel \
      libxml2-devel lynx mariadb mariadb-server mysql-connector-odbc \
      ncurses-devel net-tools newt-devel python-devel sox sqlite-devel \
      subversion texinfo tftp-server unixODBC uuid-devel vim wget
    do
      echo -e "________________________________________________________________________________\n\n$PACKAGE\n"
      if grep -q "^$PACKAGE-" /r/rpm.packages.list
        then echo "Already installed"
        else yum install -y $PACKAGE 2>&1 | tee ~/packages/install.$PACKAGE.text
      fi
    done
    
  3. The instructions at this point are to install PHP 5.6, but PHP 7.2 is already on the system. PHP 7.2 is largely compatible with 5.6 (PHP 6 was developed but never relased; changes were either backported into 5.6 or rolled forward into a re-write that became PHP 7.) Here’s hoping nothing breaks in FreePBX due to the newer PHP, since I need PHP 7 for pi-hole.

  4. Install nodejs from the nodesource repository

    curl -sL https://rpm.nodesource.com/setup_8.x | bash -
    yum install -y nodejs
    
  5. Install PHP Console_GetOpt

    PACKAGE=php-pear; yum install -y $PACKAGE 2>&1 | tee ~/packages/install.$PACKAGE.text
    pear install Console_Getopt
    --> pear/Console_Getopt is already installed and is the same as the released version 1.4.2
    
  6. Download Asterisk source files. I chose to install Asterisk 16, which is the latest version and is supported by FreePBX.

    cd /var/tmp
    wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-current.tar.gz
    wget -O jansson.tar.gz https://github.com/akheron/jansson/archive/v2.11.tar.gz
    wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-16-current.tar.gz
    
  7. The instructions at this point are to install DAHDI, but that wasn’t needed for my setup because DAHDI is used to talk to analogue telephony cards, and my setup is SIP only.

  8. Compile and install jansson

    cd /var/tmp
    tar xzf jansson.tar.gz
    cd $(ls -ld jansson* | awk '/^d/{print $9}')
    (autoreconf -i && ./configure --libdir=/usr/lib64 && make && make install) 2>&1 | jtime | tee build.text
    
  9. Unpack Asterisk and remove unneeded packages from contrib/scripts/install_prereq

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    cd /var/tmp
    tar xzf asterisk*.tar.gz
    ASTERISK_DN="$(ls -ld asterisk* | awk '/^d/{print $9}')"
    cd $ASTERISK_DN
    cd contrib/scripts
    mv install_prereq install_prereq.orig
    sed 's/^\(.*\)jansson-devel /\1/
      s/^\(.*\)postgresql-devel /\1/
      #s/^\(.*\)unixODBC-devel /\1/     # This one is commented out for now
      s/^\(.*\)radcli-devel /\1/
      s/^\(.*\)freetds-devel /\1/
    ' install_prereq.orig >install_prereq
    RC=$?
    [ $RC == 0 ] && chmod +x install_prereq
    cd ../..
    
  10. Install Asterisk pre-requisite packages

    set -o pipefail
    [ $RC == 0 ] && contrib/scripts/install_prereq install 2>&1 | jtime | tee build.1.install_prereq.text
    RC=$?
    # (Above step installed 37 packages and 60 additional dependent packages)
    if [ $RC == 0 ]; then
      ./configure --prefix=/opt/$ASTERISK_DN --with-pjproject-bundled 2>&1 |
        jtime | tee build.2.configure.text
      RC=$?
    fi
    [ $RC == 0 ] && contrib/scripts/get_mp3_source.sh 2>&1 | jtime | tee build.3.get_mp3_source.text
    

    The install_prereq step installed PostgreSQL, which I’m not sure is needed since Asterisk can use MariaDB and sqlite3.

  11. Configure Asterisk using menuselect

    [ -t 1 ] || exit    # Exit if stdout is redirected
    make menuselect     # Note we're not redirecting stdout
    

    Most options are good as-is, but some need to be changed:

    • Select Add-ons > format_mp3
    • Select Applications > app-macro (in the deprecated section)
    • In Call Detail Recording and Channel Event Logging, deselect any extended module mentioning _csv, _pgsql, _radius, or _tds (leave the core modules alone)
    • For my initial build I also selected all the AGI Samples
    • Select Core Sound Packaages > CORE-SOUNDS-EN-WAV
    • Select Extras Sound Packages > EXTRA-SOUNDS-EN-WAV
  12. Build and install Asterisk

    set -o pipefail
    make 2>&1 | jtime | tee build.4.make.text
    [ $? == 0 ] && make install 2>&1 | jtime | tee build.5.make-install.text
    [ $? == 0 ] && make samples 2>&1 | jtime | tee build.6.make-samples.text
    [ $? == 0 ] && make basic-pbx 2>&1 | jtime | tee build.7.make-basic-pbx.text
    [ $? == 0 ] && make config      # Sets up systemd; no output
    
  13. Create symlinks. I put asterisk into /opt, but I want to have symlinks in the main file system. For example, /var/log/asterisk should point to /opt/asterisk/var/log/asterisk.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    cd /opt
    [ -d asterisk ] || ln -s $ASTERISK_DN asterisk
    cd asterisk
    find . -type d | grep -v asterisk | while read DIR
    do
      [ -d $DIR/asterisk ] || continue
      DN="${DIR:2}"
      SOURCE_DN="/opt/asterisk/$DN/asterisk"
      SYMLINK_DN="/$DN/asterisk"
      [ "$DN" == 'include' ] && SYMLINK_DN="/usr/$DN/asterisk"
      #[ "$DN" == 'lib' ] && SYMLINK_DN="/lib64/asterisk"
      if [ ! -L $SYMLINK_DN ]; then
        echo "Symlink $SOURCE_DN to $SYMLINK_DN"
        ln -s $SOURCE_DN $SYMLINK_DN
      fi
      ls -ld $SYMLINK_DN
    done
    cd /opt/asterisk/sbin
    for FILE in *; do
        echo "Symlink $PWD/$FILE to /usr/sbin/$FILE"
        ln -s $PWD/$FILE /usr/sbin/$FILE
    done
    
  14. Set ownership and permissions

    chown -R asterisk:apache /opt/$ASTERISK_DN
    chown -R apache:apache /var/lib/php
    LOG_DN="/opt/asterisk/var/log/asterisk"
    chgrp apache $LOG_DN; chmod 775 $LOG_DN; unset LOG_DN
    #chown -R asterisk. /var/www/               # DON'T DO THIS
    
  15. Update ldconfig

    echo /opt/asterisk/lib >/etc/ld.so.conf.d/asterisk.conf
    ldconfig -v 2>&1 | jtime | tee build.8.ldconfig.text
    

Installing FreePBX

Typically I prefer to learn the base product instead of relying on a GUI of some description to do the work for me. I make an exception for Asterisk, because it’s a large and complex product in its own right, and I invested a lot of time into learning FreePBX.

Note: If you build a shell script using these commands, you should start it with the following lines:

1
2
3
#!/bin/bash
set -e
set -o pipefail

Also remove references to | jtime if you want pipe output frrom the script to jtime.

  1. Set up database tables and permissions

    echo "GRANT ALL ON asterisk.* TO asterisk@localhost IDENTIFIED BY 'MGMyMWUxN2Y1'" | mysql
    echo "GRANT ALL ON asteriskcdrdb.* TO asterisk@localhost" | mysql
    echo "CREATE DATABASE asterisk; CREATE DATABASE asteriskcdrdb" | mysql
    
  2. Fix up /etc/asterisk.conf to prevent the FreePBX install from failing

    cd /etc/asterisk
    awk '/\[directories\]/ { sw = 1 }; sw { print }
      /^[[:space:]]*$/ { sw = 0 }' asterisk.conf.old >asterisk.conf.new
    cat asterisk.conf >>asterisk.conf.new
    mv asterisk.conf.old asterisk.conf.older
    mv asterisk.conf asterisk.conf.old
    mv asterisk.conf.new asterisk.conf
    
  3. Install expect

    PACKAGE=expect; yum install -y $PACKAGE 2>&1 | tee ~/packages/install.$PACKAGE.text
    
  4. Download FreePBX itself (see downloads page, in the section titled FreePBX Manual/Tarball Install)

    cd /var/tmp
    wget http://mirror.freepbx.org/modules/packages/freepbx/freepbx-14.0-latest.tgz
    tar xzf freepbx-14.0-latest.tgz
    FREEPBX_VER="$(awk 'match($0,/<version>([^<]+)/,a){print a[1]; exit}' freepbx/module.xml)"
    if [ "$FREEPBX_VER" ]
    then
        FREEPBX_DN="freepbx-$FREEPBX_VER"; unset FREEPBX_VER
        mv freepbx $FREEPBX_DN
        RC=0
    else
        RC=1
    fi
    
  5. Set up an expect script for installing FreePBX

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #!/bash
    cat <<-EOF | sed 's/^[[:space:]]*//; s/\\t/\t/g' >/r/install-freepbx.expect
        #!/usr/bin/expect -f
        set timeout 1
        spawn ./install
        expect -re "Database engine.*: ";\t\t\t\t\t\t\t\tsend "\\r"
        expect -re "Database name.*: ";\t\t\t\t\t\t\t\t\tsend "\\r"
        expect -re "CDR Database name.*: ";\t\t\t\t\t\t\t\tsend "\\r"
        expect -re "Database username.*: ";\t\t\t\t\t\t\t\tsend "asterisk\\r"
        expect "Database password: ";\t\t\t\t\t\t\t\t\tsend "MGMyMWUxN2Y1\\r"
        expect -re "File owner user.*: ";\t\t\t\t\t\t\t\tsend "apache\\r"
        expect -re "File owner group.*: ";\t\t\t\t\t\t\t\tsend "asterisk\\r"
        expect -re "Filesystem location .* FreePBX files.*: ";\t\t\tsend "/var/www/freepbx\\r"
        expect -re "Filesystem location .* Asterisk config.*: ";\t\tsend "\\r"
        expect -re "Filesystem location for Asterisk modules.*: ";\t\tsend "\\r"
        expect -re "Filesystem location for Asterisk lib files.*: ";\tsend "\\r"
        expect -re "Filesystem location for Asterisk agi files.*: ";\tsend "\\r"
        expect -re "Location of the Asterisk spool directory.*: ";\t\tsend "\\r"
        expect -re "Location of the Asterisk run directory.*: ";\t\tsend "\\r"
        expect -re "Location of the Asterisk log files.*: ";\t\t\tsend "\\r"
        expect -re "Location of the FreePBX command line scripts.*: ";\tsend "\\r"
        expect -re "Location of the FreePBX .root. command line scripts.*: ";\tsend "\\r"
        expect -re "Location of the Apache cgi-bin executables.*: ";\tsend "/var/www/freepbx/cgi-bin\\r"
        expect -re "Directory for FreePBX html5 playback files.*: ";\tsend "\\r"
        set timeout -1
        expect eof
    EOF
    chmod +x /r/install-freepbx.expect
    
  6. Install FreePBX

    if [ "$FREEPBX_DN" ]; then
      cd $FREEPBX_DN
    
      # Start asterisk and fix up /opt/asterisk/var/run/asterisk/asterisk.ctl
      echo "----- Start asterisk and fix up /opt/asterisk/var/run/asterisk/asterisk.ctl"
      ./start_asterisk start
      chgrp apache /opt/asterisk/var/run/asterisk/asterisk.ctl
      chmod 775 /opt/asterisk/var/run/asterisk/asterisk.ctl
    
      mv /r/install-freepbx.expect .
      ./start_asterisk start
      ./install-freepbx.expect 2>&1 | jtime | tee install.text; RC=$?;
    fi
    
  7. Fix up the directory name in /var/www; fix some permissions

    cd /var/www
    mv freepbx $FREEPBX_DN
    ln -s $FREEPBX_DN freepbx
    chown apache:apache /etc/freepbx.conf
    chown asterisk:apache /etc/amportal.conf
    
  8. Set up an Apache configuration for FreePBX

    CONF_FN="/etc/httpd/conf.d/freepbx.conf"
    echo '# FreePBX' >$CONF_FN
    echo 'Alias "/freepbx" "/var/www/freepbx/"' >>$CONF_FN
    echo >>$CONF_FN
    echo '<Directory "/var/www/freepbx/">' >>$CONF_FN
    echo '    Options Indexes' >>$CONF_FN
    echo '    AllowOverride None' >>$CONF_FN
    echo '    Order allow,deny' >>$CONF_FN
    echo '    Allow from all' >>$CONF_FN
    echo '    Options FollowSymlinks' >>$CONF_FN
    echo '    AlloowOverride All' >>$CONF_FN
    echo '</Directory>' >>$CONF_FN
    unset CONF_FN
    
  9. Upgrade Asterisk modules to their most recent stable versions

    cd /var/tmp
    fwconsole ma upgradeall 2>&1 | jtime | tee fwconsole.ma.upgradeall.text
    
  10. Install all available FreePBX modules

    cd /var/tmp
    /var/lib/asterisk/bin/module_admin installall 2>&1 | jtime | tee module_admin.installall.text
    
  11. Restart apache

    apachectl stop
    sysstemctl start httpd
    

Issues with running FreePBX on a shared server

  • Running FreePBX as the asterisk user casues an error during setup from the web interface:
      Execption: Trying to edit user asterisk, when I'm running as apache
      in /var/www/freepbx/admin/libraries/BMO/Cron.class.php
  • Running FreePBX as the apache user causes an error during installation when the installer tries to talk to asterisk as the apache user and fails (it then recommends running asterisk as the apache user.)
    –> One way to fix this is to modify the socket file /run/asterisk/asterisk.ctl to use group apache and group write permission (chmod 775.)
      ln -s /opt/asterisk/var/run/asterisk /run/asterisk
      chgrp apache /run/asterisk/asterisk.ctl && chmod 775 /run/asterisk/asterisk.ctl

Configuring FreePBX

  • Administrator user/password: taomir / ********
  • Notifications Email address: freepbx@groupbcl.ca