FusionPBX transforms FreeSWITCH — the world's most powerful open source telephony engine — into a fully web-managed PBX with extensions, IVR menus, ring groups, call queues, voicemail, and multi-tenant domains. When FusionPBX is healthy, your phones ring and your SIP trunks carry calls. When it isn't, the silence is immediate and business-critical. Vigilmon gives you continuous monitoring across every layer of the FusionPBX stack: the web admin interface, the FreeSWITCH engine, SIP trunk registrations, active call load, and the PostgreSQL database that ties it all together.
What You'll Set Up
- HTTP uptime monitor for the FusionPBX web admin interface
- TCP monitor for FreeSWITCH Event Socket Layer (ESL) connectivity
- SIP registration health check via a lightweight probe script
- Active call count alert using the FreeSWITCH ESL API
- PostgreSQL connectivity and query latency monitor
- Voicemail disk space monitor
- CDR write success heartbeat
- Cron heartbeat for the FusionPBX version currency check
Prerequisites
- FusionPBX installed with FreeSWITCH on a Linux server (Debian/Ubuntu recommended)
- PostgreSQL as the FusionPBX configuration database
- A free Vigilmon account
- SSH access to the FusionPBX server
Step 1: Monitor the FusionPBX Web Admin Interface
FusionPBX's web UI (served by Apache or Nginx + PHP-FPM) is the control plane for your entire PBX. If it goes down, no one can add extensions, change dialplans, or manage call routing.
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter your FusionPBX URL:
https://pbx.yourdomain.com(or the server's IP if you haven't set up a domain). - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Enable Monitor SSL certificate and set the alert threshold to
21 days. - Click Save.
FusionPBX's login page returning a 200 confirms the web server, PHP-FPM, and the PHP application layer are all alive. If the page returns a PHP error page or 500, Vigilmon will alert immediately.
Step 2: Monitor FreeSWITCH via the Event Socket Layer (ESL)
FreeSWITCH exposes an Event Socket on TCP port 8021 by default. FusionPBX uses ESL to send commands like reloadxml and sofia status. If ESL is unreachable, FusionPBX loses control of the telephony engine — but the web UI may still appear healthy.
Add a TCP port monitor:
- Click Add Monitor → TCP Port.
- Enter the FreeSWITCH server IP (often the same host as FusionPBX).
- Set Port to
8021. - Set Check interval to
1 minute. - Click Save.
A successful TCP connection to port 8021 confirms FreeSWITCH is running and its ESL listener is active. Combine this with the process-level check below for complete coverage.
Step 3: SIP Trunk Registration Health via a Probe Script
FreeSWITCH's mod_sofia manages your SIP profiles and gateway registrations (trunk connections to VoIP carriers). A failed trunk registration means outbound calls fail silently.
Create a lightweight probe script that queries FreeSWITCH and pings Vigilmon:
#!/bin/bash
# /usr/local/bin/check-sip-gateways.sh
# Run via cron every 5 minutes
FS_CLI="/usr/bin/fs_cli"
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/YOUR_HEARTBEAT_ID"
# Get sofia gateway status
GATEWAY_STATUS=$($FS_CLI -x "sofia status gateway" 2>/dev/null)
# Check for any gateway in FAILED state
if echo "$GATEWAY_STATUS" | grep -q "FAILED"; then
echo "SIP gateway failure detected at $(date)" >> /var/log/fusionpbx-monitor.log
# Do NOT ping heartbeat — Vigilmon will alert on missing ping
exit 1
fi
# All gateways healthy — ping heartbeat
curl -s "$VIGILMON_HEARTBEAT" > /dev/null
In Vigilmon:
- Click Add Monitor → Cron Heartbeat.
- Set the expected ping interval to
6 minutes(5-minute cron + 1 minute grace). - Copy the heartbeat URL and paste it into the script above.
- Install the script and add the cron entry:
chmod +x /usr/local/bin/check-sip-gateways.sh
echo "*/5 * * * * root /usr/local/bin/check-sip-gateways.sh" > /etc/cron.d/fusionpbx-sip-check
If a gateway enters FAILED state, the heartbeat stops pinging and Vigilmon alerts within 6 minutes.
Step 4: Active Call Count Alert
Excessive concurrent calls can overload your FreeSWITCH server — especially on shared-core VPS instances. Monitor the active channel count and alert when it exceeds your capacity.
Create a script that checks call count and posts a custom metric:
#!/bin/bash
# /usr/local/bin/check-active-calls.sh
CALL_LIMIT=100 # Set to your licensed or capacity limit
FS_CLI="/usr/bin/fs_cli"
ACTIVE_CALLS=$($FS_CLI -x "show channels count" 2>/dev/null | grep -oP '^\d+')
ACTIVE_CALLS=${ACTIVE_CALLS:-0}
if [ "$ACTIVE_CALLS" -gt "$CALL_LIMIT" ]; then
echo "Active calls ($ACTIVE_CALLS) exceeds limit ($CALL_LIMIT)" >> /var/log/fusionpbx-monitor.log
fi
# Ping a separate heartbeat only when calls are under capacity
if [ "$ACTIVE_CALLS" -le "$CALL_LIMIT" ]; then
curl -s "https://vigilmon.online/heartbeat/YOUR_CALL_CAPACITY_HEARTBEAT_ID" > /dev/null
fi
Add to cron to run every minute:
echo "* * * * * root /usr/local/bin/check-active-calls.sh" > /etc/cron.d/fusionpbx-calls
Set the Vigilmon heartbeat interval to 2 minutes. If the call count exceeds your limit, the heartbeat stops and you receive an alert.
Step 5: Monitor the FusionPBX PostgreSQL Database
FusionPBX stores all PBX configuration — extensions, dialplans, ring groups, CDR data, and user accounts — in PostgreSQL. FreeSWITCH reads this configuration via ODBC. A PostgreSQL failure means no configuration changes take effect and CDR logging stops.
Add a TCP monitor for the PostgreSQL port:
- Click Add Monitor → TCP Port.
- Enter the database server IP (often
127.0.0.1on the same host). - Set Port to
5432. - Set Check interval to
1 minute. - Click Save.
For a deeper query-latency check, create a probe script:
#!/bin/bash
# /usr/local/bin/check-fusionpbx-db.sh
PGPASSWORD="your_db_password"
DB_USER="fusionpbx"
DB_NAME="fusionpbx"
MAX_LATENCY_MS=500
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/YOUR_DB_HEARTBEAT_ID"
START=$(date +%s%3N)
RESULT=$(psql -U "$DB_USER" -d "$DB_NAME" -c "SELECT count(*) FROM v_extensions;" -t -q 2>/dev/null)
END=$(date +%s%3N)
LATENCY=$((END - START))
if [ -z "$RESULT" ] || [ "$LATENCY" -gt "$MAX_LATENCY_MS" ]; then
echo "DB check failed: latency=${LATENCY}ms result='$RESULT'" >> /var/log/fusionpbx-monitor.log
exit 1
fi
curl -s "$VIGILMON_HEARTBEAT" > /dev/null
echo "* * * * * root /usr/local/bin/check-fusionpbx-db.sh" > /etc/cron.d/fusionpbx-db-check
Step 6: Voicemail Storage Disk Space
FusionPBX stores voicemail audio files on disk at /var/lib/freeswitch/storage/voicemail/. A full disk silently stops voicemail recording.
Create a disk space probe:
#!/bin/bash
# /usr/local/bin/check-voicemail-disk.sh
MOUNT_POINT="/var/lib/freeswitch/storage"
ALERT_THRESHOLD=80
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/YOUR_DISK_HEARTBEAT_ID"
USAGE=$(df "$MOUNT_POINT" | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$USAGE" -gt "$ALERT_THRESHOLD" ]; then
echo "Voicemail disk at ${USAGE}% — exceeds ${ALERT_THRESHOLD}% threshold" >> /var/log/fusionpbx-monitor.log
exit 1
fi
curl -s "$VIGILMON_HEARTBEAT" > /dev/null
echo "*/10 * * * * root /usr/local/bin/check-voicemail-disk.sh" > /etc/cron.d/fusionpbx-disk
Set the Vigilmon heartbeat interval to 15 minutes. You'll be alerted before disk fills completely.
Step 7: CDR Write Success Heartbeat
Call Detail Records (CDRs) are essential for billing and compliance. FusionPBX writes CDRs to PostgreSQL via mod_cdr_pg_csv. If CDR inserts are failing, billing data is silently lost.
Add a CDR write verification check:
#!/bin/bash
# /usr/local/bin/check-cdr-writes.sh
# Checks that new CDR records were inserted in the last 10 minutes
# (only meaningful during business hours with active calls)
PGPASSWORD="your_db_password"
DB_USER="fusionpbx"
DB_NAME="fusionpbx"
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/YOUR_CDR_HEARTBEAT_ID"
RECENT_CDRS=$(psql -U "$DB_USER" -d "$DB_NAME" \
-c "SELECT count(*) FROM v_xml_cdr WHERE start_stamp > NOW() - INTERVAL '10 minutes';" \
-t -q 2>/dev/null | tr -d ' ')
# If there were active calls but no CDRs, something is wrong
ACTIVE_CALLS=$(/usr/bin/fs_cli -x "show channels count" 2>/dev/null | grep -oP '^\d+' || echo "0")
if [ "${ACTIVE_CALLS:-0}" -gt 5 ] && [ "${RECENT_CDRS:-0}" -eq 0 ]; then
echo "CDR writes appear stalled: $ACTIVE_CALLS active calls but 0 CDRs in last 10 min" >> /var/log/fusionpbx-monitor.log
exit 1
fi
curl -s "$VIGILMON_HEARTBEAT" > /dev/null
Step 8: Configure Alert Channels
- In Vigilmon, go to Alert Channels and add your preferred destinations (email, Slack, PagerDuty, webhook).
- For the FusionPBX web monitor, set Consecutive failures before alert to
2— PHP-FPM restarts can cause a single probe miss. - For the FreeSWITCH ESL TCP monitor, set Consecutive failures before alert to
1— a lost ESL connection is immediately critical. - Group your FusionPBX monitors under a Status Page in Vigilmon to give your team a single-pane view of PBX health.
For planned maintenance windows (FreeSWITCH upgrades, system patching):
# Suppress Vigilmon alerts during maintenance via API
curl -X POST https://vigilmon.online/api/maintenance \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"monitor_id": "YOUR_MONITOR_ID", "duration_minutes": 30}'
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| HTTP uptime | FusionPBX web UI URL | Web server, PHP-FPM, or app crash |
| TCP port | FreeSWITCH ESL :8021 | FreeSWITCH process down |
| Cron heartbeat | SIP gateway probe | SIP trunk registration failure |
| Cron heartbeat | Active call count script | Call capacity overload |
| TCP port | PostgreSQL :5432 | Database down |
| Cron heartbeat | DB query latency script | Slow or unresponsive database |
| Cron heartbeat | Voicemail disk script | Storage full, voicemail loss |
| Cron heartbeat | CDR write check | Silent billing data loss |
| SSL certificate | FusionPBX HTTPS domain | Expired TLS certificate |
FusionPBX brings enterprise PBX capabilities to self-hosted infrastructure — but each layer (web, telephony engine, SIP signaling, database, storage) is a potential point of failure. With Vigilmon monitoring every layer, a crashed FreeSWITCH process or failed SIP trunk registration triggers an alert within minutes rather than when your users start complaining that the phones aren't ringing.