Multiple Instances on a Single Server

Asad Khan
Senior Product Manager at Vodia Networks
Vodia PBX server
Most servers today have multiple CPU cores. In many cases in order to reduce operational costs it makes sense to run multiple instances on that server. But it also makes sense to run multiple instances if the customization requires that separate instances must be run. This way you can have several hundred, maybe even a thousand domains on a single server with excellent server performance, all at typical hosting costs down to less than a dollar per domain and month. This blog entry shows show to do this on a CentOS installation.

1. Installing the First Instance

Installing the first instance is just like installing any other PBX instance. In anticipation of the other instances, you might want to use the working directory /usr/local/pbx-1, so that the other instances have similar path names. Or you include the later IP address in the path name so that you can easier see which one is which. But it is also okay to name the first directory /usr/local/pbx in case you have already done that.

2. Adding Directories

Once the first PBX is installed, the easiest is to copy just the PBX executable and the .dat file into the directory of the other instances. This means that those instances will start off with whatever software version you are running there. Later, if you decide to perform a software upgrade, you can upgrade each instance independently.
If you are using a backup cloud service, you might also want to add those directories for backup, so that in a case of a fatal crash you still have the data.

3. Separate IP addresses

On the operating system level you should have one public (whatever that is) IPv4 address per PBX instance on your server. Unfortunately IPv6 has not made it into the mainstream yet, where this would be a lot easier.
It is possible to have multiple PBX running on the same IP address and just run the different instances on different, non-standard ports. However this will have several drawbacks: First of all, telling your users that they have to log in on a non-standard port is somewhat unusual. And secondly, using a standard port makes it easy to obtain SSL certificates through challenges on port 80.
The biggest problem will be to get those IP addresses assigned from your hosting company. This is something that you need to figure out yourself and which is different from installation to installation.
Once the PBX is running, you need to bind all ports to the assigned IP address. The easiest way to do this is to set up the first PBX instance with the right IP address bindings. You need to do this for the HTTP, HTTPS, SIP, SIPS, and TFTP ports. For example, if your server has the address 1.2.3.4, you would use 1.2.3.4:80 for the HTTP port. IMHO there is no need to have the TFTP port open if your are running this as a hosted PBX service. You also need to set the address for "Bind to specific IP address (IPv4)" setting in the RTP settings (reg_rtpsettings.htm). Having an overlapping port range is no problem as the PBX will automatically pick a random port anyway, however if you want to be super sure that this is no problem you can assign separate RTP port ranges for each instance.
Then copy the pbx.xml file to the other directories and edit it with a standard text editor and replace the IP addresses of the first instance with the IP address for the other instances. Then when you start those instances up they will bind to the right address right from the start.

4. Separate startup scripts

Having separate startup scripts has the advantage that you can easily control each of the instance. You can use the following script for each instance, just edit the INSTANCE variable in the script:

#!/bin/bash
#
# pbx      This takes care of starting and stopping the Vodia PBX.
#
# chkconfig: - 20 80
# description: Vodia PBX PBX \
# Vodia PBX is a software-based private branch exchange (PBX) for \
# devices that support the SIP protocol. It provides telephony \
# services as well as associated services like provisioning devices \
# for telephony.

### BEGIN INIT INFO
# Provides: pbx
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs $remote_fs
# Should-Start: $syslog $named ntpdate
# Should-Stop: $syslog $named
# Short-Description: start and stop the Vodia PBX

# Description: Vodia PBX is a software-based private branch exchange
#              (PBX) for devices that support the SIP protocol. It
#              provides telephony services as well as associated
#              services like provisioning devices for telephony.

### END INIT INFO

# Source function library.
. /etc/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

INSTANCE=1
PBX_DIR=/usr/local/pbx-$INSTANCE
PROG=$PBX_DIR/pbxctrl
PIDFILE=/var/run/pbx-$INSTANCE
LOCKFILE=/var/lock/subsys/pbxctrl-$INSTANCE
OPTIONS="--respawn --dir $PBX_DIR --pidfile $PIDFILE"

start() {
        [ "$EUID" != "0" ] && exit 4
        [ "$NETWORKING" = "no" ] && exit 1
        [ -x $PROG ] || exit 5
}

stop() {
        [ "$EUID" != "0" ] && exit 4
        PID=$(cat $PIDFILE)
        echo -n $"Shutting down $PROG: "
        /bin/kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f $LOCKFILE
        return $RETVAL
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status $PROG
        ;;
  restart|force-reload)
        stop
        start
        ;;
  try-restart|condrestart)
        if status $PROG > /dev/null; then
            stop
            start
        fi
        ;;
  reload)
        exit 3
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}"
        exit 2
esac
 

4. Failover

Failover works exactly like a single instance failover. However because some files are stored outside of the directory (to differentiate between the primary and secondary), you need to make sure that those files are also names after the instance name. 

5. Fine-tuning

Once that the PBX are running, it makes sense to set the processor affinity so that the operating system does not start shuffling processes around once you get load on the system.
Outgoing TCP connection e.g. from the HTTP client or when sending emails will still be done from the standard IP address of the system. This is usually not a problem, except when customers get confused that they receive traffic from a different IP address than they are expecting. If this is a problem, it might be necessary to reserve the standard IP address for this purpose and don't run a PBX instance on it.

6. Further Thinking

For other operating systems, this will be similar. We have seen multiple instances working also in Windows, though the setup there requires a proper setup with the service manager.
There are alternatives to this. The first one is to leverage the container service (Docker) to let it handle the instances. This further increases the separation of the systems. When using Docker you need to pay attention to the performance of the networking subsystem, as Docker mostly addresses systems with only a few ports that need to be exposed in the container. If you expose thousands of RTP ports this will be a different setup and it might make sense to expose the full port range of a IP address of the system. This will be similar to the setup with the different directories.
The other alternative is of course the virtualization of the server. This is mainstream in the hosting industry; however it is important to pay attention to the CPU resource allocation so that the PBX gets the CPU when there is work to do especially on the RTP side. Sharing the RAM can also have a negative effect on performance which needs to be kept in mind.
As always, at Vodia we are happy to help you with your installation and make sure that you experience smooth operations.