Building a self-hosted solution (not on AWS)

If you are using your own hardware, or a hosting provider other than AWS, there is a little more elbow grease required. Follow the instructions below to create a jambonz deployment consisting of one SBC and one Feature Server. You will also be provisioning a mysql server and a redis server.

A. Provision servers

You'll need two servers -- one will be the public-facing SBC, while the other will be the feature server. The SBC must have a public address; the Feature Server does not necessarily need a public address, but of course will need connectivity to the SBC, the mysql database, the redis server, and outbound connectivity to the internet in order to complete the install.

If desired, you can install mysql and redis on the SBC server, but as long as they are reachable from both the SBC and the Feature Server you'll be fine. We will be using ansible to build up the servers, which means from your laptop you need ssh connectivity to both the SBC and the Feature Server.

The base software distribution for both the SBC and the Feature Server should be Debian 10. A vanilla install that includes sudo and python is all that is needed (python is used by ansible, which we will be using to build up the servers in the next step).

B. Use ansible to install base software

If you don't have ansible installed on your laptop, install it now following these instructions.

Check out the following github repos to your laptop:

ansible-role-drachtio

ansible-role-fsmrf

ansible-role-nodejs

ansible-role-rtpengine

For the SBC, create an ansible playbook that looks like this, and run it:

---
- hosts: all
  become: yes
  vars: 
    drachtioBranch: develop
    rtp_engine_version: mr8.5
  vars_prompt:
    - name: "cloud_provider"
      prompt: "Cloud provider: aws, gcp, azure, digital_ocean"
      default: none
      private: no
  roles:
    - ansible-role-drachtio
    - ansible-role-nodejs
    - ansible-role-rtpengine

and for the Feature Server, create an ansible playbook that looks like this, and run it:

---
- hosts: all
  become: yes
  vars:
    drachtioBranch: develop
    build_with_grpc: true
  vars_prompt:
    - name: "cloud_provider"
      prompt: "Cloud provider: aws, gcp, azure, digital_ocean"
      default: none
      private: no
  roles:
    - ansible-role-drachtio
    - ansible-role-nodejs
    - ansible-role-fsmrf
C. Create mysql database

You need to install a mysql database server. Example instructions for installing mysql are provided here.

Once the mysql server is installed, create a new database named 'jambones' with an associated username 'admin' and a password of your choice. For the remainder of these instructions, we'll assume a password of 'JambonzR0ck$' was assigned, but you may create a password of your own choosing.

Once the database and user has been created, then create the database schema by running this script.

Next, run this database script to seed the database.

D. Install influxdb

Influxdb is used to call detail records and platform metrics. You will need to install an influxdb database either on the SBC or somewhere else in your network. For an example install script, refer to this bash script.

E. Install telegraf

Telegraf should be installed on the SBC. Telegraf is used to receive platform metrics and forward them to influxdb For an example install script, refer to this bash script and configure /etc/telegraf.conf to send data onwards to influxdb as shown here

F. Create redis server

Install redis somewhere either on the SBC or somewhere in your network by following these instructions and save the redis hostname that you will use to connect to it.

G. Configure SBC

Your SBC should have both a public IP and a private IP. The public IP needs to be reachable from the internet, while the private IP should be on the internal subnet, and thus reachable by the Feature Server.

In the examples below, we assume that the public IP is 190.144.12.220 and the private IP is 192.168.3.11. Your IPs will be different of course, so substitute the correct IPs in the changes below.

drachtio configuration

In /etc/systemd/system/drachtio.service change this line:

ExecStart=/usr/local/bin/drachtio --daemon

to this:

ExecStart=/usr/local/bin/drachtio --daemon \
--contact sip:192.168.3.11;transport=udp --external-ip 190.144.12.220 \
--contact sip:192.168.3.11;transport=tcp \
--address 0.0.0.0 --port 9022

or, if you plan on enabling Microsoft Teams routing, to this:

ExecStart=/usr/local/bin/drachtio --daemon \
--contact sip:192.168.3.11;transport=udp --external-ip 190.144.12.220 \
--contact sips:192.168.3.11:5061;transport=tls --external-ip 190.144.12.220 \
--contact sip:192.168.3.11;transport=tcp \
--address 0.0.0.0 --port 9022

Then, edit /etc/drachtio.conf.xml to uncomment the request-handler xml tag and edit it to look like this:

    <request-handlers>
	    <request-handler sip-method="INVITE">http://127.0.0.1:4000</request-handler>
    </request-handlers>

Then, reload and restart the drachtio server

systemctl daemon-reload
systemctl restart drachtio

After doing that, run systemctl status drachtio and check /var/log/drachtio/drachtio.log to verify that the drachtio server started properly and is listening on the specified IPs and ports.

rtpengine configuration

In /etc/systemd/system/rtpengine.service change this line:

ExecStart=/usr/local/bin/rtpengine --interface 192.168.3.11!192.168.3.11 \

to this:

ExecStart=/usr/local/bin/rtpengine \
--interface private/192.168.3.11 \
--interface public/192.168.3.11!190.144.12.220 \

Then, reload and restart rtpengine

systemctl daemon-reload
systemctl restart rtpengine

After doing that, run systemctl status rtpengine to verify that rtpengine is running with the defined interfaces.

Note: rtpengine logs to /var/log/daemon.log.

Install drachtio apps

Choose a user to install the drachtio applications under -- the instructions below assume the admin user; if you use a different user than edit the instructions accordingly (note: the user must have sudo priviledges).

Execute the following commands from the home directory of the install user:

mkdir apps && cd $_
git clone https://github.com/jambonz/sbc-outbound.git 
git clone https://github.com/jambonz/sbc-inbound.git 
git clone https://github.com/jambonz/sbc-registrar.git
git clone https://github.com/jambonz/sbc-call-router.git 
git clone https://github.com/jambonz/sbc-options-handler.git 
git clone https://github.com/jambonz/jambonz-api-server.git 
git clone https://github.com/jambonz/jambonz-webapp.git

Next, edit this file: ~/apps/jambonz-webapp/.env. Change this:

REACT_APP_API_BASE_URL=http://[ip]:[port]/v1

to this:

REACT_APP_API_BASE_URL=http://190.144.12.220:3000/v1

Note: again, substitute the public IP of your own SBC in the above

Next, from the ~/apps/ folder execute the following

cd sbc-inbound && sudo npm install --unsafe-perm
cd ../sbc-outbound && sudo npm install --unsafe-perm
cd ../sbc-registrar && sudo npm install --unsafe-perm
cd ../sbc-call-router && sudo npm install --unsafe-perm
cd ../sbc-options-handler && sudo npm install --unsafe-perm
cd ../jambonz-api-server && sudo npm install --unsafe-perm
cd ../jambonz-webapp && sudo npm install --unsafe-perm && npm run build

sudo -u admin bash -c "pm2 install pm2-logrotate"
sudo -u admin bash -c "pm2 set pm2-logrotate:max_size 1G"
sudo -u admin bash -c "pm2 set pm2-logrotate:retain 5"
sudo -u admin bash -c "pm2 set pm2-logrotate:compress true"

sudo chown -R admin:admin  /home/admin/apps

Next, copy this file below into ~/apps/ecosystem.config.js.

Note: Make sure to edit the file to have the correct connectivity information for your mysql and redis servers, and also if you have installed under a user other than 'admin' make sure to update the file paths accordingly (e.g. in the properties below such as 'cwd', 'out_file' etc).

module.exports = {
	apps: [
    {
      name: 'jambonz-api-server',
      cwd: '/home/admin/apps/jambonz-api-server',
      script: 'app.js',
      out_file: '/home/admin/.pm2/logs/jambonz-api-server.log',
      err_file: '/home/admin/.pm2/logs/jambonz-api-server.log',
      combine_logs: true,
      instance_var: 'INSTANCE_ID',
      exec_mode: 'fork',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production',
        JAMBONES_MYSQL_HOST: '<your-mysql-host>',
        JAMBONES_MYSQL_USER: 'admin',
        JAMBONES_MYSQL_PASSWORD: 'JambonzR0ck$',
        JAMBONES_MYSQL_DATABASE: 'jambones',
        JAMBONES_MYSQL_CONNECTION_LIMIT: 10,
        JAMBONES_REDIS_HOST: '<your-redis-host>',
        JAMBONES_REDIS_PORT: 6379,
        JAMBONES_LOGLEVEL: 'info',
        JAMBONE_API_VERSION: 'v1',
        JAMBONES_TIME_SERIES_HOST: '<your-influxdb-host>',
        ENABLE_METRICS: 1,
        STATS_HOST: '127.0.0.1',
        STATS_PORT: 8125,
        STATS_PROTOCOL: 'tcp',
        STATS_TELEGRAF: 1,
        HTTP_PORT:  3000,
        HOMER_BASE_URL: 'http://127.0.0.1:9080',
        HOMER_USERNAME: 'admin',
        HOMER_PASSWORD: 'sipcapture'      
      }
    },
    {
      name: 'sbc-call-router',
      cwd: '/home/admin/apps/sbc-call-router',
      script: 'app.js',
      instance_var: 'INSTANCE_ID',
      out_file: '/home/admin/.pm2/logs/jambonz-sbc-call-router.log',
      err_file: '/home/admin/.pm2/logs/jambonz-sbc-call-router.log',
      exec_mode: 'fork',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production',
        HTTP_PORT: 4000,
        JAMBONES_INBOUND_ROUTE: '127.0.0.1:4002',
        JAMBONES_OUTBOUND_ROUTE: '127.0.0.1:4003',
        JAMBONZ_TAGGED_INBOUND: 1,
        ENABLE_METRICS: 1,
        STATS_HOST: '127.0.0.1',
        STATS_PORT: 8125,
        STATS_PROTOCOL: 'tcp',
        STATS_TELEGRAF: 1,
        JAMBONES_NETWORK_CIDR: '192.168.0.0/16'
      }
    },
		{
      name: 'sbc-registrar',
      cwd: '/home/admin/apps/sbc-registrar',
      script: 'app.js',
      instance_var: 'INSTANCE_ID',
      out_file: '/home/admin/.pm2/logs/jambonz-sbc-registrar.log',
      err_file: '/home/admin/.pm2/logs/jambonz-sbc-registrar.log',
      exec_mode: 'fork',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production',
        JAMBONES_LOGLEVEL: 'info',
        DRACHTIO_HOST: '127.0.0.1',
        DRACHTIO_PORT: 9022,
        DRACHTIO_SECRET: 'cymru',
        JAMBONES_MYSQL_HOST: '<your-mysql-host>',
        JAMBONES_MYSQL_USER: 'admin',
        JAMBONES_MYSQL_PASSWORD: 'JambonzR0ck$',
        JAMBONES_MYSQL_DATABASE: 'jambones',
        JAMBONES_MYSQL_CONNECTION_LIMIT: 10,
        JAMBONES_REDIS_HOST: '<your-redis-host>',
        JAMBONES_REDIS_PORT: 6379,
        JAMBONES_TIME_SERIES_HOST: '<your-influxdb-host>',
        ENABLE_METRICS: 1,
        STATS_HOST: '127.0.0.1',
        STATS_PORT: 8125,
        STATS_PROTOCOL: 'tcp',
        STATS_TELEGRAF: 1
      }
    },
    {
      name: 'sbc-outbound',
      cwd: '/home/admin/apps/sbc-outbound',
      script: 'app.js',
      instance_var: 'INSTANCE_ID',
      out_file: '/home/admin/.pm2/logs/jambonz-sbc-outbound.log',
      err_file: '/home/admin/.pm2/logs/jambonz-sbc-outbound.log',
      exec_mode: 'fork',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production',
        JAMBONES_LOGLEVEL: 'info',
        DRACHTIO_HOST: '127.0.0.1',
        DRACHTIO_PORT: 9022,
        DRACHTIO_SECRET: 'cymru',
        JAMBONES_RTPENGINES: '127.0.0.1:22222',
        JAMBONES_MYSQL_HOST: '<your-mysql-host>',
        JAMBONES_MYSQL_USER: 'admin',
        JAMBONES_MYSQL_PASSWORD: 'JambonzR0ck$',
        JAMBONES_MYSQL_DATABASE: 'jambones',
        JAMBONES_MYSQL_CONNECTION_LIMIT: 10,
        JAMBONES_REDIS_HOST: '<your-redis-host>',
        JAMBONES_REDIS_PORT: 6379,
        JAMBONES_NETWORK_CIDR: '192.168.0.0/16',
        JAMBONES_TIME_SERIES_HOST: '<your-influxdb-host>',
        ENABLE_METRICS: 1,
        STATS_HOST: '127.0.0.1',
        STATS_PORT: 8125,
        STATS_PROTOCOL: 'tcp',
        STATS_TELEGRAF: 1
      }
    },
    {
      name: 'sbc-inbound',
      cwd: '/home/admin/apps/sbc-inbound',
      script: 'app.js',
      instance_var: 'INSTANCE_ID',
      out_file: '/home/admin/.pm2/logs/jambonz-sbc-inbound.log',
      err_file: '/home/admin/.pm2/logs/jambonz-sbc-inbound.log',
      exec_mode: 'fork',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production',
        JAMBONES_NETWORK_CIDR: '192.168.0.0/16',
        JAMBONES_LOGLEVEL: 'info',
        DRACHTIO_HOST: '127.0.0.1',
        DRACHTIO_PORT: 9022,
        DRACHTIO_SECRET: 'cymru',
        JAMBONES_RTPENGINES: '127.0.0.1:22222',
        JAMBONES_MYSQL_HOST: '<your-mysql-host>',
        JAMBONES_MYSQL_USER: 'admin',
        JAMBONES_MYSQL_PASSWORD: 'JambonzR0ck$',
        JAMBONES_MYSQL_DATABASE: 'jambones',
        JAMBONES_MYSQL_CONNECTION_LIMIT: 10,
        JAMBONES_REDIS_HOST: '<your-redis-host>',
        JAMBONES_REDIS_PORT: 6379,
        JAMBONES_TIME_SERIES_HOST: '<your-influxdb-host>',
        ENABLE_METRICS: 1,
        STATS_HOST: '127.0.0.1',
        STATS_PORT: 8125,
        STATS_PROTOCOL: 'tcp',
        STATS_TELEGRAF: 1
			}
		},
    {
      name: 'sbc-options-handler',
      cwd: '/home/admin/apps/sbc-options-handler',
      script: 'app.js',
      instance_var: 'INSTANCE_ID',
      out_file: '/home/admin/.pm2/logs/jambonz-sbc-options-handler.log',
      err_file: '/home/admin/.pm2/logs/jambonz-sbc-options-handler.log',
      exec_mode: 'fork',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production',
        JAMBONES_NETWORK_CIDR: '192.168.0.0/16',
        JAMBONES_LOGLEVEL: 'info',
        DRACHTIO_HOST: '127.0.0.1',
        DRACHTIO_PORT: 9022,
        DRACHTIO_SECRET: 'cymru',
        JAMBONES_REDIS_HOST: '<your-redis-host>',
        JAMBONES_REDIS_PORT: 6379,
        ENABLE_METRICS: 1,
        STATS_HOST: '127.0.0.1',
        STATS_PORT: 8125,
        STATS_PROTOCOL: 'tcp',
        STATS_TELEGRAF: 1
      }
    },
		{
      name: 'jambonz-webapp',
      script: 'npm',
      cwd: '/home/admin/apps/jambonz-webapp',
      args: 'run serve'
		}
	]
};

Open the following ports on the server

SBC traffic allowed in

ports transport description
3000 tcp REST API
3001 tcp provisioning GUI
5060 udp sip over udp
5060 tcp sip over tcp
5061 tcp sip over tls
4433 tcp sip over wss
40000-60000 udp rtp

Next, ssh into the server and run the following command:

JAMBONES_MYSQL_HOST=<your-mysql-host> \
JAMBONES_MYSQL_USER=admin \
JAMBONES_MYSQL_PASSWORD=JambonzR0ck$ \
JAMBONES_MYSQL_DATABASE=jambones \
/home/admin/apps/jambonz-api-server/db/reset_admin_password.js"

This is a security measure to randomize some of the initial seed data in the mysql database.

Next, start the applications and configure them to restart on boot:

sudo -u admin bash -c "pm2 start /home/admin/apps/ecosystem.config.js"
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u admin --hp /home/admin
sudo -u admin bash -c "pm2 save"
sudo systemctl enable pm2-admin.service

Check to be sure they are running:

pm2 list

You should see output similar to this:

admin@ip-172-31-32-10:~$ pm2 list
┌─────┬───────────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name                  │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼───────────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 7   │ jambonz-api-server    │ default     │ 1.1.7   │ fork    │ 4494     │ 4s     │ 0    │ online    │ 30.4%    │ 104.7mb  │ admin    │ disabled │
│ 12  │ jambonz-webapp        │ default     │ N/A     │ fork    │ 4540     │ 4s     │ 0    │ online    │ 7.9%     │ 49.9mb   │ admin    │ disabled │
│ 8   │ sbc-call-router       │ default     │ 0.0.1   │ fork    │ 4500     │ 4s     │ 0    │ online    │ 3.7%     │ 43.8mb   │ admin    │ disabled │
│ 11  │ sbc-inbound           │ default     │ 0.3.5   │ fork    │ 4538     │ 4s     │ 0    │ online    │ 24.1%    │ 100.3mb  │ admin    │ disabled │
│ 10  │ sbc-outbound          │ default     │ 0.4.2   │ fork    │ 4515     │ 4s     │ 0    │ online    │ 13.9%    │ 83.3mb   │ admin    │ disabled │
│ 9   │ sbc-registrar         │ default     │ 0.1.7   │ fork    │ 4512     │ 4s     │ 0    │ online    │ 13.6%    │ 83.0mb   │ admin    │ disabled │
└─────┴───────────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Module
┌────┬───────────────────────────────────────┬────────────────────┬───────┬──────────┬──────┬──────────┬──────────┬──────────┐
│ id │ module                                │ version            │ pid   │ status   │ ↺    │ cpu      │ mem      │ user     │
├────┼───────────────────────────────────────┼────────────────────┼───────┼──────────┼──────┼──────────┼──────────┼──────────┤
│ 0  │ pm2-logrotate                         │ 2.7.0              │ 28461 │ online   │ 1    │ 0.3%     │ 80.7mb   │ admin    │
└────┴───────────────────────────────────────┴────────────────────┴───────┴──────────┴──────┴──────────┴──────────┴──────────┘

Finally, in your browser, navigate to http://<sbc-public-ip>:3001.

You should get a login page to the SBC. Log in with admin/admin. You will be asked to change the password and then be guided through an initial 3-step setup process to configuring your account, application, and SIP trunking provider.

F. Configure Feature Server

Open the following ports on the server

Feature server traffic allowed in

Note: all of the ports below need to be open for traffic sent from a source IP that is within the local network. Traffic from the internet to these ports can be blocked.

ports transport description
3000 tcp REST API
5060 udp sip
5060 tcp sip
5080 udp freeswitch sip
5080 tcp freeswitch sip
25000 - 40000 udp rtp

In the file /usr/local/freeswitch/conf/autoload_configs/switch.conf.xml set the rtp port range to be 25000 through 39000 by editing the 'rtp-start-port' and 'rtp-end-port' as follows:

    <!-- RTP port range -->
<param name="rtp-start-port" value="25000"/>
<param name="rtp-end-port" value="39000"/>

In the file /usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml replace the contents with:

<configuration name="event_socket.conf" description="Socket Client">
  <settings>
    <param name="nat-map" value="false"/>
    <param name="listen-ip" value="0.0.0.0"/>
    <param name="listen-port" value="8021"/>
    <param name="password" value="JambonzR0ck$"/>
     <param name="apply-inbound-acl" value="socket_acl"/>
  </settings>
</configuration>

Note: Feel free to choose a different password if you like.

In the file /etc/systemd/system/freeswitch.service make sure the following Environment variables are set:

[Service]
; service
Type=forking
PIDFile=/usr/local/freeswitch/run/freeswitch.pid
EnvironmentFile=-/etc/default/freeswitch
Environment="MOD_AUDIO_FORK_SUBPROTOCOL_NAME=audio.jambonz.org"
Environment="MOD_AUDIO_FORK_SERVICE_THREADS=1"
Environment="MOD_AUDIO_FORK_BUFFER_SECS=3"
Environment="LD_LIBRARY_PATH=/usr/local/lib"
Environment="GOOGLE_APPLICATION_CREDENTIALS=/home/admin/credentials/gcp.json"
ExecStart=/usr/local/freeswitch/bin/freeswitch -nc -nonat
Install drachtio apps

Choose a user to install the drachtio applications under -- the instructions below assume the admin user; if you use a different user than edit the instructions accordingly (note: the user must have sudo priviledges).

Execute the following commands from the home directory of the install user:

mkdir apps credentials
cd apps
git clone https://github.com/jambonz/jambonz-feature-server.git
git clone https://github.com/jambonz/fsw-clear-old-calls.git
cd jambonz-feature-server && sudo npm install --unsafe-perm
cd ../fsw-clear-old-calls && npm install && sudo npm install -g .
echo "0 *	* * *	root    fsw-clear-old-calls --password JambonzR0ck$ >> /var/log/fsw-clear-old-calls.log 2>&1" | sudo tee -a /etc/crontab
sudo -u admin bash -c "pm2 install pm2-logrotate"
sudo -u admin bash -c "pm2 set pm2-logrotate:max_size 1G"
sudo -u admin bash -c "pm2 set pm2-logrotate:retain 5"
sudo -u admin bash -c "pm2 set pm2-logrotate:compress true"
sudo chown -R admin:admin  /home/admin/apps

Note: if you chose a different Freeswitch password, make sure to adjust the crontab entry above to use that password.

Next, copy your google service credentials json file into /home/admin/credentials/gcp.json. Note that this is referenced from the Environment variable that you set in the freeswitch systemd service file.

Next, copy this file below into ~/apps/ecosystem.config.js.

Note: Make sure to edit the file below to have the correct information for:

  • your mysql and redis server hosts,
  • your AWS access key, secret access key, and region
  • your mysql and freeswitch passwords, if different than below
  • the IP address of the SBC on the internal network,
  • the network CIDR of the internal network, and
  • if you have installed under a user other than 'admin' make sure to update the file paths accordingly (e.g. in the properties below such as 'cwd', 'out_file' etc).
module.exports = {
  apps : [
  {
    name: 'jambonz-feature-server',
    cwd: '/home/admin/apps/jambonz-feature-server',
    script: 'app.js',
    instance_var: 'INSTANCE_ID',
    out_file: '/home/admin/.pm2/logs/jambonz-feature-server.log',
    err_file: '/home/admin/.pm2/logs/jambonz-feature-server.log',
    exec_mode: 'fork',
    instances: 1,
    autorestart: true,
    watch: false,
    max_memory_restart: '1G',
    env: {
      NODE_ENV: 'production',
      ENABLE_METRICS: 1,
      STATS_HOST: '127.0.0.1',
      STATS_PORT: 8125,
      STATS_PROTOCOL: 'tcp',
      STATS_TELEGRAF: 1,
      JAMBONES_NETWORK_CIDR: '192.168.0.0/16',
      JAMBONES_API_BASE_URL: 'http://<sbc-public-ip>:3000',
      JAMBONES_MYSQL_HOST: '<your-mysql-host>',
      JAMBONES_MYSQL_USER: 'admin',
      JAMBONES_MYSQL_PASSWORD: 'JambonzR0ck$',
      JAMBONES_MYSQL_DATABASE: 'jambones',
      JAMBONES_MYSQL_CONNECTION_LIMIT: 10,
      JAMBONES_REDIS_HOST: '<your-redis-host>',
      JAMBONES_REDIS_PORT: 6379,
      JAMBONES_LOGLEVEL: 'debug',
      JAMBONES_TIME_SERIES_HOST: '<your-influxdb-host>',
      HTTP_PORT: 3000,
      DRACHTIO_HOST: '127.0.0.1',
      DRACHTIO_PORT: 9022,
      DRACHTIO_SECRET: 'cymru',
      JAMBONES_SBCS: '<your-sbc-address>',
      JAMBONES_FREESWITCH: '127.0.0.1:8021:JambonzR0ck$'
    }
  }]
};

Next, start the applications and configure them to restart on boot:

sudo -u admin bash -c "pm2 start /home/admin/apps/ecosystem.config.js"
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u admin --hp /home/admin
sudo -u admin bash -c "pm2 save"
sudo systemctl enable pm2-admin.service

Check to be sure they are running:

pm2 list

You should see output similar to this:

admin@ip-172-31-33-250:~$ pm2 list
┌─────┬───────────────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name                      │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼───────────────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 1   │ jambonz-feature-server    │ default     │ 0.2.3   │ fork    │ 22438    │ 47h    │ 6    │ online    │ 0.2%     │ 85.4mb   │ admin    │ disabled │
└─────┴───────────────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Module
┌────┬───────────────────────────────────────┬────────────────────┬───────┬──────────┬──────┬──────────┬──────────┬──────────┐
│ id │ module                                │ version            │ pid   │ status   │ ↺    │ cpu      │ mem      │ user     │
├────┼───────────────────────────────────────┼────────────────────┼───────┼──────────┼──────┼──────────┼──────────┼──────────┤
│ 0  │ pm2-logrotate                         │ 2.7.0              │ 1015  │ online   │ 0    │ 0.1%     │ 66.4mb   │ admin    │
└────┴───────────────────────────────────────┴────────────────────┴───────┴──────────┴──────┴──────────┴──────────┴──────────┘

Finally, restart the drachtio and freeswitch services:

sudo systemctl daemon-reload
sudo systemctl restart freeswitch
sudo systemctl restart drachtio

For good measure, restart the drachtio apps as well

pm2 restart /home/admin/apps/ecosystem.config.js

Now you should have a running system. Verify the drachtio server and freeswitch are running

sudo systemctl status drachtio
sudo systemctl status freeswitch

Verify the apps are running and are not logging any errors:

pm2 list
pm2 log

Finally, tail the /var/log/drachtio/drachtio.log file and verify that sip OPTIONS requests are being sent to the SBC and are receiving a 200 OK response.

At this point, your system is ready for testing.