The requirement was ordinary: agents needed to see their own call data from a portal. The constraint was not. The portal ran on shared hosting, and the call data lived in MySQL on the PBX VPS.
Connecting the two directly means exposing a production database to a shared hosting environment, where you do not control the neighbours, the outbound IP range is not reliably yours, and database credentials sit in a filesystem you do not administer.
Why the obvious fixes are not enough
- Allowlisting the shared host's IP: shared hosting IPs are shared, so you are allowlisting every other tenant on that host too.
- A read-only database user: reduces the blast radius but still exposes the full schema and full row set to anyone who reads the credentials.
- A VPN from the shared host: usually not available, and if it were, it puts an untrusted machine inside your network perimeter.
Each of these treats the problem as a network access question. It is better treated as a data exposure question: the portal does not need database access, it needs answers to a small number of specific questions.
The API proxy pattern
- 1
Run the proxy on the trusted side
An n8n instance on the VPS, inside the same trust boundary as the database, acts as the only thing that ever holds database credentials.
- 2
Expose named endpoints, not queries
The portal calls webhook endpoints that each answer one defined question. It never sends SQL, so it cannot ask for anything that was not designed for it.
- 3
Authenticate with a shared secret
Requests carry a shared secret, so an endpoint discovered by scanning is not an endpoint that can be used.
- 4
Execute server-side and return only what is needed
Queries run on the VPS and the response contains only the fields required to render that view, not whole rows.
- 5
Keep the database closed
MySQL accepts connections from the VPS static IP alone. The public internet, including the shared host, cannot reach it.
Why this is stronger than a firewall rule
A firewall rule answers the question of who may connect. It says nothing about what they may then ask for. Once a connection is permitted, the full schema is reachable and the only remaining control is the database user's grants, which are coarse by comparison.
The proxy inverts that. The set of possible requests is finite and defined in advance, so the worst case for a leaked shared secret is that someone can call the same endpoints the portal calls, returning the same narrow fields. That is a meaningfully smaller incident than a reachable database.
Result
Agents reach their call data through the portal while the database itself stays closed to the public internet, with no database credentials held on the shared host.
Sources and further reading
- One agent dashboard across multiple FreePBX servers— a related portal that avoids the whole problem by holding no database of its own
- Secrets management for business systems— where the shared webhook secret should live
- Network segmentation for growing businesses— the segmentation principle this proxy pattern extends to the database layer
- n8n workflow automation for modern businesses— the platform used as the proxy here
Services This Relates To
Written by KYCONNECTS Engineering. Client names are withheld under confidentiality.