The Remote Database Proxy (TCP/TLS): Securely Connecting Cloud Workers to Localhost

Quick answer
Secure Remote Database Proxy: Expose Local PostgreSQL & Redi: quick comparison answer
Choose the tunnel tool based on the network model: public HTTPS URLs for webhooks and demos, private mesh access for internal apps, and managed infrastructure when policy controls matter most.
Which tunnel tool is best for public webhook testing?
Use a public HTTPS localhost tunnel with stable URLs. InstaTunnel focuses on webhook testing, demos, OAuth callbacks, and MCP endpoint workflows.
When should I choose a private network tool instead?
Choose a private mesh or Zero Trust tool when every user and service should stay inside a controlled private network.
Modern cloud development has fundamentally fractured where our code runs versus where our data lives during the engineering lifecycle. We build serverless functions, deploy edge workers on Vercel or Cloudflare, and provision AWS Lambdas that scale infinitely. Yet the foundational data driving these deployments — your freshly seeded, carefully mocked relational database or fast-caching memory store — often sits right on your local machine.
The standard developer playbook usually dictates writing a mock HTTP API to sit in front of the local database, allowing the remote worker to fetch data. But sometimes you don’t want an API. When you’re testing complex Prisma migrations, debugging deeply nested SQL JOIN statements, or evaluating the raw throughput of a cloud worker connected to a cache, an API abstraction is an active hindrance. You need your cloud infrastructure to speak directly to your local database.
You need a way to expose local PostgreSQL to internet traffic securely, temporarily, and reliably. You need a TCP tunnel localhost database solution that bypasses network translation layers without compromising the integrity of your local machine.
In Part 8 of our deep dive into advanced developer networking, we explore the mechanics of Layer 4 tunneling. We’ll walk through exactly how to bridge the gap between cloud workers and local data stores using LocalXpose, covering secure Redis remote access and PostgreSQL connectivity via a raw TCP tunnel and a LocalXpose TLS tunnel — and where the tunnel type you pick changes what you actually need to configure on the database side.
The Networking Dilemma: Why Layer 7 Tunnels Fail Databases
If you’ve ever tried to use a standard webhook testing tunnel to expose a database, you’ve likely watched your terminal immediately vomit connection errors. Understanding why requires a brief descent into the OSI networking model.
Most developer tunneling tools operate strictly at Layer 7 (the Application Layer). They’re designed for HTTP and HTTPS traffic. When a request hits the tunnel’s public edge server, the proxy engine expects an HTTP request line (e.g., GET /api/users HTTP/1.1) and standard headers.
Databases do not speak HTTP.
PostgreSQL communicates using the Postgres wire protocol, a custom binary protocol. Redis uses RESP, the REdis Serialization Protocol. Both are fundamentally Layer 4 (Transport Layer) traffic. Pipe that binary stream into an HTTP tunnel and the proxy tries to parse it as HTTP text, fails to find valid headers, and abruptly terminates the connection.
To bypass this, developers traditionally resorted to one of two options, both worse than the problem:
- Port forwarding — digging into a residential router’s admin panel to expose port 5432 to the open internet. Severe security risk, and often blocked outright by ISPs running Carrier-Grade NAT (CGNAT).
- VPN gateways — setting up WireGuard or OpenVPN so the cloud worker and local machine share a virtual subnet. Works, but is hours of configuration for a five-minute testing session.
The modern answer is a dedicated TCP tunnel localhost database proxy: it skips HTTP parsing entirely and blindly forwards raw TCP byte streams from the public internet to your localhost port.
The Toolchain: Why LocalXpose?
The market is flooded with HTTP-only webhook proxies, but a reliable TCP and UDP tunneling service is a narrower search. LocalXpose is a reverse proxy purpose-built for this: it natively supports HTTP, HTTPS, TCP, TLS, and UDP tunnels, which is exactly the protocol range this workflow needs.
| Feature | HTTP Tunnel (Layer 7) | TCP Tunnel (Layer 4) | TLS Tunnel (Layer 4 + Security) |
|---|---|---|---|
| Parsing | Inspects headers and payload | No inspection; raw byte stream | Encrypted byte stream, no inspection |
| Target use case | Webhooks, Next.js previews | PostgreSQL, MySQL, SSH | Redis-with-TLS, production data syncs, anything that already speaks TLS |
| TLS termination | LocalXpose’s edge servers decrypt for you, then hand your app plain HTTP | Not applicable — traffic is unencrypted end-to-end unless the app encrypts it | Never at LocalXpose’s edge. Either your app terminates it, or you hand the LocalXpose client a cert/key and it terminates locally |
| LocalXpose support | loclx tunnel http |
loclx tunnel tcp |
loclx tunnel tls |
That TLS-termination row is worth pausing on, because it’s the part most guides — including an earlier draft of this one — get backwards, and it changes what Workflow 2 below actually requires.
Workflow 1: Expose Local PostgreSQL to the Internet
You have a Next.js app on a Vercel preview deployment, using Prisma, and you need it to talk to PostgreSQL running in Docker on your laptop.
1. Install and authenticate LocalXpose.
LocalXpose ships as a cross-platform binary and as an npm wrapper around it.
npm install -g loclx
loclx account login
(Homebrew, Snap, and Chocolatey builds exist too, if you’d rather not go through npm.)
2. Verify local PostgreSQL is running.
psql -h localhost -p 5432 -U postgres -d my_local_db
3. Start the TCP tunnel.
loclx tunnel tcp --to localhost:5432
This prints a dynamically generated public endpoint, e.g. us.loclx.io:49152. That’s now a direct pipe to your local port 5432 — with one catch: it’s random, and it changes every time you restart the tunnel. If you’re wiring this into a Vercel environment variable rather than pasting it into a one-off script, that’s a problem, because Vercel won’t know the port moved. Reserve a stable one instead:
loclx endpoint reserve
loclx tunnel tcp --reserved-endpoint us.loclx.io:4455
4. Point the remote worker at it.
# Format: postgresql://[user]:[password]@[tunnel-host]:[tunnel-port]/[db-name]
DATABASE_URL="postgresql://postgres:mysecretpassword@us.loclx.io:4455/my_local_db"
5. Run migrations or queries as normal.
Your cloud function connects to us.loclx.io:4455, which LocalXpose forwards straight into your Docker container.
Because TCP tunnels don’t inspect the payload, Postgres’s own SSL negotiation (sslmode=require, verify-full, client certs, whatever you’ve set on the server) rides through completely untouched. You don’t need LocalXpose’s TLS tunnel type for Postgres at all unless you specifically want the tunnel-level TLS on top — the wire protocol handles its own encryption if you’ve configured it to.
Workflow 2: Secure Redis Access with a LocalXpose TLS Tunnel
Redis presents a different problem than Postgres. It was designed to run inside trusted private networks, and plenty of local installs — including most default Homebrew and apt builds — don’t have TLS compiled in at all. If you push a default Redis instance across the public internet in plaintext, your cache contents, session tokens, and app state are readable to anyone on the path.
This is where a TLS tunnel matters — but here’s the correction: a loclx tunnel tls command does not, by itself, add encryption that wasn’t already there. LocalXpose’s TLS tunnel type keeps the byte stream encrypted across the public hop between its edge servers and your machine, but its edge servers never decrypt that stream for you the way they do for HTTP tunnels. Termination happens on your side, one of two ways:
- Your local service already speaks TLS. Point
loclx tunnel tlsat it and the encrypted bytes pass straight through, untouched, all the way to your app. - Your local service doesn’t speak TLS (plain FTP is LocalXpose’s own example). Then you hand the LocalXpose client itself a certificate and key with
--crt/--key, and the client decrypts locally before forwarding plaintext to your app.
Redis falls into the first case only if you’ve actually turned its TLS support on. Redis has had native TLS since version 6.0, but it’s an optional feature enabled with tls-port in redis.conf — and on many platforms it has to be compiled in explicitly (make BUILD_TLS=yes; redis-server --version should report tls=yes). A bare requirepass, with Redis still listening in plaintext on 6379, gives you authentication, not encryption — pointing a TLS tunnel at that port either fails outright or, if you use --crt/--key to have the client terminate locally, just re-adds plaintext RESP for the last hop into Redis, which is fine but worth knowing is what’s actually happening.
1. Enable TLS on local Redis.
# redis.conf
tls-port 6379
port 0
tls-cert-file /path/to/redis.crt
tls-key-file /path/to/redis.key
tls-ca-cert-file /path/to/ca.crt
requirepass MyUltraSecurePassword
Modern Redis also supports ACL-based users (ACL SETUSER) as a finer-grained alternative to the single global requirepass — worth using if more than one service will connect through the tunnel.
2. Confirm it’s listening.
redis-cli --tls --cert redis.crt --key redis.key --cacert ca.crt -h localhost -p 6379 ping
3. Start the TLS tunnel.
loclx tunnel tls --to localhost:6379
This gives you a secure endpoint, e.g. eu.loclx.io:51020 — again, reserve a domain if this needs to survive restarts.
4. Configure the remote client with rediss://.
# The 'rediss://' prefix enforces a TLS connection
REDIS_URL="rediss://default:MyUltraSecurePassword@eu.loclx.io:51020"
Because the tunnel itself is passthrough, the TLS handshake your Lambda’s Redis client performs is negotiated directly with your local Redis server — LocalXpose is just carrying the encrypted bytes, not a party to the encryption.
Locking It Down: IP Allowlisting
Both workflows above are reachable from anywhere on the internet by default, which is the whole point but also the risk. LocalXpose supports IP allowlisting as a config-file plugin, and it applies to TCP and TLS tunnels the same way it does to HTTP:
# config.yaml
db-tunnel:
type: tcp
region: us
to: localhost:5432
plugins:
ip_whitelist:
- 203.0.113.0/24 # e.g. your cloud provider's NAT gateway egress range
loclx tunnel config -f /path/to/config.yaml
If your Lambda or Vercel function has a static egress IP (an AWS NAT Gateway, for instance), restricting the tunnel to that CIDR closes off the “anyone who guesses the port” risk almost entirely.
One more practical note the earlier draft skipped: TCP and TLS tunnels aren’t available on LocalXpose’s free tier. The free/Starter plan is HTTP(S)-only; TCP, TLS, and UDP tunnels — along with reserved endpoints and custom domains — require the paid Pro plan (currently $8/month billed annually, $96/year, covering 10 concurrent tunnels across all protocols with unlimited bandwidth). Worth knowing before you build a workflow around a command that quietly won’t run on a free account.
The Principle of Least Privilege: Security Mandates
Punching a hole through your firewall directly into your local database is a powerful capability — and a loaded weapon. Bypassing your router’s NAT protection means security can’t be an afterthought:
- Never expose unauthenticated data stores. Strong passwords (or Redis ACL users) on PostgreSQL, MySQL, or Redis before the tunnel goes up, every time. Drop any
postgres:postgresoradmin:admindefaults. - Treat the tunnel as ephemeral. These are for temporary integration testing. Kill the LocalXpose daemon the moment the session ends — don’t leave it running.
- Mask your data. Local databases exposed this way should hold only synthetic or heavily anonymized data. Never restore a production dump with real PII to a laptop and then tunnel it out; a compromised tunnel turns your local machine into the source of a breach.
- Use IP allowlisting where the calling infrastructure has a stable, known egress range — see above.
Surviving the Latency Equation: Connection Pooling
There’s a final engineering reality worth naming: physics. A Lambda in us-east-1 querying an RDS instance in the same region sees sub-millisecond latency. That same Lambda querying your laptop through a TCP tunnel has to go from the AWS data center, to LocalXpose’s edge, across the public internet, through your ISP, onto your Wi-Fi, into Docker, and back. A single query might take 100ms; an ORM resolving a chain of relations with dozens of sequential round trips (the N+1 problem) can turn 50ms of production latency into several seconds through the tunnel.
The one thing worth correcting here: Lambda’s default timeout is 3 seconds, not 10 — and it’s configurable up to a hard ceiling of 900 seconds (15 minutes). But that ceiling only applies to the Lambda function itself. If it’s invoked through API Gateway (REST or HTTP API), the gateway enforces its own hard 29-second cap regardless of what you’ve set on the function — bumping your vercel.json or serverless.yml timeout to 60 seconds won’t help if API Gateway is what’s actually cutting the connection. Function URLs and direct/async invocations (EventBridge, SQS) aren’t subject to that 29-second limit and can use the full 900 seconds if you need it.
To mitigate the round-trip cost while testing:
- Raise the timeout on the right layer — the Lambda’s own setting, and separately the API Gateway integration timeout if one is in the path.
- Pool connections locally. Serverless functions open and close connections constantly, which is expensive over a high-latency tunnel. Run PgBouncer in front of PostgreSQL and point the tunnel at PgBouncer instead of the raw database.
- Batch your queries. Prefer bulk
INclauses over iterative loops to cut the number of round trips.
Automating It: Docker, the Node.js Client, and CI/CD
Beyond the interactive CLI, LocalXpose ships a few pieces aimed specifically at not having to type loclx tunnel ... by hand every time:
- An official Node.js client (
node-localxposeon GitHub, published aslocalxposeon npm) with a promise-based API —client.tcp({ to: '127.0.0.1:5432', reservedEndpoint: '...' })orclient.tls({ crt: '/path/to/cert.pem', key: '/path/to/key.pem' })— for wiring tunnel lifecycle directly into a test runner or seed script instead of shelling out. - An official Docker image (
localxpose/localxpose), useful for running the tunnel as a sidecar container; if you’re generating Let’s Encrypt certificates for a TLS tunnel this way, mount a volume for/home/nonroot/.localxposeor you’ll hit Let’s Encrypt’s 5-certificates-per-domain-per-week limit on every container restart. - A GitHub Action (
LocalXpose/localxpose-action@v1) for spinning up a tunnel inside a workflow run — handy for integration tests that need a real Postgres instance reachable from a hosted runner without standing up infrastructure for it.
None of this changes the underlying TCP/TLS mechanics above; it just moves the same commands into places where you’d rather not run them manually.
The Ultimate Integration Shortcut
The remote database proxy is a testament to how flexible modern backend development has become. By leveraging tools capable of Layer 4 routing, we can temporarily collapse the physical distance between serverless cloud infrastructure and local development environments.
Whether you’re debugging a flaky microservice, testing webhook data transformations, or just refusing to write a mock API for a one-off cache test, the TCP tunnel localhost database pattern is worth having in the toolbox — as long as you’re clear on which tunnel type does what, which one needs a paid plan, and which one actually needs your database to speak TLS before the tunnel can do anything useful with it.
Changelog
Fact-checked against LocalXpose’s own documentation, GitHub repos, npm listings, Redis’s official docs, and AWS Lambda documentation (checked September 9, 2026).
- Biggest correction (TLS tunnel mechanics): the draft implied LocalXpose “can terminate a TLS connection at the edge or pass it through directly,” suggesting edge-side decryption as an option for TLS tunnels the way it works for HTTP tunnels. LocalXpose’s own docs are explicit that TLS tunnels never terminate at the edge — the stream either passes straight through to an app that already speaks TLS, or you supply
--crt/--keyand the client on your machine terminates it. Rewrote Workflow 2 and the comparison table around this. - Redis TLS prerequisite the draft skipped entirely: the original workflow only asked for a strong
requirepassbefore runningloclx tunnel tls --to localhost:6379, which doesn’t work unless Redis’s own TLS support is actually enabled (tls-port, and on many buildsmake BUILD_TLS=yes) — Redis has had this since 6.0, but it’s opt-in, not default. Added theredis.confTLS block and a client-certredis-clicheck as real prerequisite steps; noted ACL users as a modern alternative to a single globalrequirepass. - AWS Lambda timeout facts corrected: draft’s “typically 10 seconds for standard setups” isn’t an AWS figure — the actual default is 3 seconds, configurable up to a 900-second (15-minute) ceiling. Added the detail the draft missed entirely: functions invoked through API Gateway are hard-capped at 29 seconds by the gateway itself, independent of the Lambda’s own timeout setting, so the draft’s “bump to 60 seconds” advice would silently fail for API-Gateway-fronted functions; noted Function URLs and async invocations aren’t subject to that cap.
- Free-tier gating not mentioned in the draft: added that TCP, TLS, and UDP tunnels — plus reserved endpoints and custom domains — require LocalXpose’s paid Pro plan ($8/month billed annually, $96/year, 10 tunnels, unlimited bandwidth); the free/Starter tier is HTTP(S)-only. Both workflows in the draft would fail on a free account without this caveat.
- Reserved endpoints added: the draft’s example output (
us.loclx.io:49152) is a randomly assigned address that changes on every tunnel restart, which undermines wiring it into a persistedDATABASE_URL/REDIS_URL. Addedloclx endpoint reserveand--reserved-endpointas the actual fix, sourced from LocalXpose’s TCP tunnel docs. - IP allowlisting made concrete: the draft only asserted that “advanced reverse proxies… offer IP restriction capabilities” without showing how. Added the real
config.yamlip_whitelistplugin syntax, confirmed against LocalXpose’s own config-file documentation, and noted it applies to TCP/TLS tunnels the same as HTTP. - Postgres/TLS-tunnel clarification added: noted that because TCP tunnels are payload-agnostic, Postgres’s own
sslmodenegotiation passes through a plain TCP tunnel untouched — Postgres doesn’t need the TLS tunnel type at all unless you specifically want tunnel-level TLS on top, a distinction the draft never drew. - New section added (Docker, Node.js client, CI/CD): the draft didn’t mention LocalXpose’s official Node.js client (
node-localxpose/localxposeon npm), Docker image, or GitHub Action, all of which are relevant to automating the exact workflows described. Added with the Let’s Encrypt rate-limit caveat for the Docker case (5 certs/domain/week, requires volume persistence). - Verified as accurate and left unchanged:
npm install -g loclx,loclx account login,loclx tunnel tcp --to localhost:5432,loclx tunnel tls --to localhost:6379, therediss://URL scheme, and the general Layer 4 vs. Layer 7 framing. - Removed non-standard scaffolding (no visible frontmatter or metadata block remained in the delivered draft; formatting normalized into standard Markdown headings and fenced code blocks throughout).
Related InstaTunnel pages
Continue from this article into the most relevant product guides and workflows.
Related Topics
Keep building with InstaTunnel
Read the docs for implementation details or compare plans before you ship.