Expose your local apps to the world—securely, instantly, and with zero hassle.
Moley is the easiest way to share your local development services using Cloudflare Tunnels and your own custom domains. Moley automates everything for you, so you can focus on building, not configuring.
- Zero Infra: No reverse proxies, load balancers, or additional services needed
- Instant Setup: Get your local app online in minutes with a single command
- Custom Domains: Use your own domain names for a professional presentation
- Secure by Default: Uses Cloudflare's enterprise-grade security and DDoS protection
- Automatic Recovery: Robust state management with crash recovery and cleanup
Automated Setup: Moley handles tunnel creation, DNS configuration, and ingress routing automatically. Streamlined Operations: Single command deployment with automatic subdomain management. Resource Management: Proper cleanup on tunnel termination with crash recovery. Multi-App Support: Expose multiple local applications simultaneously. Professional Presentation: Use your own domain names for a polished appearance.
Zero Additional Infrastructure: No need for reverse proxies, load balancers, or additional services. Centralized Configuration: All settings managed through a single, validated configuration file. Operational Clarity: Structured logging provides clear operational insights and debugging information.
Unlike traditional approaches that require setting up reverse proxies like Nginx Proxy Manager, Moley automatically creates and manages DNS records via the Cloudflare API. This means no additional infrastructure setup—just configure your local services and let Moley handle the rest.
Approach | Infrastructure Required | DNS Management | Setup Complexity |
---|---|---|---|
Moley | None | Automatic via API | Single command |
cloudflared + Nginx | Nginx Proxy Manager | Manual dashboard | Multiple services |
Manual Cloudflare | None | Manual dashboard | Complex config |
Moley eliminates the need for reverse proxies while providing automated DNS management. Simplicity first.
- Cloudflared installed and authenticated
- A Cloudflare account with a custom domain
- Go 1.23+ (for building from source)
# Install via Homebrew
brew install --cask stupside/tap/moley
# Or download from releases
# Or build from source (see Development section)
# Authenticate with Cloudflare
cloudflared tunnel login
# Set your Cloudflare API token
moley config set --cloudflare.token="your-api-token"
# Create a new tunnel configuration
moley tunnel init
Edit the generated moley.yml
file:
tunnel:
id: "a-unique-tunnel-id"
ingress:
zone: "yourdomain.com"
apps:
- target:
port: 8080
hostname: "localhost"
expose:
subdomain: "api"
- target:
port: 3000
hostname: "localhost"
expose:
subdomain: "web"
# Start the tunnel service
moley tunnel run
# Stop when done: press Ctrl-C (Moley will clean up gracefully)
Your apps are now accessible at:
https://api.yourdomain.com
→localhost:8080
https://web.yourdomain.com
→localhost:3000
Moley uses Hexagonal Architecture (Ports & Adapters) to keep business logic separate from external dependencies, making it maintainable and testable:
- Domain Layer: Business entities (
Tunnel
,Ingress
,AppConfig
) with validation - Application Layer: Orchestration services that coordinate resource lifecycle
- Ports: Interfaces defining contracts (
TunnelService
,DNSService
) - Adapters: Cloudflare-specific implementations of the ports
- Framework: Resource management with state tracking and idempotent operations
- Resource Management Framework: Declarative resource lifecycle with
Up
/Down
/Status
operations - State Persistence:
moley.lock
file tracks deployed resources for crash recovery - Idempotent Operations: Resources are only created/destroyed when needed
- Configuration System: Global config (
~/.moley/config.yml
) + local config (moley.yml
) - Dry-Run Support: Test configurations without making real changes
- Graceful Shutdown: Proper cleanup on termination signals
┌─────────────────────────────────────────────────────────────────┐
│ CLI Layer │
│ moley tunnel run | moley tunnel init | moley config set │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────────┐
│ Application Layer │
│ Tunnel Service (orchestrates resources) │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────────┐
│ Resource Framework │
│ Resource Manager -> Resource Handlers -> Resource Lock │
│ ┌──────────────┐ ┌─────────────────┐ ┌──────────────────┐ │
│ │ Tunnel Create│ │ Tunnel Config │ │ DNS Records │ │
│ │ Handler │ │ Handler │ │ Handler │ │
│ └──────────────┘ └─────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────────┐
│ Ports (Interfaces) │
│ TunnelService │ DNSService │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────────┐
│ Cloudflare Adapters │
│ tunnel.go (cloudflared CLI) │ dns.go (Cloudflare API) │
└─────────────────────────────────────────────────────────────────┘
- Parse Configuration: Load tunnel and ingress configuration from
moley.yml
- Create Resources: Generate resource specifications (tunnel, config, DNS records)
- Diff Management: Compare desired state vs. current state in
moley.lock
- Sequential Operations: Execute resource operations in dependency order
- State Persistence: Update lock file with actual resource states
- Graceful Cleanup: Reverse-order teardown on shutdown
Moley uses two configuration files:
- Global Configuration (
~/.moley/config.yml
): Contains sensitive data like API tokens - Local Configuration (
moley.yml
): Project-specific tunnel and ingress settings
Field | Type | Description | Required | Validation |
---|---|---|---|---|
tunnel.id |
string | Unique identifier for the tunnel | Yes | Generated UUID |
ingress.zone |
string | The DNS zone (your domain) to use for the tunnel | Yes | Valid domain format |
ingress.apps |
array | Array of application configurations | Yes | At least one app |
apps[].target.port |
integer | Local service port | Yes | 1-65535 |
apps[].target.hostname |
string | Local hostname (typically localhost ) |
Yes | Valid hostname/IP |
apps[].expose.subdomain |
string | Public subdomain (e.g., api becomes api.yourdomain.com ) |
Yes | Alphanumeric + hyphens |
cloudflare:
token: "your-cloudflare-api-token"
tunnel:
id: "1663c83d-8801-424f-b060-734882126071"
ingress:
zone: "example.com"
apps:
- target:
port: 8080
hostname: "localhost"
expose:
subdomain: "api"
- target:
port: 3000
hostname: "localhost"
expose:
subdomain: "web"
Moley creates a moley.lock
file that tracks deployed resources:
{
"resources": {
"hash1": {
"handler": "tunnel-create",
"payload": "..."
},
"hash2": {
"handler": "dns-record",
"payload": "..."
}
}
}
This lockfile enables:
- Crash Recovery: Resume operations after interruption
- Incremental Updates: Only deploy changes, not everything
- Clean Teardown: Remove only what was actually created
# Show version and build information
moley --version
moley info
# Adjust logging level
moley --log-level=debug tunnel run
# Set Cloudflare API token (stored in ~/.moley/config.yml)
moley config set --cloudflare.token="your-token"
# Initialize a new tunnel configuration (creates moley.yml)
moley tunnel init
# Start the tunnel service (uses moley.yml by default)
moley tunnel run
# Use a custom configuration file
moley tunnel run --config custom-config.yml
Command | Description |
---|---|
moley info |
Display detailed build and configuration information |
moley config set |
Set global configuration values (API tokens, etc.) |
moley tunnel init |
Create a new tunnel configuration file with defaults |
moley tunnel run |
Deploy and run the tunnel with current configuration |
moley tunnel run --config FILE |
Deploy and run with a custom configuration file |
moley tunnel run --dry-run |
Validate configuration without creating resources |
# Run with dry-run mode (no actual resources created)
moley tunnel run --dry-run
# Use custom config file for different environments
moley tunnel run --config production.yml
# Use Task for development workflows
task go:test # Run tests
task go:lint # Run linting
task go:build # Build binary
# Clone the repository
git clone https://github.com/stupside/moley.git
cd moley
# Install dependencies
go mod download
# Build the binary
go build -o moley .
# Or use Task for development
task go:build
# Run moley in Docker
task docker:moley -- tunnel run
# Run cloudflared commands in Docker
task docker:cloudflared -- tunnel list
- API Token Management: Never commit API tokens to version control
- Configuration Security: Local configuration files contain sensitive data
- Network Security: All traffic encrypted via Cloudflare tunnels
- Access Control: Regular token rotation recommended
See SECURITY.md for detailed security guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.