Harsh Vardhan Goswami
Jul 4, 2025
As software teams build increasingly data-driven products, the need to securely connect local databases and private services to cloud platforms has never been greater. Yet, exposing sensitive resources to the public internet or relying on third-party tunneling services introduces risk and complexity that most developers—and their security teams—would rather avoid. At SyneHQ, we faced this challenge head-on while building our own data platform, and it inspired us to create Rabbit: an open-source, production-ready TCP tunneling system that puts security, control, and reliability back in your hands.
At SyneHQ, we obsess over making data platforms seamless and secure. But as our users grew, so did a challenge: how do you connect local databases and services to a cloud platform—without opening up your firewall or trusting a third-party tunnel?
Today, we’re excited to share Rabbit: an open-source, production-grade TCP tunneling system designed for developers and teams who want secure, persistent, and fully-owned tunnels to their local resources.
In this post, we’ll walk through the problems Rabbit solves, how it works, and best practices for deploying it in real-world environments.
Why We Built Rabbit
When building Syne, we saw a pattern: developers and data teams often run databases and services on their laptops, in private VPCs, or behind strict firewalls. Exposing these to the internet—even temporarily—was a non-starter for many.
Existing tools like ngrok
are great for demos, but they require you to trust a third-party, pay per tunnel, and accept session-based, public endpoints. We wanted a solution that was:
Persistent: Your tunnel, your port, always available.
Private: No public subdomains or shared infrastructure.
Production-ready: Survives restarts, logs everything, and scales with your team.
Self-hosted: You control the infrastructure, tokens, and access.
Rabbit in Action: How It Works
Rabbit is built to be developer-friendly and robust in production:
You deploy Rabbit server on a VPS or cloud instance you control.
Your users run Rabbit client on their local machines, connecting their local database or service.
Each user gets a unique token—generated via the API—that maps to a persistent port.
Your platform connects to that port to access the user’s local resource, securely tunneled through your infrastructure.
Rabbit is perfect for:
Data platforms (like Syne) that need secure access to user databases.
Dev teams sharing local services for review or testing.
Analytics and staging environments that need to bridge private data.
Security & Control: The Token System
Rabbit’s token model gives you fine-grained, auditable control:
One token = one port = one tunnel. No conflicts, no sharing.
Teams and environments can have their own tokens.
Revoke a token, free up the port. No lingering access.
All connections logged—know who connected, when, and how much data was transferred.
This model is inspired by best practices in access control and disaster recovery: always know your critical assets, and be able to revoke or restore them instantly
Technical Deep Dive: Under the Hood
Rabbit is written in Go, using idiomatic concurrency and a layered, modular architecture:
Core Server Structure
The Rabbit server manages tunnels, connections, and state using Go’s concurrency primitives:
Each tunnel is tracked as a first-class object:
Connection Pairing and Bridging
When a new external connection arrives, the server notifies the client via a persistent control channel. The client opens a matching data connection, and the server bridges the two using Go’s io.Copy
for efficient, bidirectional streaming:
Automatic Restoration and Resilience
Rabbit’s server persists tunnel state in PostgreSQL. If the server restarts, it automatically restores all active tunnels and their port assignments:
This ensures your tunnels survive outages and maintenance windows, minimizing downtime and manual intervention.
For a detailed flow. Checkout our Github Docs:
Real-World Reliability: Built for Production
Rabbit isn’t just for demos—it’s designed for real workloads:
Automatic restoration: If the server restarts, tunnels and port assignments are restored from the database.
Seamless reconnection: Clients can reconnect without losing their port or session.
Comprehensive logging: Every connection is tracked for auditing and troubleshooting.
Docker-ready: Deploy Rabbit anywhere, scale as needed.
Health checks and monitoring: API endpoints for status and metrics.
Getting Started: Deploy Your First Rabbit Tunnel
1. Set up the Server
2. Connect a Client
3. Generate and Manage Tokens
lightbulb_2
Pro tip
Best Practices for Running Rabbit in Production
Just like disaster recovery in Kubernetes, running a tunnel system in production means planning for the unexpected:
Back up your Rabbit server’s database regularly. This ensures you can restore tunnels and tokens after an outage.
Define your RPO/RTO: How much downtime or data loss can you tolerate? Rabbit’s persistence model helps minimize both.
Document your recovery process: Make sure any team member can restore tunnels or revoke tokens in an emergency.
Automate health checks and alerting: Use Rabbit’s APIs to monitor tunnel health and usage.
Use role-based access control: Limit who can create or revoke tokens, especially in multi-team environments.
Why Not ngrok or Other Tunneling Services?
ngrok / Public Tunnels | Rabbit (Self-Hosted) |
---|---|
Trust a third-party | You control everything |
Pay per tunnel | Free, runs on your infra |
Public, ephemeral endpoints | Private, persistent ports |
Limited logs or monitoring | Full API, database-backed logs |
Session-based, can expire | Survives restarts, always on |
Looking Ahead
Rabbit is open source and ready for your feedback. We’re excited to see how the developer community uses and extends it. We’re already planning features like mTLS, rate limiting, and advanced analytics.
Ready to take control of your tunnels?
Check out the Rabbit repo and get started today.
Built with ❤️ by the SyneHQ team for developers who demand reliability, security, and control.