Concept Write-up: MachPBX
I often have ideas for stories I'd like to tell and programs I'd like to write. More often than not, I do not have time to actually implement them. So I will take this small break to flesh them out a bit with words so that when I do have time, I have my original thoughts on “paper”.
The Idea
So I was, for a long time, a telephony engineer. I still do some phone things, but not like I used to do. I have worked on a great many systems some big ones like Cisco CallManager, but mostly smaller, open source systems. A lot of Switchvox (I know, not open source), FreePBX (and it's lying, commercial sibling PBXact), and FusionPBX.
And they're all... okay. They want to be something they're not. They want to be these big systems that can help small, two-phone offices as well as thousand-plus, multi-location corporations. And on top of that, they are built with older programming paradigms that make them very clunky to extend.
FreePBX, for example, is a proprietary PBX that lacks any sensible way to scale other than throwing more hardware at it. It wants to be this big player, but lacks the technical capability to do so. And in case you're wondering about why I called it proprietary, it is technically open source. Several core components are open source. However, there's no sensible way to install it other than the ISO, and they claim a copyright on the ISO and that no one else can distribute it. On top of that, several key modules are proprietary and Sangoma is very hostile to anyone that tries to build modules that may even hint at similar functionality. It's closed source wearing an open source mask.
FusionPBX, on the other hand, has all of the tools to scale massively, but every piece of it feels very outdated. Visually, it's an engineers idea of good UX. Managing upgrades requires git knowledge (fine for developers, but not phone engineers). Scaling requires you to be a database admin. Certificates are fetched from Let's Encrypt, but you have to renew them manually. And, finally, writing new features is like time traveling back to 2005 in the bad, old days of PHP development.
What's extra silly about FusionPBX is that the core concepts are brilliant. It's just the implementation that needs work, and that's where I will begin.
The Infrastructure
To begin, this is not going to be some system that claims to be the answer for every phone situation. It's intended to be a single server PBX with a rock solid foundation. It will scale with better hardware and it will keep your data safe, but it's not intended to run across multiple boxes or automatically fail over to backup hardware (though that would probably be possible with some tweaking).
For a good system, you need your core software pieces to be solid. FusionPBX uses nginx, PHP, and PostgreSQL for the web UI. For the phone switch, it's FreeSWITCH running Lua scripts to fetch config data. It's very clever, especially since Lua is built into FreeSWITCH and can manage calls and how they route. Because this is a solid foundation I'm going to start similar.
The MachPBX web UI is also going to be PHP. I'm going to change up the web server to Caddy. Caddy has an API that I can keep behind a firewall, and then use PHP to make calls to it for any changes I need to make. On top of that, Caddy has built in support for Let's Encrypt. That way certificates can renew without any extra work. A cronjob written in PHP will run daily to check for new certificates, compile them into a bundle and stash them in a place that FreeSWITCH can reach.
The database will also be changed to SQLite. It simple to run, and rock-solid production software. A single SQLite database will run to manage users and permissions, and then each tenant on the phone system will get a separate SQLite database. Will multi-tenancy be useful on a PBX like this? No clue, but it's easy to do on the phone switch.
Also running will be Litestream, a software that replicates SQLite databases to various remote storage solutions. This along with rclone will make sure all of the data is safely stored remotely.
For the phone routing, the system will run FreeSWITCH with Lua scripting to handle config and call routing. Essentially, like Fusion PBX does now. How I will handle it will vary slightly, but that will be explained below when we reach the section regarding modules.
All of this will be installed on any FreeSWITCH supported OSs using Ansible to handle the installation and configuration of softwares.
The Web UI Backend
Here's where the biggest deviation from FusionPBX happens. FusionPBX's PHP UI is mostly self-written with no framework being used. Each module, despite being separate modules, is packaged with the main git repo. So when you download the PBX, you download every module whether you need it or not. And each module doesn't follow the common MVC paradigm... or really anything. When a module is loaded into the PHP applicaiton, you can add a menu item. However, the menu item simply points to a PHP file. The PHP file then handles everything. The logic, the database calls, and writing the HTML to the browser. On top of that, nothing is documented so it requires looking at every other module to figure out how to do anything.
For MachPBX, off the shelf libraries will be used when possible. To this end, it will use the CakePHP framework. There are a lot of great frameworks out there, but I think Cake would require the least amount of tinkering to be production ready and still be easy enough for developers to contribute to the project.
Every piece of the MachPBX UI will be a standard CakePHP Plugin (for which the project includes documentation) that can be installed using Composer. Adding functionality to MachPBX will be almost as easy as writing a CakePHP plugin, and interactions with FreeSWITCH using the plugins will be documented so that as many people as possible can contribute to the project.
And speaking of FreeSWITCH, since it will use Lua scripts to deal with configuration and call handling we'll need a way to include those scripts in the plugins. Which is why part of the install process for plugins will include a method to add that plugin's lua scripts to the search path used by Lua within FreeSWITCH. Thus making the whole system modular.
A modular system would be very handy for those times when you don't want to install support for every phone manufacturer under the sun. Maybe you just want Yealink or Snom, or Yealink and Snom but not Polycom. The point is to have the option to choose, and make it easy for you to do that.
The Web UI Frontend
So finally, the part of the UI that users can see. Most phone systems are ugly to look at. We'll work this one to be more pleasant to use, and the design will use an efficient CSS framework to keep it looking mostly consistent across plugins.
Personally, I tend to shy away from CSS frameworks, choosing to write all of the CSS from scratch. Because of this, I haven't yet chosen one to use. But I would like it to include the common pieces like forms, tables, buttons, and such. Even better would be if it included a dark mode. Once I find a suitable option, I will update this section with more details.