Background
A VoIP phone system sits at the center of a service business. Every inbound call is a customer interaction that might also need a ticket created, a contact looked up, a callback scheduled, or a Slack notification sent. The phone system exposes a rich call control API, but the API alone does not get you workflows — it gets you a place to start.
n8n is a self-hostable visual workflow engine, well-suited to gluing systems together. The piece that was missing was a clean bridge between the phone system’s call control surface and n8n’s node model.
What I built
A set of custom n8n nodes, published as an npm package, that turn the phone system’s call control API into first-class building blocks inside n8n. The nodes cover the operations that actually matter for automation: answering and hanging up calls, transferring between extensions and queues, playing prompts, collecting DTMF input, routing through IVR logic, and subscribing to real-time call events via webhooks.
Alongside the nodes, a deployment repo provisions a production n8n instance on a single DigitalOcean droplet. The droplet runs n8n in Docker behind Caddy. Provisioning is scripted end to end — droplet creation, firewall, DNS expectations, Tailscale enrollment, n8n container with persistent volumes, and Caddy with automatic Let’s Encrypt certificates.
How access is split
The deployment runs two access paths on the same host with different trust profiles.
The n8n editor UI — where workflows are designed, credentials are stored, and the full system surface lives — is bound to the Tailscale interface only. Reaching it requires being on the tailnet. There is no public route to the editor at all.
The webhook endpoints — which receive the phone system’s call events and any other inbound triggers — are exposed publicly through Caddy at a real domain with a real TLS certificate. They are read-only intake. The phone system POSTs an event, n8n acknowledges, and the workflow runs internally.
This split keeps the high-value surface (workflows, credentials, integrations) entirely off the public internet, while letting the parts that need to be reachable — and only those parts — be reachable. The droplet itself sits behind a cloud firewall that only allows the necessary ports through.
Why it matters
Most “connect your phone system to your CRM” stories rely on a vendor’s own integration marketplace and end where that marketplace ends. Building custom n8n nodes turns the same call control API into a generic capability you can wire to anything else n8n can talk to — ticketing systems, identity providers, chat platforms, calendars, internal scripts. The automation is no longer constrained to whichever integrations the vendor decided to ship.
The deployment pattern is the part that scales. Tailscale for the management plane and Caddy for the public ingress keeps the production environment small, cheap, and defensible without giving up the visual-workflow ergonomics that make n8n worth running in the first place.