If you report call costs off more than one PBX distribution, you learn quickly that "just read the CDR table" is not as uniform across FreePBX, Issabel, Elastix and VitalPBX as you'd hope. Here are the practical lessons — the same ground Q5000 automates when it connects to your PBX.
1. Never report against the PBX admin database user
Whatever reads your CDR should be a least-privilege, read-only MySQL/MariaDB user scoped to
the CDR database only. Reusing the root or admin credential your PBX ships with is an
unnecessary risk — a reporting tool only needs SELECT. Create a dedicated read-only user and
grant it nothing else.
2. VitalPBX makes that harder than FreePBX
On FreePBX, Issabel and Elastix you can generally create a read-only user the normal way. VitalPBX
runs MariaDB root as unix_socket-only, so you often can't simply log in and CREATE USER
remotely the same way.
The practical workaround is to detect and reuse an existing working CDR credential the platform already uses, rather than fighting socket authentication. VitalPBX keeps database credentials in:
/etc/vitalpbx/database.conf/etc/odbc.inires_odbc.conf
Prefer the application credential that can read both the CDR table and the extension directory, so a single credential covers reporting and user grouping.
3. Tunnel the connection — don't expose MySQL
Don't open port 3306 to the internet for a reporting tool. SSH-tunnel the database connection instead, and use one tunnel per PBX if you're consolidating multiple sites. This keeps the database unreachable from outside while your reporting tool connects over an encrypted channel.
4. Extension-to-department import differs by distro
Where the extension directory lives varies, so an importer needs a fallback chain rather than assuming one table:
- Classic Asterisk/FreePBX:
users/sip - VitalPBX (PJSIP):
ombu_extensions/ps_endpoints
Auto-detecting which source is populated saves a lot of "why did zero extensions import?" debugging.
5. Prioritise budget alerts over month-end reports
A monthly report tells you a department overspent after it happened. A threshold alert (say 80%, 90% and 100% of budget) tells the manager while they can still act. If you're building call cost tracking, the alerting is the part that changes behaviour — the report is just the record.
If you run a department hierarchy, make sure sub-department spend rolls up to parent budgets, or a branch can quietly blow the group number while each child looks fine.
Build it or automate it
None of this is exotic, but together it turns "I'll just query CDR" into a multi-day project that you then have to maintain. Q5000 handles all of it for FreePBX, Issabel, Elastix and VitalPBX: SSH-tunnelled read-only CDR access (auto-provisioning a least-privilege user on FreePBX, detect-and-reuse on VitalPBX), the multi-distro extension-import fallback chain, and department budget threshold alerts with hierarchy roll-up. See how Q5000 connects to your PBX →
Frequently asked questions
Why can't I create a read-only MySQL user on VitalPBX?
VitalPBX configures MariaDB root to authenticate via unix_socket only, so remote
CREATE USER the usual way often fails. The workaround is to reuse an existing CDR credential
from /etc/vitalpbx/database.conf or the ODBC configuration.
Do I need to expose my PBX's MySQL port to report on call costs? No — and you shouldn't. Tunnel the database connection over SSH so port 3306 stays closed to the internet.
Why did zero extensions import from my PBX?
The extension directory lives in different tables per distro (users/sip on FreePBX,
ombu_extensions/ps_endpoints on VitalPBX PJSIP). An importer needs to fall back across these
sources rather than assume one.
What's the best way to stop a department overspending on calls? Set a monthly budget and fire threshold alerts at 80/90/100% of spend so managers are warned before month-end, with sub-department spend rolling up to parent budgets.