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
| Method | Setup Time | Custom URLs | Persistent | Multiple Apps | Automatic |
|---|---|---|---|---|---|
| ngrok | 30 sec | ❌ (Pro) | ❌ | ❌ | ✅ |
| localtunnel | 15 sec | ❌ | ❌ | ❌ | ✅ |
| Manual Cloudflare | 15 min | ✅ | ✅ | ✅ | ❌ |
| Nginx Proxy Manager | 30 min | ✅ | ✅ | ✅ | ❌ |
| Moley | 2 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.ymledit +./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.





