Skip to main content

Introduction to rs-tunnel

rs-tunnel is a self-hostable alternative to ngrok that creates secure public hostnames for localhost services through Cloudflare’s infrastructure. It provides enterprise-grade authentication, tunnel lifecycle management, and automatic cleanup of stale sessions.

What is rs-tunnel?

rs-tunnel is a platform consisting of:

CLI

@ripeseed/rs-tunnel - User-facing command line tool

API

@ripeseed/api - Fastify-based backend with Postgres

Shared

@ripeseed/shared - Type-safe Zod contracts
It exposes local HTTP services at https://<slug>.<base-domain> with full SSL termination, authentication, and automatic DNS management.

Key Features

Secure Access Control

  • Email domain restriction: Only users from approved email domains can authenticate
  • Slack workspace validation: Enforces team membership through Slack OpenID
  • JWT-based authentication: Short-lived access tokens with refresh token rotation
  • Server-side credential management: CLI never holds Cloudflare API tokens

Automatic Lifecycle Management

  • Dynamic DNS provisioning: DNS records are created/deleted with tunnel lifecycle
  • Heartbeat-based leasing: Clients heartbeat every 20 seconds to maintain tunnels
  • Stale session cleanup: Automatic reaping of tunnels when clients stop responding
  • Quota enforcement: Configurable max active tunnels per user (default: 5)

Developer Experience

  • ngrok-style dashboard: Real-time request monitoring during rs-tunnel up
  • Custom URLs: Request specific slugs with --url my-app
  • Simple commands: login, up, list, stop, logout, doctor
  • Self-hosted flexibility: Configure custom API domains with --domain

Robust Infrastructure

  • Cloudflare edge network: Leverages Cloudflare Tunnel for global performance
  • Postgres-backed state: Reliable persistence with Drizzle ORM
  • Background workers: Reaper process handles cleanup jobs with exponential backoff
  • Audit logging: Track all tunnel creation and stopping events

How It Compares to ngrok

rs-tunnel

  • Self-hosted and open source
  • Organization-level authentication (Slack)
  • Email domain whitelisting
  • Full control over infrastructure
  • Uses your Cloudflare account
  • Customizable tunnel limits

ngrok

  • SaaS offering
  • Individual account authentication
  • Shared infrastructure
  • Managed service
  • ngrok’s infrastructure
  • Pricing-based limits
rs-tunnel is ideal for teams that want tunnel capabilities with organization-level access control and infrastructure ownership.

Core Concepts

Tunnel Lifecycle

Every tunnel goes through these states:
  1. creating - Initial state during Cloudflare tunnel + DNS setup
  2. active - Tunnel is running and accepting connections
  3. stopping - Shutdown initiated, DNS/tunnel cleanup in progress
  4. stopped - Tunnel fully cleaned up
  5. failed - Error during creation or operation

Heartbeat & Leases

The CLI sends a heartbeat every 20 seconds. Each heartbeat refreshes the lease with a 60-second timeout. If the API doesn’t receive a heartbeat before the lease expires, the tunnel is marked stale and queued for cleanup by the reaper worker.

Slugs & Hostnames

Tunnels are exposed at https://<slug>.<CLOUDFLARE_BASE_DOMAIN>. Slugs must be:
  • Single-label (no nested domains)
  • 1-32 characters
  • Alphanumeric and hyphens only
  • Start and end with alphanumeric
Example valid slugs: my-app, api-dev, test123

Authentication Flow

  1. User runs rs-tunnel login --email [email protected]
  2. CLI starts OAuth PKCE flow through the API
  3. API redirects to Slack for OpenID Connect authentication
  4. API validates email domain and Slack team ID
  5. User receives access token (15 min TTL) + refresh token (30 day TTL)
  6. CLI stores tokens securely (keytar when available, file fallback)

Quick Start

1

Install the CLI

npm install -g @ripeseed/rs-tunnel
2

Login to your organization's API

rs-tunnel login --email [email protected] --domain https://api.company.com
The CLI will open your browser for Slack authentication.
3

Start a tunnel

rs-tunnel up --port 3000 --url my-app
Your local service at http://localhost:3000 is now accessible at https://my-app.tunnel.company.com
4

Monitor requests

The terminal displays an ngrok-style dashboard with:
  • Account info and tunnel details
  • Connection metrics (ttl, opn, rt1, rt5, p50, p90)
  • Live HTTP request stream
5

Stop the tunnel

Press Ctrl+C or run:
rs-tunnel stop my-app

Use Cases

Local Development

Test webhooks, OAuth callbacks, and integrations without deploying

Team Demos

Share work-in-progress features with teammates instantly

Mobile Testing

Access localhost from physical devices on different networks

Third-party Integrations

Test Slack bots, payment processors, and external APIs

Architecture Highlights

  • Monorepo: pnpm workspace with apps (API, CLI) and shared packages
  • Type safety: End-to-end type safety with Zod schemas in @ripeseed/shared
  • Security model: Provider secrets (Cloudflare, Slack, JWT) live only in API runtime
  • Reliability: Background reaper worker with exponential backoff for cleanup retries
  • Observability: Audit logs, tunnel metrics, and request history
Continue to Architecture for detailed system design or How It Works for the full request flow.

Non-Negotiable Constraints

These constraints are enforced by the system and cannot be bypassed:
  • Only emails matching ALLOWED_EMAIL_DOMAIN can authenticate
  • Slack workspace must match ALLOWED_SLACK_TEAM_ID
  • No nested domains - slugs are single-label only
  • Max 5 active tunnels per user (server-side enforcement)
  • DNS records are deleted when tunnels stop
  • Stale tunnels are automatically cleaned up
  • CLI never receives Cloudflare API credentials

Next Steps

Architecture

Learn about the monorepo structure, tech stack, and component interactions

How It Works

Understand tunnel creation, heartbeats, DNS lifecycle, and cleanup mechanisms

Installation

Set up rs-tunnel for local development or production deployment

CLI Reference

Complete command reference and configuration options

Build docs developers (and LLMs) love