Expose local services to the public internet — Open Source & Self-Hostable
Quick Start • Features • Security • Self-Hosting • Documentation • Contributing
Jrok is an open-source tunnel service that exposes your local development servers to the public internet. Think of it as a self-hostable alternative to ngrok, localtunnel, or Cloudflare Tunnel.
Use cases:
- 🔧 Development — Test webhooks, share WIP with clients
- 🚀 Demos — Show local apps without deploying
- 🔌 IoT — Access devices behind NAT/firewalls
- 🧪 Testing — Mobile testing against local servers
No server setup required. Get started in 30 seconds:
# Install CLI with one command
curl -fsSL https://raw.githubusercontent.com/koompi/jrok/v2.3.0/install.sh | bash
# Expose your local service (you'll be prompted for API key)
jrok --port 3000Output:
🎲 Generated subdomain: a1b2c3d4
🔌 Connecting to jrok server...
📍 Domain: a1b2c3d4
🏠 Local Service: localhost:3000
✅ Connected to server!
🌐 Your service is now available at: https://a1b2c3d4.tunnel.koompi.cloud
Get your API key at jrok.koompi.cloud
Deploy your own Jrok server for complete control:
git clone https://github.com/koompi/jrok.git
cd jrok
./scripts/deploy.shThe deploy script will guide you through the entire setup. See Self-Hosting Guide for details.
# Simple - auto-generate subdomain
jrok --port 3000
# Custom subdomain
jrok --port 8080 --domain myapp
# → https://myapp.tunnel.koompi.cloud
# TCP tunnel (raw TCP, databases, SSH, etc.)
jrok --port 5432 --tcp
# → tcp://tunnel.koompi.cloud:54321# If "myapp" is already taken by another org, auto-assigns suffix
jrok --port 3000 --domain myapp
# → https://myapp-a7b3.tunnel.koompi.cloud
# Force new subdomain even if you own the existing one
jrok --port 3000 --domain myapp --force-new
# → https://myapp-c2d4.tunnel.koompi.cloud# Register a custom domain with auto-generated subdomain
jrok domain register --domain mysite.com
# Register with specific subdomain target
jrok domain register --domain mysite.com --subdomain myapp
# Verify CNAME and issue SSL certificate
jrok domain verify --domain mysite.com
# Check domain status
jrok domain status --domain mysite.com# Docker Swarm service
jrok connect --domain api --docker-service my-api
# Kubernetes service
jrok connect --domain app --k8s-service my-svc:8080- Create organizations for teams
- Invite members with role-based access
- Manage API keys per organization
- Usage tracking and analytics
- HTTPS with automatic SSL certificates (Let's Encrypt)
- WebSocket connections over WSS
- API key authentication with scoped permissions
- OAuth via KOOMPI ID
- CNAME verification required for custom domains (prevents domain abuse)
- Rate limiting on HTTP requests per tunnel
- TCP connection limits per agent
- Bandwidth throttling per tunnel
- IP allowlist support for restricting access
- Connection logging for audit trails
- Manage tunnels and domains
- Create and revoke API keys
- View usage statistics
- Organization management
┌─────────────────────────────────────────────────────────────────────┐
│ INTERNET │
└─────────────────────────────────────────────────────────────────────┘
│ │
(HTTP/HTTPS) (TCP - databases, etc.)
▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ YOUR VPS SERVER │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Nginx (SSL termination, wildcard certs) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Jrok Server (Bun runtime) │ │
│ │ • WebSocket connection manager │ │
│ │ • HTTP/TCP request routing │ │
│ │ • Authentication (OAuth + API keys) │ │
│ │ • Security (rate limits, bandwidth, IP allowlist) │ │
│ │ • MongoDB (users, orgs, tunnels, custom domains) │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
▲ ▲ ▲
│ WSS │ WSS │ WSS
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Jrok Agent │ │ Jrok Agent │ │ Jrok Agent │
│ (laptop) │ │ (server) │ │ (CI/CD) │
│ :3000 │ │ :8080 │ │ :5000 │
└────────────┘ └────────────┘ └────────────┘
# Expose local port (auto-generates subdomain)
jrok --port 3000
# Specify subdomain
jrok --port 3000 --domain myapp
# TCP tunnel (databases, SSH, custom protocols)
jrok --port 5432 --tcp
# Force new subdomain (even if you own existing one)
jrok --port 3000 --domain myapp --force-new
# List active tunnels
jrok list
# Disconnect tunnel
jrok disconnect --domain myapp
# Show configuration
jrok config
# Get help
jrok help# Register custom domain (auto-generates subdomain target)
jrok domain register --domain mysite.com
# Register with specific subdomain
jrok domain register --domain mysite.com --subdomain myapp
# Verify CNAME configuration and issue SSL
jrok domain verify --domain mysite.com
# Check domain verification status
jrok domain status --domain mysite.com
# List all your custom domains
jrok domain list# List organizations
jrok org list
# Create organization
jrok org create --name "My Team"
# Create API key
jrok apikey create --org <org-id> --name "CI Key"# Set server (for self-hosted)
jrok config --server https://tunnel.yourdomain.com
# Set API key
jrok config --auth jrok_your_api_key
# Clear config
jrok config --clearSee CLI Commands Reference for full documentation.
Jrok includes comprehensive security features to protect your tunnels:
| Feature | Description |
|---|---|
| TCP Connection Limits | Maximum concurrent TCP connections per agent |
| Bandwidth Throttling | Per-tunnel bandwidth limits prevent abuse |
| HTTP Rate Limiting | Request rate limiting per tunnel |
| IP Allowlist | Restrict tunnel access to specific IPs |
| Connection Logging | Full audit trail of all connections |
| CNAME Verification | Custom domains require DNS verification before SSL |
When registering a custom domain, Jrok requires CNAME verification:
- Register domain → Jrok provides CNAME target
- Configure DNS → Add CNAME record pointing to target
- Verify → Jrok confirms DNS propagation
- SSL Issued → Certificate generated only after verification
This prevents domain abuse and ensures you own the domain.
- Different org owns subdomain: Auto-generates suffix (e.g.,
myapp-a7b3) - Same org owns subdomain: Updates existing tunnel OR use
--force-newfor new subdomain - Subdomain available: Assigns as requested
| Requirement | Where to Get It |
|---|---|
| Domain name | Any registrar |
| DigitalOcean account | digitalocean.com |
| Cloudflare account | cloudflare.com |
| MongoDB Atlas | mongodb.com/atlas (free tier) |
| KOOMPI ID credentials | dash.koompi.org |
The easiest way to deploy is using our automated script:
git clone https://github.com/koompi/jrok.git
cd jrok
./scripts/deploy.shThe script will interactively:
- ✅ Prompt for all required credentials
- ✅ Create VPS on DigitalOcean (via Terraform)
- ✅ Configure DNS records
- ✅ Issue SSL certificates (via Certbot + Cloudflare)
- ✅ Deploy and start all services (via Ansible)
Before running the deploy script, gather these credentials:
| Credential | How to Get It |
|---|---|
| DigitalOcean Token | API → Tokens → Generate |
| Cloudflare Token | Profile → API Tokens → Create |
| MongoDB URI | Atlas → Connect → Connection String |
| KOOMPI OAuth | dash.koompi.org → Create Project |
For custom configurations, see our detailed guides:
- 📖 Self-Hosting Guide — Complete walkthrough
- 🏗️ Terraform Setup — Infrastructure provisioning
- ⚙️ Ansible Deployment — Server configuration
- 🐳 Docker Deployment — Container-based setup
| Variable | Description | Required |
|---|---|---|
MONGODB_URI |
MongoDB connection string | ✅ |
JWT_SECRET |
Secret for JWT tokens (64+ chars) | ✅ |
BASE_DOMAIN |
Base domain for tunnels | ✅ |
KOOMPI_CLIENT_ID |
OAuth client ID | ✅ |
KOOMPI_CLIENT_SECRET |
OAuth client secret | ✅ |
KOOMPI_REDIRECT_URI |
OAuth callback URL | ✅ |
PORT |
Server port | 3000 |
DASHBOARD_URL |
Dashboard URL | Optional |
See Environment Variables for complete reference.
- 🔐 KOOMPI ID OAuth — Authentication setup
- ☁️ Cloudflare Setup — DNS and SSL
- 🗄️ MongoDB Setup — Database configuration
| Category | Guides |
|---|---|
| Getting Started | Quick Start · Architecture |
| Deployment | Self-Hosting · Terraform · Ansible · Docker |
| Configuration | Environment · OAuth · Cloudflare · MongoDB |
| CLI | Installation · Commands |
jrok/
├── src/ # Server source code (Bun/TypeScript)
│ ├── handlers/ # HTTP & WebSocket handlers
│ ├── services/ # Business logic
│ ├── types/ # TypeScript types
│ └── utils/ # Utilities
├── cli/ # CLI client (Node.js/TypeScript)
├── dashboard/ # React dashboard (Vite)
├── ansible/ # Ansible playbooks & roles
├── docs/ # Documentation
├── scripts/ # Deployment scripts
│ └── deploy.sh # Automated deployment
├── jrok.tf # Terraform configuration
└── docker-compose.yml # Docker configuration
| Component | Technology |
|---|---|
| Server | Bun (TypeScript) |
| Database | MongoDB (Atlas) |
| Web Server | Nginx |
| SSL | Let's Encrypt + Certbot |
| DNS | Cloudflare |
| Dashboard | React + Vite + Tailwind |
| CLI | Node.js + TypeScript |
| IaC | Terraform + Ansible |
Contributions are welcome!
# Clone repository
git clone https://github.com/koompi/jrok.git
cd jrok
# Install dependencies
bun install
# Start development server
bun run dev
# Run CLI in development
cd cli && bun run src/index.ts --helpApache License 2.0 — see LICENSE for details.
Built with ❤️ by KOOMPI
