FusionPBX 5 Freeswitch 1.10 Debian 11 PostgreSQL Nginx Install Guide
Fusionpbx is a full featured mult-tenant GUI for Freeswitch. This guide covers the installation of Fusionpbx and Freeswitch® with PostgreSQL and NGINX on Debian 11.
Tested on:
Debian 11 (Bullseye) x64 minimal install
Freeswitch 1.10
FusionPBX 5
Nginx 1.1x
PHP 8.1
PostgreSQL 16
Assumptions:
Console text mode (multi-user.target)
Installation done as root user (su
).
Prerequisites
Verify locale is set to C.UTF-8
.
locale
If it is not then set it now.
# Select C.UTF-8 UTF-8
apt update && apt -y install locales && dpkg-reconfigure locales
Log out/in or close/open shell for changes to take effect. This should be done before PostgreSQL is installed.
Install base packages
apt update && apt upgrade -y && apt -y remove apache2
apt -y install wget git nano dbus sudo nginx curl dialog qrencode net-tools lsb-release sqlite3 haveged ghostscript libtiff5-dev libtiff-tools at tftpd ssl-cert gnupg2 software-properties-common
SNMP
apt install -y snmpd echo "rocommunity public" > /etc/snmp/snmpd.conf systemctl restart snmpd
IPtables
If ufw is not installed, you can ignore any resulting error.
apt install -y iptables update-alternatives --set iptables /usr/sbin/iptables-legacy update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy ufw --force disable && ufw --force reset && apt remove -y ufw
wget http://packages.irontec.com/public.key -q -O - | apt-key add - echo "deb http://packages.irontec.com/debian $(lsb_release -sc) main" > \ /etc/apt/sources.list.d/irontec.list apt update && apt -y install sngrep
PostgreSQL
echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -sc)-pgdg main" > \ /etc/apt/sources.list.d/postgresql.list wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - apt update && apt install postgresql-16 postgresql-client-16
PHP
Install Dependencies
# Remove any existing PHP files apt remove -y php* # Install dependencies apt -y install apt-transport-https ca-certificates
Add Repository
# Add php 8.1 repository wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > \ /etc/apt/sources.list.d/php.list
Install
apt update && apt -y install php8.1 php8.1-cli php8.1-dev php8.1-fpm php8.1-pgsql php8.1-sqlite3 php8.1-odbc php8.1-curl php8.1-imap php8.1-xml php8.1-gd php8.1-mbstring php8.1-ldap
update-alternatives --set php /usr/bin/php8.1
Disable Firewall
It is sometimes helpful to disable the firewall during installation. If the packages are not installed or enabled, you can ignore any resulting errors.
systemctl disable firewalld systemctl disable iptables systemctl stop firewalld systemctl stop iptables
Set Timezone
Using tzselect is one way to find the correct timezone.
## FIND YOUR TIMEZONE tzselect
## SET TIMEZONE EXAMPLE timedatectl set-timezone America/Vancouver ## CHECK TIMEZONE timedatectl status
systemctl restart rsyslog
Install
Freeswitch
Freeswitch
Get your signalwire token according to these instructions:
https://freeswitch.org/confluence/display/FREESWITCH/HOWTO+Create+a+SignalWire+Personal+Access+Token
Once you have your signalwire token install freeswitch packages
TOKEN=YOURSIGNALWIRETOKEN apt-get update && apt-get install -y gnupg2 wget lsb-release wget --http-user=signalwire --http-password=$TOKEN -O /usr/share/keyrings/signalwire-freeswitch-repo.gpg https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg echo "machine freeswitch.signalwire.com login signalwire password $TOKEN" > /etc/apt/auth.conf echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list echo "deb-src [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ `lsb_release -sc` main" >> /etc/apt/sources.list.d/freeswitch.list apt update && apt install -y freeswitch-meta-all
Database
Check that localhost connections are always allowed. This is necessary for the backup script.
nano +125 /etc/postgresql/16/main/pg_hba.conf
host all all 127.0.0.1/32 trust
systemctl restart postgresql
Check PostgreSQL locale
sudo -u postgres psql -l
If Encoding is not UTF8
and Collate & Ctype is not C.UTF-8
then set it now.
sudo -u postgres psql update pg_database set encoding = 6, datcollate = 'C.UTF-8', datctype = 'C.UTF-8' where datname = 'template0'; update pg_database set encoding = 6, datcollate = 'C.UTF-8', datctype = 'C.UTF-8' where datname = 'template1';
Create databases and user
cd /tmp # Set the DB password variable. password=fusionpbx
sudo -u postgres psql -c "SET client_encoding = 'UTF8';" sudo -u postgres psql -c "CREATE DATABASE fusionpbx;" sudo -u postgres psql -c "CREATE DATABASE freeswitch;" sudo -u postgres psql -c "CREATE ROLE fusionpbx WITH SUPERUSER LOGIN PASSWORD '$password';" sudo -u postgres psql -c "CREATE ROLE freeswitch WITH SUPERUSER LOGIN PASSWORD '$password';" sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE fusionpbx to fusionpbx;" sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE freeswitch to fusionpbx;" sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE freeswitch to freeswitch;"
Fusionpbx
There may be enhancements and fixes in our repository that are not in the official repository. We also strive to merge updates from the official repository on a regular basis.
mkdir -p /etc/fusionpbx mkdir -p /var/www/fusionpbx mkdir -p /var/cache/fusionpbx git clone -b 5.1 https://github.com/powerpbx/fusionpbx.git /var/www/fusionpbx
Copy Directories
mv /etc/freeswitch /etc/freeswitch.orig mkdir /etc/freeswitch cp -R /var/www/fusionpbx/app/switch/resources/conf/* /etc/freeswitch
Copy music directories to default location
mkdir -p /usr/share/freeswitch/sounds/music/default mv /usr/share/freeswitch/sounds/music/*000/ /usr/share/freeswitch/sounds/music/default/
Php-fpm config
sed 's#post_max_size = .*#post_max_size = 80M#g' -i /etc/php/8.1/fpm/php.ini sed 's#upload_max_filesize = .*#upload_max_filesize = 80M#g' -i /etc/php/8.1/fpm/php.ini sed 's#max_execution_time = .*#max_execution_time = 120#g' -i /etc/php/8.1/fpm/php.ini sed 's#;max_input_vars = .*#max_input_vars = 8000#g' -i /etc/php/8.1/fpm/php.ini systemctl restart php8.1-fpm
Nginx config
mkdir -p /etc/nginx/ssl cd /etc/nginx/sites-available wget https://raw.githubusercontent.com/powerpbx/fusionpbx-install.sh/master/debian/resources/nginx/fusionpbx sed -i /etc/nginx/sites-available/fusionpbx -e 's#unix:.*;#unix:/var/run/php/php8.1-fpm.sock;#g' ln -s /etc/nginx/sites-available/fusionpbx /etc/nginx/sites-enabled/fusionpbx rm /etc/nginx/sites-enabled/default # link to self signed certificate ln -s /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/private/nginx.key ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/certs/nginx.crt # For future use mkdir -p /var/www/letsencrypt/ systemctl restart nginx
Systemd
Create custom Freeswitch unit file
systemctl stop freeswitch rm -r /run/freeswitch nano /etc/systemd/system/freeswitch.service
[Unit] Description=freeswitch After=syslog.target network.target local-fs.target postgresql.service [Service] Type=forking RuntimeDirectory=freeswitch PIDFile=/run/freeswitch/freeswitch.pid Environment="DAEMON_OPTS=-ncwait -nonat" EnvironmentFile=-/etc/default/freeswitch ExecStart=/usr/bin/freeswitch $DAEMON_OPTS TimeoutSec=45s Restart=always User=www-data Group=www-data LimitCORE=infinity LimitNOFILE=100000 LimitNPROC=60000 LimitSTACK=250000 LimitRTPRIO=infinity LimitRTTIME=infinity IOSchedulingClass=realtime IOSchedulingPriority=2 CPUSchedulingPriority=89 UMask=0007 ; Comment this out if using OpenVZ CPUSchedulingPolicy=rr [Install] WantedBy=multi-user.target
Create environment file.
cat >> /etc/default/freeswitch << EOF # Uncommented variables will override variables in unit file # User="" # Group="" # DAEMON_OPTS="" EOF
Set ownership and permissions
Run this on a fresh install and anytime there are any updates or changes or if experiencing problems.
# Set ownership chown -R www-data. /etc/freeswitch /etc/fusionpbx /var/cache/fusionpbx /var/lib/freeswitch \ /var/log/freeswitch /usr/share/freeswitch /var/www/fusionpbx /var/run/freeswitch ## Set directory permissions to 755 (u=rwx,g=rx,o='rx') find /etc/freeswitch -type d -exec chmod 755 {} \; find /etc/fusionpbx -type d -exec chmod 755 {} \; find /var/cache/fusionpbx -type d -exec chmod 755 {} \; find /var/lib/freeswitch -type d -exec chmod 755 {} \; find /var/log/freeswitch -type d -exec chmod 755 {} \; find /usr/share/freeswitch -type d -exec chmod 755 {} \; find /var/www -type d -exec chmod 755 {} \; ## Set file permissions to 664 (u=rw,g=rw,o=r) find /etc/freeswitch -type f -exec chmod 664 {} \; find /etc/fusionpbx -type f -exec chmod 664 {} \; find /var/lib/freeswitch -type f -exec chmod 664 {} \; find /var/log/freeswitch -type f -exec chmod 664 {} \; find /usr/share/freeswitch -type f -exec chmod 664 {} \; find /var/www -type f -exec chmod 664 {} \; ## Set misc permissions to 755 (u=rwx,g=rx,o='rx') chmod -R 755 /var/www/fusionpbx/secure ## These two files do not yet exist on a fresh install chmod 755 /etc/cron.daily/fusionpbx-backup chmod 755 /etc/cron.daily/fusionpbx-maintenance
Enable services
systemctl daemon-reload systemctl enable freeswitch systemctl restart freeswitch
Browse to the public IP address of the server
http://xx.xx.xx.xx
to complete the install using the following:
Username: superadmin
(or whatever you want)
Password: someSuperAdminPassword
Database Name: fusionpbx
Database Username: fusionpbx
Database Password: fusionpbx
(The database user password created earlier)
The install may take a minute or two on slower servers.
Post install tasks are optional but recommended.
Post Install
Enable freeswitch database connection
This optional configuration changes FreeSWITCH's internal data storage from SQLite to PostgreSQL. SQLite is suitable for testing, troubleshooting, and moderate usage but may not be optimal for busy servers requiring high performance. Additionally, SQLite has a tendency to become corrupted if the server experiences an unclean shutdown.
nano +185 /etc/freeswitch/autoload_configs/switch.conf.xml
<param name="core-db-dsn" value="pgsql://hostaddr=127.0.0.1 dbname=freeswitch user=fusionpbx password='fusionpbx'" />
systemctl restart freeswitch
Firewalld
apt -y install firewalld systemctl enable firewalld sed 's#FirewallBackend=.*#FirewallBackend=iptables#g' -i /etc/firewalld/firewalld.conf systemctl start firewalld firewall-cmd --permanent --zone=public --add-service={http,https} firewall-cmd --permanent --zone=public --add-port={5060,5061,5080,5081}/tcp firewall-cmd --permanent --zone=public --add-port={5060,5061,5080,5081}/udp firewall-cmd --permanent --zone=public --add-port=16384-32768/udp firewall-cmd --reload firewall-cmd --list-all
Daily Backup and Housekeeping
Backup script
nano /etc/cron.daily/fusionpbx-backup
#!/bin/sh db_host=127.0.0.1 db_port=5432 now=$(date +%Y-%m-%d) mkdir -p /var/backups/fusionpbx/postgresql echo "Backup Started" # Delete postgres backups if older than 4 days find /var/backups/fusionpbx/postgresql/fusionpbx_pgsql* -mtime +4 -exec rm -f {} \; # Delete the main backup if older than 4 days find /var/backups/fusionpbx/*.tgz -mtime +4 -exec rm -f {} \; # Create database backup pg_dump --verbose -Fc --host=${db_host} --port=${db_port} -U fusionpbx fusionpbx --schema=public -f /var/backups/fusionpbx/postgresql/fusionpbx_pgsql_${now}.sql # Combine and compress to create the main backup tar --exclude='/var/lib/freeswitch/recordings/*/archive' \ -zvcf /var/backups/fusionpbx/backup_${now}.tgz /var/backups/fusionpbx/postgresql/fusionpbx_pgsql_${now}.sql \ /var/www/fusionpbx \ /usr/share/freeswitch/scripts \ /usr/share/freeswitch/sounds/music \ /var/lib/freeswitch/storage \ /var/lib/freeswitch/recordings \ /etc/fusionpbx \ /etc/freeswitch echo "Backup Completed"
chmod 755 /etc/cron.daily/fusionpbx-backup
Housekeeping script
nano /etc/cron.daily/fusionpbx-maintenance
#!/bin/sh echo "Maintenance Started" # Delete freeswitch logs older than 7 days find /var/log/freeswitch/freeswitch.log.* -mtime +7 -exec rm {} \; #delete php sessions older than 7 days find /var/lib/php/sessions/* -name 'sess_*' -mtime +7 -exec rm {} \; ## Uncomment to delete call recordings older than 90 days #find /var/lib/freeswitch/recordings/*/archive/* -name '*.wav' -mtime +90 -exec rm {} \; #find /var/lib/freeswitch/recordings/*/archive/* -name '*.mp3' -mtime +90 -exec rm {} \; ## Uncomment to delete faxes older than 90 days #find /var/lib/freeswitch/storage/fax/* -name '*.tif' -mtime +90 -exec rm {} \; #find /var/lib/freeswitch/storage/fax/* -name '*.pdf' -mtime +90 -exec rm {} \; ## Uncomment to delete faxe_queue older than 30 days psql --host=127.0.0.1 --username=fusionpbx -c "delete from v_fax_queue where fax_status = 'sent' and fax_date < NOW() - INTERVAL '30 days'" ## Uncomment to delete voicemails older than 90 days #find /var/lib/freeswitch/storage/voicemail/default/* -name 'msg_*.wav' -mtime +90 -exec rm {} \; #find /var/lib/freeswitch/storage/voicemail/default/* -name 'msg_*.mp3' -mtime +90 -exec rm {} \; #psql --host=127.0.0.1 --username=fusionpbx -c "delete from v_voicemail_messages WHERE to_timestamp(created_epoch) < NOW() - INTERVAL '90 days'" ## Uncomment to delete call detail records older than 90 days #psql --host=127.0.0.1 --username=fusionpbx -c "delete from v_xml_cdr WHERE start_stamp < NOW() - INTERVAL '90 days'" ## Uncomment to delete database_transactions older than 90 days psql --host=127.0.0.1 --username=fusionpbx -c "delete from v_database_transactions where transaction_date < NOW() - INTERVAL '90 days'" ## Uncomment to delete email_queue older than 30 days psql --host=127.0.0.1 --username=fusionpbx -c "delete from v_email_queue where email_status = 'sent' and email_date < NOW() - INTERVAL '30 days'" echo "Maintenance Completed"
chmod 755 /etc/cron.daily/fusionpbx-maintenance
TFTP
If you plan to use hardware SIP phones you may want to enable TFTP.
Create tftp config
apt -y install xinetd
cat >> /etc/xinetd.d/tftp << EOF service tftp { protocol = udp port = 69 socket_type = dgram wait = yes user = nobody server = /usr/sbin/in.tftpd server_args = /tftpboot disable = no } EOF
Make the directory and restart the daemon to start tftp.
mkdir /tftpboot chmod 777 /tftpboot systemctl restart xinetd
firewall-cmd --permanent --zone=public --add-port=69/udp firewall-cmd --reload
Go to GUI Advanced > Default Settings > Provision
. About 20 rows down set enabled = True
and reload
Add a new subcategory in Provision category by pressing the +
icon and fill in as follows:
Category = provision Subcategory = path type = text Value = /tftpboot Enabled = True
Fail2ban
apt -y install fail2ban URL=https://raw.githubusercontent.com/fusionpbx/fusionpbx-install.sh/master/debian/resources/fail2ban DIR=/etc/fail2ban/filter.d wget $URL/freeswitch.conf -O $DIR/freeswitch.conf wget $URL/freeswitch-acl.conf -O $DIR/freeswitch-acl.conf wget $URL/sip-auth-failure.conf -O $DIR/sip-auth-failure.conf wget $URL/sip-auth-challenge.conf -O $DIR/sip-auth-challenge.conf wget $URL/auth-challenge-ip.conf -O $DIR/auth-challenge-ip.conf wget $URL/freeswitch-ip.conf -O $DIR/freeswitch-ip.conf wget $URL/fusionpbx.conf -O $DIR/fusionpbx.conf wget $URL/fusionpbx-mac.conf -O $DIR/fusionpbx-mac.conf wget $URL/fusionpbx-404.conf -O $DIR/fusionpbx-404.conf wget $URL/nginx-404.conf -O $DIR/nginx-404.conf wget $URL/nginx-dos.conf -O $DIR/nginx-dos.conf wget $URL/jail.local -O /etc/fail2ban/jail.local systemctl restart fail2ban
If connecting from external LANs, it is a good idea to add their public IP addresses in fail2ban to prevent accidental banning of the entire LAN.
nano /etc/fail2ban/jail.conf
# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban # will not ban a host which matches an address in this list. Several addresses # can be defined using space (and/or comma) separator. [DEFAULT] ignoreip = 127.0.0.1/8 ::1
systemctl restart fail2ban
Email Queue
cp /var/www/fusionpbx/app/email_queue/resources/service/debian.service /etc/systemd/system/email_queue.service systemctl daemon-reload systemctl enable email_queue systemctl start email_queue
Event Guard
cp /var/www/fusionpbx/app/event_guard/resources/service/debian.service /etc/systemd/system/event_guard.service systemctl daemon-reload systemctl enable event_guard systemctl start event_guard
Troubleshooting the Dialplan
To view the dyamically generated xml files.
nano /usr/share/freeswitch/scripts/resources/functions/config.lua
## Change debug options from false to true to see lua generated output in fs_cli debug.params = true; debug.sql = true; debug.xml_request = true; debug.xml_string = true; debug.cache = true;