Free Tunnel Services for LPI

To test webhooks from external services, you'll need to expose your local LPI instance to the internet. Here are several free options that work great with LPI.

Cloudflare Tunnel (cloudflared)

Installation

# macOS
brew install cloudflared

# Linux
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb

# Windows
# Download from https://github.com/cloudflare/cloudflared/releases

Usage with LPI

# Start LPI first
lpi --proxy 8091  --target {you_app_local_port:8080}

# In another terminal, start the tunnel
cloudflared tunnel --url http://localhost:8091

You'll get a URL like https://random-name.trycloudflare.com - use this as your webhook endpoint.

Using Custom Domains (DNS on Cloudflare)

If your DNS is managed on Cloudflare, you can use your own domain with subdomains for persistent tunnels:

# First time setup - authenticate with Cloudflare
cloudflared tunnel login

# Create a named tunnel
cloudflared tunnel create lpi-dev

# Route it to a subdomain
cloudflared tunnel route dns lpi-dev t1.example.com

# Run the tunnel
cloudflared tunnel run --url http://localhost:8091 lpi-dev

Now you can use https://t1.example.com as your webhook endpoint! Create multiple tunnels for different environments:

  • t1.example.com for development
  • t2.example.com for staging
  • webhook.example.com for production testing

Pros

  • No account required for quick testing (random URLs)
  • Fast and reliable
  • HTTPS by default
  • No time limits
  • Custom domains available if DNS is on Cloudflare

Cons

  • Random URL changes each time (unless using custom domain)
  • Custom domains require Cloudflare DNS management

ngrok

How It Works

ngrok creates secure tunnels to localhost and provides a web interface for inspecting HTTP traffic. It's the most popular tunneling service with both free and paid tiers.

Installation

# macOS
brew install ngrok/ngrok/ngrok

# Linux/Windows - Download from https://ngrok.com/download
# Or use npm
npm install -g @ngrok/ngrok

Setup

# Sign up for free account at https://ngrok.com
# Get your authtoken from the dashboard
ngrok config add-authtoken YOUR_AUTHTOKEN

Usage with LPI

# Start LPI
lpi --proxy 8091  --target {you_app_local_port:8080}

# Start ngrok tunnel
ngrok http 8091

You'll get a URL like https://abc123.ngrok.io - use this as your webhook endpoint.

Advanced Features

# Custom subdomain (paid plans)
ngrok http 8091 --subdomain=myapp

# Basic auth protection
ngrok http 8091 --basic-auth="username:password"

# Custom domain (paid plans)
ngrok http 8091 --hostname=webhook.yourdomain.com

Pros

  • Most popular and well-documented
  • Built-in request inspection (3-day history)
  • Authentication and security features
  • Reliable infrastructure
  • Custom domains and subdomains available
  • Mobile apps for monitoring

Cons

  • Requires account signup
  • Free tier has connection limits
  • Inspection history limited to 3 days
  • Can be expensive for heavy usage
  • Some corporate firewalls block ngrok domains

Note: Both ngrok and LPI provide request inspection. ngrok's inspection is limited to 3 days, while LPI stores requests locally for longer-term analysis and provides additional webhook testing features.

SSH Tunneling

If you have access to a VPS or remote server with SSH:

Setup

# Start LPI
lpi --proxy 8091  --target {you_app_local_port:8080}

# Create SSH tunnel (maps remote port to local port)
ssh -R 8090:localhost:8091 [email protected]

Web Server Configuration

For subdomain setup, configure your web server to proxy the tunneled port:

Nginx configuration (/etc/nginx/sites-available/tunnel):

server {
    listen 80;
    server_name mytunnel.example.com;

    location / {
        proxy_pass http://localhost:8090;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Apache configuration (/etc/apache2/sites-available/tunnel.conf):

<VirtualHost *:80>
    ServerName mytunnel.example.com
    ProxyPass / http://localhost:8090/
    ProxyPassReverse / http://localhost:8090/
    ProxyPreserveHost On
</VirtualHost>

DNS Setup

Create an A record pointing your subdomain to your VPS:

Type: A
Name: mytunnel
Value: [your-vps-ip-address]
TTL: 300 (or your preferred value)

Pros

  • Completely under your control
  • Use your own domain or subdomain
  • No third-party dependencies

Cons

  • Requires VPS with SSH access
  • Need to configure web server and DNS
  • Manual setup for each subdomain

LocalTunnel

Installation

npm install -g localtunnel

Usage with LPI

# Start LPI
lpi --proxy 8091  --target {you_app_local_port:8080}

# Start LocalTunnel
lt --port 8091

You'll get a URL like https://random.loca.lt

Pros

  • Easy to install via npm
  • Can request custom subdomains
  • Open source

Cons

  • Requires Node.js
  • Shows warning page to visitors
  • Can be slow

Bore

How It Works

Bore creates a TCP tunnel between your local machine and a remote server, bypassing NAT firewalls. When you run bore local 8091 --to bore.pub, it:

  1. Connects to the bore.pub server - Establishes a control connection to coordinate the tunnel
  2. Gets assigned a random port - The server assigns you a public port (e.g., bore.pub:12345)
  3. Forwards traffic - Any requests to bore.pub:12345 get forwarded to your local localhost:8091
  4. Maintains the connection - Keeps the tunnel alive as long as the bore client is running

The public URL will look like: http://bore.pub:12345 (where 12345 is randomly assigned)

Installation

# macOS
brew install bore-cli
# Linux/Windows
cargo install bore-cli

Usage with LPI

# Start LPI
lpi --proxy 8091  --target {you_app_local_port:8080}

# Start Bore tunnel
bore local 8091 --to bore.pub

Self-Hosting (Optional)

If you prefer to run your own bore server:

# On your VPS
bore server

# On your local machine (replace your-server.com with your VPS)
bore local 8091 --to your-server.com

Pros

  • Fast and lightweight
  • Written in Rust
  • Minimal dependencies
  • Can self-host for better reliability

Cons

  • Less well-known
  • Requires Rust/cargo for installation
  • Public bore.pub service occasionally experiences downtime

Stripe CLI

How It Works

The Stripe CLI creates a secure tunnel between Stripe's servers and your local development environment, allowing you to receive real webhook events locally. This is essential for testing payment flows and webhook handling during development.

Installation

# macOS
brew install stripe/stripe-cli/stripe

# Linux/Windows - Download from GitHub releases
# https://github.com/stripe/stripe-cli/releases

Setup

# Login to your Stripe account
stripe login

# This will open a browser to authenticate with Stripe

Usage with LPI

# Start LPI
lpi --proxy 8091  --target {you_app_local_port:8080}

# Forward Stripe webhooks to your local endpoint
stripe listen --forward-to localhost:8091/webhook/stripe

# Or specify events you want to listen for
stripe listen --events payment_intent.succeeded,payment_intent.payment_failed --forward-to localhost:8091/webhook/stripe

Testing Webhooks

# Trigger test events to verify your webhook handling
stripe trigger payment_intent.succeeded
stripe trigger customer.created
stripe trigger invoice.payment_failed

Webhook Endpoint Signing

The Stripe CLI automatically handles webhook signature verification. Your webhook endpoint will receive a Stripe-Signature header that you should verify in your application:

// Example webhook verification
const signature = req.headers['stripe-signature'];
const event = stripe.webhooks.constructEvent(req.body, signature, process.env.STRIPE_WEBHOOK_SECRET);

Pros

  • Official Stripe tool
  • Handles authentication automatically
  • Real webhook events from Stripe
  • Built-in event triggering for testing
  • Automatic signature verification
  • Free to use

Cons

  • Stripe-specific (only works for Stripe webhooks)
  • Requires Stripe account and authentication
  • Limited to webhook forwarding (not general tunneling)

Getting Your Webhook Secret

When you run stripe listen, it will display your webhook signing secret:

> Ready! Your webhook signing secret is whsec_1234567890abcdef...

Add this to your environment variables for webhook verification.

Comparison Table

ServiceSetup TimeReliabilityCustom DomainsAccount RequiredBest For
Cloudflared2 minExcellentYes (with CF DNS)NoQuick testing, reliable tunnels
ngrok3 minExcellentYes (paid plans)YesPopular choice, built-in inspection
SSH Tunnel5 minExcellentYes (with VPS)VPS accessProduction-like testing, full control
LocalTunnel3 minFairLimitedNoNode.js projects, quick setup
Bore2 minGood*No (random ports)NoLightweight, Rust projects
Stripe CLI3 minExcellentN/AStripe accountStripe webhook testing only

*Note: Bore's public bore.pub service occasionally experiences downtime. Self-hosting improves reliability.

Best Practices

  1. For Quick Testing: Use cloudflared - it's the most reliable and fastest to set up
  2. For Popular Choice: Use ngrok - widely documented with built-in inspection (though limited to 3 days)
  3. For Permanent URLs: Use SSH tunnel with your own VPS for full control
  4. For Stripe Webhooks: Use Stripe CLI for authentic webhook events and automatic signature verification
  5. For Lightweight Setup: Use Bore if you prefer minimal dependencies and Rust-based tools
  6. For Node.js Projects: LocalTunnel integrates well with npm-based workflows
  7. For CI/CD: Consider the paid tier of any service for stability and guaranteed uptime

Security Considerations

  • These tunnels expose your local LPI to the internet
  • Anyone with the URL can send requests to your LPI instance
  • Always close tunnels when not actively testing
  • Consider using webhook signature verification for production webhooks
  • For SSH tunnels: Ensure your VPS is properly secured with key-based authentication and firewall rules
  • For development: Never expose sensitive data, database credentials, or API keys through these tunnels
  • Rate limiting: Consider implementing rate limiting in your local application to prevent abuse
  • IP allowlisting: If possible, restrict tunnel access to known webhook provider IP ranges

Troubleshooting

Tunnel URL Not Working

  1. Ensure LPI is running on the expected port (default: 8091)
  2. Check firewall settings on your local machine
  3. Try accessing http://localhost:8091 directly first
  4. Verify the tunnel service is actually running and connected

Slow Response Times

  • This is normal for free tunnel services
  • Try a different service or upgrade to paid tier
  • Consider using a VPS closer to your webhook source
  • Check your local internet connection stability

Connection Drops

  • Free services may have connection limits or timeouts
  • Restart the tunnel service
  • For critical testing, use multiple tunnel services as backup
  • Consider upgrading to paid tiers for better stability

Service-Specific Issues

ngrok

  • Re-authenticate if getting auth errors: ngrok config add-authtoken YOUR_TOKEN
  • Free tier has connection limits - upgrade if hitting limits
  • Some corporate networks block ngrok - try cloudflared as alternative

Bore

  • If bore.pub is unreachable, try self-hosting a bore server on your VPS
  • Connection refused errors may indicate bore.pub is temporarily down
  • Try different ports if you're getting port allocation errors

Cloudflared

  • Clear browser cache if seeing stale content
  • If random URLs keep changing, set up a named tunnel with custom domain
  • Check Cloudflare status page if connections are failing

LocalTunnel

  • Try a different subdomain if getting rate limited
  • The warning page is normal - click through to access your app
  • Install the latest version if experiencing connection issues

Stripe CLI

  • Re-authenticate with stripe login if webhooks stop working
  • Check your Stripe account permissions if authentication fails
  • Verify your webhook endpoint URL format is correct

SSH Tunnels

  • Ensure SSH key authentication is working properly
  • Check if your VPS firewall allows the tunnel port
  • Verify web server configuration is correctly proxying to localhost

Port Conflicts

  • If port 8091 is busy, start LPI on a different port: ./lpi --port 8092
  • Update your tunnel command to match the new port
  • Check what's using the port: lsof -i :8091 (macOS/Linux) or netstat -ano | findstr :8091 (Windows)

Next Steps

  • Start with cloudflared for immediate testing
  • Set up your webhook provider to send to your tunnel URL
  • Monitor requests in the LPI web interface at http://localhost:3001
  • Test with a simple webhook first (like a GitHub webhook) before moving to payment providers
  • Keep your tunnel logs open in a separate terminal to monitor incoming requests
  • Document your webhook URLs and tunnel setup for team members