Moley: The Tool That Makes Cloudflare Tunnels Finally Usable (and Why We Needed It)

The Problem We All Have (But Solve Poorly)

As a DevOps Manager, I spend more time than I should configuring ways for the team to show their development work. Client demos, webhooks for testing, temporary APIs for integrations… we always need to expose localhost to the world.

Traditional options are a pain:

  • ngrok: Works, but ugly URLs, limits on free plan, and every restart generates a new URL
  • localtunnel: Unstable, URLs that expire, and often blocked by corporate firewalls
  • SSH tunneling: Requires your own servers, manual configuration, and networking knowledge
  • Manual Cloudflare Tunnels: Powerful but… God, the manual configuration is hellish

And then I discovered Moley.

Moley: Cloudflare Tunnels Without the Suffering

Moley is basically “Cloudflare Tunnels for humans”. It takes all the power of Cloudflare tunnels (free, stable, with your own domain) and eliminates all the configuration friction.

# moley.yml - This is ALL you need to configure
zone: "mydomain.com"
apps:
  - target:
      hostname: "localhost"
      port: 3000
    expose:
      subdomain: "app-dev"
  - target:
      hostname: "localhost"
      port: 8080
    expose:
      subdomain: "api-staging"

One command, multiple services, professional domains:

./moley tunnel run
# ✅ app-dev.mydomain.com → localhost:3000
# ✅ api-staging.mydomain.com → localhost:8080

And when you’re done, Ctrl+C and everything cleans up automatically. DNS records, tunnel config, certificates… disappears as if it never existed.

What Are Cloudflare Tunnels? (The Necessary Context)

To understand why Moley is brilliant, we need to understand what it solves.

Cloudflare Tunnels is a free service that creates secure outbound connections from your machine to Cloudflare’s network, without opening ports in your firewall:

[Your Local App] ←→ [cloudflared] ←→ [Cloudflare Edge] ←→ [Internet]
     :3000              tunnel              HTTPS            users

Benefits vs. alternatives:

  • Free (unlike ngrok Pro)
  • Your own domain (app.yourcompany.com vs. abc123.ngrok.io)
  • Stable (same URL always, doesn’t expire)
  • Secure (automatic HTTPS, Cloudflare DDoS protection)
  • No open ports (all outbound, firewall-friendly)
  • Performance (Cloudflare’s global network)

The traditional problem:

# The manual way (that nobody wants to do)
cloudflared tunnel login
cloudflared tunnel create my-tunnel
cloudflared tunnel route dns my-tunnel app.mydomain.com
# Edit config.yml manually
# Configure ingress rules
# Manage credentials
# Clean up after...

It’s powerful, but too manual for iterative development.

The Comparison That Matters

MethodSetup TimeCustom URLsPersistentMultiple AppsAutomatic
ngrok30 sec❌ (Pro)
localtunnel15 sec
Manual Cloudflare15 min
Nginx Proxy Manager30 min
Moley2 min

Moley is the sweet spot: All the power of Cloudflare with the simplicity of ngrok.

Real Use Cases (From the Trenches)

1. Client Demos with Professional Domain

# Instead of: "Connect to https://f4b2c1d.ngrok.io"
# Now: "The demo is at https://demo-client.yourcompany.com"

Impact: Clients trust professional URLs more. I’ve seen deals close faster when the demo uses the company’s domain.

2. Webhooks for Testing

# GitHub webhooks, Stripe webhooks, etc.
apps:
  - target:
      hostname: "localhost"
      port: 4000
    expose:
      subdomain: "webhooks-test"

Advantage: Stable URL you can configure once in all external services.

3. APIs for Temporary Integrations

apps:
  - target:
      hostname: "localhost"
      port: 8080
    expose:
      subdomain: "api-integration-partner-x"

Benefit: The partner can do their integration against a professional URL that works 24/7.

4. Multiple Environments Simultaneously

# One developer working on 3 parallel features
zone: "dev.mycompany.com"
apps:
  - target:
      port: 3001
    expose:
      subdomain: "feature-auth"
  - target:
      port: 3002
    expose:
      subdomain: "feature-payments"
  - target:
      port: 3003
    expose:
      subdomain: "feature-dashboard"

5. Collaboration in Remote Teams

# Developer A in Barcelona
moley tunnel run  # → feature-x.dev.company.com

# Developer B in Mexico can access immediately
curl https://feature-x.dev.company.com/api/status

Practical Implementation: From Zero to Running

Initial setup (once):

# 1. Install cloudflared
brew install cloudflare/cloudflare/cloudflared  # macOS
# Linux: wget + dpkg (see docs)

# 2. Authenticate with Cloudflare
cloudflared tunnel login

# 3. Install Moley
git clone https://github.com/stupside/moley.git
cd moley
make build

# 4. Configure API token
./moley config --cloudflare.token="your-api-token"

Daily use:

# 1. Create initial config
./moley tunnel init

# 2. Edit moley.yml according to your services
# 3. Run
./moley tunnel run

Config example for typical stack:

zone: "mycompany.dev"
apps:
  - target:
      hostname: "localhost"
      port: 3000        # React frontend
    expose:
      subdomain: "app"
  - target:
      hostname: "localhost"
      port: 8080        # API backend
    expose:
      subdomain: "api"
  - target:
      hostname: "localhost"
      port: 5432        # PostgreSQL (TCP tunnel)
    expose:
      subdomain: "db"

What Fascinates Me Technically

1. Automatic DNS Management

Moley uses Cloudflare’s API to create/delete DNS records on-demand:

// Pseudocode of what Moley does internally
func createDNSRecord(subdomain, zone string) {
    cloudflare.CreateRecord(DNSRecord{
        Type: "CNAME",
        Name: subdomain + "." + zone,
        Content: tunnelID + ".cfargotunnel.com"
    })
}

No more manual configuration in Cloudflare dashboard.

2. Automatic Cleanup

When you Ctrl+C, Moley:

  • ✅ Deletes DNS records
  • ✅ Gracefully terminates the tunnel
  • ✅ Cleans up temporary files
  • ✅ Revokes tunnel config

“Leave no trace” - exactly what you need in development.

3. Centralized and Validated Configuration

./moley --help
# Built-in config validation
# Structured logging
# Intelligent error handling

4. Multiple Apps in One Tunnel

Instead of one tunnel per service (complex), Moley configures intelligent ingress rules:

# Internally generates:
ingress:
  - hostname: app.mycompany.dev
    service: http://localhost:3000
  - hostname: api.mycompany.dev
    service: http://localhost:8080
  - service: http_status:404  # catch-all

Advanced Use Cases with Cloudflare Tunnels

TCP Tunnels for Databases

# Expose development PostgreSQL
apps:
  - target:
      hostname: "localhost"
      port: 5432
    expose:
      subdomain: "db-dev"
      # Internally uses TCP tunneling

Now your partner can connect directly:

psql -h db-dev.yourcompany.com -U postgres

SSH Tunneling for Servers

apps:
  - target:
      hostname: "localhost"
      port: 22
    expose:
      subdomain: "ssh-server"

SSH access without opening ports:

ssh user@ssh-server.yourcompany.com

RDP for Windows Servers

apps:
  - target:
      hostname: "192.168.1.100"
      port: 3389
    expose:
      subdomain: "windows-dev"

Monitoring and Logging

All tunnels appear in Cloudflare dashboard with metrics:

  • ✅ Requests per second
  • ✅ Bandwidth usage
  • ✅ Error rates
  • ✅ Geographic distribution

Security Considerations (Important)

Positive points:

  • Encrypted traffic (end-to-end TLS)
  • No exposed ports (all outbound)
  • Cloudflare DDoS protection
  • Token authentication (not passwords)

Points of attention:

  • ⚠️ Internal services publicly accessible (configure authentication)
  • ⚠️ API tokens are powerful (minimum necessary scope)
  • ⚠️ Logs in Cloudflare (data privacy considerations)

Best practices:

# Use specific subdomains, not wildcards
subdomain: "feature-123-dev"  # ✅
subdomain: "*"               # ❌

# Limit ports
port: 3000  # ✅ Specific app
port: 22    # ⚠️ Only if you need remote SSH

Add authentication in your app if you expose sensitive data:

// Simple auth middleware
app.use((req, res, next) => {
    if (process.env.NODE_ENV === 'tunnel') {
        // Require API key when on public tunnel
        if (!req.headers['x-api-key']) {
            return res.status(401).send('Auth required');
        }
    }
    next();
});

When NOT to Use Moley/Tunnels

Production Workloads:

For production, use dedicated infrastructure. Tunnels are perfect for development/staging.

High-Bandwidth Applications:

Cloudflare tunnels add minimal but perceptible latency. For video streaming or gaming, better direct connection.

Apps Handling Super Sensitive Data:

If you work with PHI, PCI, or classified data, consider if exposing via public tunnel meets compliance.

Debugging Network Issues:

Tunnels add a layer of abstraction. For network debugging, sometimes you need direct connection.

My Practical Experience

Before Moley (pain points):

  • 15 minutes manual setup per demo
  • URLs that expire in the middle of presentations
  • Manually configuring DNS records in Cloudflare
  • Cleaning up old tunnels by hand

With Moley (happiness):

  • 2 minutes of moley.yml edit + ./moley tunnel run
  • Stable URLs that always work
  • Automatic cleanup
  • Multiple simultaneous apps without conflicts

Clear ROI: From 15 min → 2 min per deployment. With 10+ demos per month, that’s 2+ hours saved.

But more important: less friction = more iterations = better product.

Alternatives and Competition

Bore (similar concept):

bore local 3000 --to bore.pub
  • ✅ Simple
  • ❌ Public URLs, not your own domain
  • ❌ Not persistent

Telebit:

  • ✅ Own domain
  • ❌ More complex configuration
  • ❌ Lower adoption

Pinggy:

  • ✅ Simple setup
  • ❌ Freemium model
  • ❌ URLs not customizable in free tier

Moley stands out for the combination: Simplicity + own domain + Cloudflare infrastructure + open source.

The Roadmap I’d Like to See

Features I would add:

  • Stack templates: moley init --template=next-js
  • Team sharing: moley share --with=team@company.com
  • Load balancing: Multiple instances of the same service
  • Custom headers: Automatically add auth headers
  • CI/CD integration: Deploy tunnels from GitHub Actions

Improved monitoring:

moley status
# ✅ app.mydomain.com → localhost:3000 (healthy)
# ⚠️ api.mydomain.com → localhost:8080 (down)

Conclusion: Why This Matters

As someone who manages infrastructure daily, Moley solves a real problem we all have. It’s not revolutionary technology, it’s simply good engineering: takes something complex (Cloudflare Tunnels) and makes it simple without sacrificing power.

The real value isn’t technical, it’s organizational:

  • More productive developers (less setup time)
  • More professional demos (own domain)
  • Easier collaboration (stable URLs)
  • Less dependency on DevOps for temporary setups

In a world where infrastructure costs are going down but developer time costs are going up, tools like Moley optimize the right thing.


Are you going to try it? What do you currently use to expose localhost? Do you think it’s worth the switch from ngrok?

My prediction: Moley is the type of tool that becomes muscle memory. Once you try it, it’s hard to go back to manually configuring tunnels.

Next step: Download Moley, try it on a real project, and see if it saves you the time it saves me.

PS: If you work at companies that frequently do development demos, Moley can be a game-changer. The difference between “connect to https://abc123.ngrok.io” and “the demo is at https://demo.your-company.com” is… notable.