Skip to content

Tunnel Quick Reference

Tunnel Quick Reference

Quick commands and configurations for ngrok tunnel setup.


Installation

Terminal window
# macOS
brew install ngrok/ngrok/ngrok
# Linux (Ubuntu/Debian)
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | \
sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && \
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | \
sudo tee /etc/apt/sources.list.d/ngrok.list && \
sudo apt update && sudo apt install ngrok
# Windows
choco install ngrok
# Verify
ngrok version

One-Time Setup

Terminal window
# 1. Get authtoken from https://dashboard.ngrok.com/get-started/your-authtoken
# 2. Configure authtoken
ngrok config add-authtoken YOUR_TOKEN_HERE
# 3. Verify
cat ~/.config/ngrok/ngrok.yml | grep authtoken

Basic Commands

Terminal window
# Start tunnel on port 8000
ngrok http 8000
# Start tunnel with specific region
ngrok http 8000 --region us # Options: us, eu, ap, au, sa, jp, in
# Start tunnel with custom subdomain (paid plan)
ngrok http 8000 --subdomain my-api-dev
# Start tunnel with custom domain (paid plan)
ngrok http 8000 --hostname api.yourdomain.com
# Start tunnel with basic auth (paid plan)
ngrok http 8000 --basic-auth "username:password"
# Start specific named tunnel
ngrok start python-saas
# Start multiple named tunnels (paid plan)
ngrok start python-saas react-client rails-api
# Check version
ngrok version
# View help
ngrok http --help

Process Management

Terminal window
# Check if ngrok is running
ps aux | grep ngrok
# Stop all ngrok processes
pkill ngrok
# Stop specific ngrok process
kill <PID>
# Run in background
ngrok http 8000 > /dev/null &
# View ngrok processes with PIDs
pgrep -l ngrok

Configuration File

Location: ~/.config/ngrok/ngrok.yml

Basic Config

version: "2"
authtoken: YOUR_TOKEN_HERE
tunnels:
python-saas:
proto: http
addr: 8000
react-client:
proto: http
addr: 5173
rails-api:
proto: http
addr: 3000

Advanced Config

version: "2"
authtoken: YOUR_TOKEN_HERE
region: us
console_ui: true
log_level: info
log_format: json
log: /var/log/ngrok.log
tunnels:
python-saas:
proto: http
addr: 8000
inspect: true
bind_tls: true
host_header: rewrite
subdomain: my-api-dev # Paid plan
# IP restrictions (paid plan)
ip_restriction:
allow_cidrs:
- 203.0.113.0/24
# Basic auth (paid plan)
basic_auth:
- "admin:secretpass"

Get Tunnel URL

From Terminal Output

Terminal window
ngrok http 8000
# Look for "Forwarding" line:
# Forwarding https://abc123.ngrok-free.app -> http://localhost:8000

Using API

Terminal window
# Get tunnel info as JSON
curl -s http://localhost:4040/api/tunnels
# Extract just the URL
curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url'
# Get HTTPS URL only
curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[] | select(.proto=="https") | .public_url'

Web Inspection UI

Terminal window
# Access ngrok Web UI (when tunnel is running)
open http://127.0.0.1:4040
# Or in browser
curl http://127.0.0.1:4040

Features:

  • View all requests/responses
  • Replay requests
  • Edit and replay modified requests
  • Filter by path, status, method
  • View timing and metrics

Common Debugging

Check Local Server

Terminal window
# Verify server is running on port
lsof -i :8000
# Test endpoint locally
curl http://localhost:8000/health
# Check what's listening on port
netstat -an | grep 8000

Check ngrok Status

Terminal window
# View ngrok logs (in terminal where ngrok is running)
# Look for error messages
# Check ngrok service status
curl -s https://status.ngrok.com/api/v2/status.json | jq .
# Test tunnel externally
curl https://YOUR_TUNNEL_URL.ngrok-free.app/health

Reset Configuration

Terminal window
# Remove config file
rm ~/.config/ngrok/ngrok.yml
# Re-add authtoken
ngrok config add-authtoken YOUR_NEW_TOKEN
# Test
ngrok http 8000

Webhook URL Formats

PactaPay Webhook

https://YOUR_SUBDOMAIN.ngrok-free.app/api/commerce/webhooks/pactapay

Shopify Webhook

https://YOUR_SUBDOMAIN.ngrok-free.app/api/commerce/webhooks/shopify

GitHub Webhook

https://YOUR_SUBDOMAIN.ngrok-free.app/webhooks/github

Generic Format

https://YOUR_SUBDOMAIN.ngrok-free.app/your/endpoint/path

Docker Integration

Run ngrok Outside Docker

Terminal window
# Start Docker services
docker-compose up -d
# Check which port is exposed
docker-compose ps
# Start ngrok pointing to exposed port
ngrok http 8000

Run ngrok Inside Docker

docker-compose.yml
services:
api:
build: ./templates/python-saas
ports:
- "8000:8000"
ngrok:
image: ngrok/ngrok:alpine
command: http api:8000
environment:
- NGROK_AUTHTOKEN=${NGROK_AUTHTOKEN}
ports:
- "4040:4040"
Terminal window
# Get tunnel URL from Docker
docker exec -it <ngrok-container> sh -c \
"wget -qO- http://localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url'"
# Or use host curl
curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url'

Environment Variables

Terminal window
# Set authtoken via environment (alternative to config file)
export NGROK_AUTHTOKEN=YOUR_TOKEN_HERE
ngrok http 8000
# Set region
export NGROK_REGION=us
ngrok http 8000
# Disable inspect UI
export NGROK_INSPECT=false
ngrok http 8000

Troubleshooting Quick Checks

Connection Refused

Terminal window
# Check server is running
lsof -i :8000
# Start server if not running
cd templates/python-saas && python src/ui/main.py &
# Then try ngrok again
ngrok http 8000

Invalid Authtoken

Terminal window
# Reset config
rm ~/.config/ngrok/ngrok.yml
ngrok config add-authtoken NEW_TOKEN_HERE
ngrok http 8000

Account Limit Reached

Terminal window
# Kill all ngrok processes
pkill ngrok
# Verify no processes running
ps aux | grep ngrok
# Start new tunnel
ngrok http 8000

Webhook Returns 404

Terminal window
# Verify endpoint exists locally
curl http://localhost:8000/api/commerce/webhooks/pactapay
# Check route in code
cd templates/python-saas
grep -r "webhooks/pactapay" src/
# Ensure path matches exactly

Webhook Returns 401

Terminal window
# Check webhook secret is configured
cat .env | grep WEBHOOK_SECRET
# Verify secret matches provider dashboard
# PactaPay: https://dashboard.pactapay.com/webhooks
# Reload environment
source .env && python src/ui/main.py

Useful Scripts

Auto-Extract Tunnel URL

get_ngrok_url.sh
#!/bin/bash
while true; do
URL=$(curl -s http://localhost:4040/api/tunnels 2>/dev/null | jq -r '.tunnels[0].public_url' 2>/dev/null)
if [ "$URL" != "null" ] && [ -n "$URL" ]; then
echo $URL
break
fi
sleep 1
done

Usage:

Terminal window
chmod +x get_ngrok_url.sh
./get_ngrok_url.sh

Auto-Configure Webhook

auto_webhook_pactapay.sh
#!/bin/bash
# Get ngrok URL
NGROK_URL=$(curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url')
if [ -z "$NGROK_URL" ] || [ "$NGROK_URL" == "null" ]; then
echo "Error: ngrok not running or tunnel not found"
exit 1
fi
# Construct webhook URL
WEBHOOK_URL="${NGROK_URL}/api/commerce/webhooks/pactapay"
echo "Webhook URL: $WEBHOOK_URL"
echo ""
echo "Configure in PactaPay Dashboard:"
echo "https://dashboard.pactapay.com/webhooks"

Usage:

Terminal window
chmod +x auto_webhook_pactapay.sh
./auto_webhook_pactapay.sh

Free Plan Limits

  • Tunnels: 1 simultaneous
  • Rate: 40 requests/minute
  • URLs: Random (changes on restart)
  • Connections: Up to 10 per minute
  • Tunnel lifetime: No limit (but URL changes)

Upgrade for:

  • Multiple simultaneous tunnels
  • Custom subdomains
  • Reserved domains
  • IP restrictions
  • Basic auth

Pricing: https://ngrok.com/pricing


Keyboard Shortcuts (in ngrok terminal)

  • Ctrl+C: Stop tunnel
  • No other interactive commands (ngrok runs in foreground)

Common Ports

ServiceDefault PortTunnel Command
FastAPI / Python SaaS8000ngrok http 8000
React / Vite5173ngrok http 5173
Rails API3000ngrok http 3000
Rails UI Kit3001ngrok http 3001
Data Pipeline (dbt docs)8081ngrok http 8081
Static Landing (Astro)3002ngrok http 3002
PostgreSQL5432ngrok tcp 5432
Redis6379ngrok tcp 6379

Alternative Tunneling Tools

ToolFree TierCustom DomainsOpen Source
ngrok1 tunnel, 40 req/minPaidNo
Cloudflare TunnelUnlimitedYesNo
localtunnelUnlimitedNoYes
serveoUnlimitedNoYes
Tailscale FunnelYesYesNo

Additional Resources


Last Updated: February 28, 2026 Maintainer: Seed & Source Team