Skip to main content

What moley can do

Moley is a thin, opinionated orchestrator over three Cloudflare APIs — Tunnels, DNS, and Access. Everything you need lives in a single moley.yml; everything moley does is reversible.

Tunnel lifecycle

One command provisions the tunnel, routes DNS, creates Access apps, and starts cloudflared. Another tears it all back down.

CommandWhat it does
moley tunnel initGenerates a starter moley.yml in the current directory
moley tunnel runCreates the tunnel, sets up DNS and Access, then starts cloudflared in the foreground
moley tunnel run --detachSame, but detaches — moley stays running under your shell
moley tunnel stopCleans up every resource moley created for this config

By default, tunnels and DNS records are deleted when you stop. Set tunnel.persistent: true to keep them (useful if you want a stable URL across runs).

DNS routing modes

Pick per-project based on how often your apps change.

  • mode: subdomain — one CNAME per app (api.example.com, web.example.com). Production-flavored; each app gets its own record proxied to the tunnel.
  • mode: wildcard — a single *.example.com CNAME. cloudflared routes by hostname. Ideal for dev when you're adding and removing apps constantly — no DNS churn.

See Configuration → Ingress Mode.

Protocol support

Each app target declares its protocol: http, https, or tcp. TCP opens the door to databases, SSH, and custom protocols through the same tunnel.

Cloudflare Access integration

Add an access: block to any app and moley creates the Access Application, wires up identity providers (GitHub, Google Workspace, one-time PIN, etc.), and attaches any policies you reference. Pure pass-through: every field not named providers is forwarded to the Cloudflare Access API as-is, so anything the API supports, moley supports.

See Access.

Reusable, account-level policies

Policies live at the top level of moley.yml under access.policies — not buried inside each app. Name them once, reference by name from as many apps as you want. Moley creates them as account-level Access policies, which means:

  • Swap a policy's rules in one place → every app using it updates.
  • Policies outlive a single tunnel, so reconnection doesn't rebuild them.
  • Service-token-only policies (decision: non_identity) work for machine-to-machine calls without any browser flow.

See Policies.

Reconciliation and change detection

Moley hashes each resource's desired input. If nothing changed between runs, the resource is left alone. If the input changed, only the diff is applied. This keeps re-runs cheap and avoids flapping DNS or re-issuing Access apps needlessly.

Lock file and orphan cleanup

Every run writes a moley.lock alongside moley.yml. The lock records exactly which tunnel, DNS records, and Access apps belong to this project. On tunnel stop:

  1. Moley reads the lock.
  2. Deletes each resource in dependency order (apps → DNS → tunnel).
  3. Removes the lock.

If a run crashes or the lock goes missing, moley can rediscover the resources from Cloudflare by name and clean them up anyway.

Dry-run

Prepend --dry-run to any tunnel command to simulate it. No resources are created, deleted, or modified — moley just logs what it would do.

moley tunnel --dry-run run
moley tunnel --dry-run stop

Great for CI previews and for checking a new config before committing to it.

Structured logging

Log output uses zerolog with selectable levels via --log-level:

trace · debug · info (default) · warn · error · fatal · panic · disabled

Trace and debug are verbose by design — use them when debugging Cloudflare API responses or tunnel lifecycle issues.

Environment variable overrides

Every key in moley.yml and the global config can be set via env vars. Useful for CI, Docker, and ephemeral shells.

  • Global keys: MOLEY_* (e.g. MOLEY_CLOUDFLARE__TOKEN)
  • Tunnel keys: MOLEY_TUNNEL_* (e.g. MOLEY_TUNNEL_INGRESS__ZONE)
  • Array indexes: __N__ where N is 0-based

See Configuration → Environment variables.

Container image

An official image is published to ghcr.io/stupside/moley:latest with cloudflared bundled. See Docker for a turnkey Compose setup.

What moley does not do

  • No built-in web UI — it's a CLI, by design.
  • No load balancing across multiple origins per hostname — one tunnel target per app.
  • No non-Cloudflare backends. Moley is Cloudflare-shaped on purpose.