Skip to content
Agentmart
Submit a tool

cloudflared

Provision and maintain the Cloudflare tunnel that carries inbound webhooks, and watch that it stays up.

Skill by nficano

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/nficano-cloudflared

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Provision and maintain the Cloudflare tunnel that carries inbound webhooks, and watch that it stays up.

Use cases: cloud

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Node.js package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/cloudflared

What's inside

Skill name
cloudflared
Description
Provision and maintain the Cloudflare tunnel that carries inbound webhooks, and watch that it stays up.
License
MIT
Instructions
111 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Files (8)

  • SKILL.md
  • manifest.yaml
  • api.ts · src/
  • handoff.ts · src/
  • index.ts · src/
  • probe.ts · src/
  • reconcile.ts · src/
  • types.ts · src/

SKILL.md (first lines)

# cloudflared

A containerized elliott has no public IP. Inbound webhooks reach it through a
Cloudflare tunnel: Cloudflare terminates `https://hooks.example.com`, the tunnel
carries the request to the runtime's HTTP port, and
[webhook-provisioner](../webhook-provisioner/SKILL.md) verifies it and dispatches
it to whichever skill acquired the `ingress.webhook` grant.

Give this skill Cloudflare credentials and it builds that path itself.

## What it provisions

On every boot, idempotently:

1. **A named tunnel** — `elliott-<hostname>`, adopted if it already exists.
   Deleted tunnels are excluded from the lookup, because adopting one yields an
   id that can never connect.
2. **Ingress rules** — the hostname routed to `http://localhost:<runtime port>`,
   with a catch-all 404. This is the rule that keeps a provisioned tunnel from
   becoming general-purpose ingress into the host: whatever hostname is routed,
   it terminates at this runtime's own port.
3. **A proxied CNAME** — `hooks.example.com → <tunnel-id>.cfargotunnel.com`.
   Proxied is not optional; unproxied would expose the tunnel target directly.

A boot on an already-provisioned account performs three GETs and changes
nothing. It reports only what it actually changed, so a restart is silent and
the one boot that took action stands out.

It also heals drift. A DNS record left pointing at a deleted tunnel, or ingress
pointing at the wrong port, is rewritten — both are failures that look fine
until someone sends a webhook.

## What it does not do

**It never runs the connector.** `cloudflared` runs in its own locked-down
container, supervised by compose. elliott is not given a Docker socket: a socket
is root-equivalent on the host and would dwarf every other capability in this
framework.

**It does not choose your hostname.** You do, in config. An ephemeral
quick-tunnel name would change on every restart and silently invalidate every
URL already registered with Slack and every other sender.

## Configuration

```yaml
gateways:
  cloudflared:
    api_token: ${VAULT:infra/cloudflare#api_token}
    account_id: "…"
    zone_id: "…"
    hostname: hooks.example.com
    # Optional: the sidecar's metrics endpoint. Supply it and the tunnel's
    # health is watched too, not just provisioned.
    ready_url: http://cloudflared:20241/ready
  webhook_provisioner:
    enabled: true
    hooks_base_url: https://hooks.example.com
```

The API token needs `Zone:DNS:Edit` on the zone and
`Account:Cloudflare Tunnel:Edit` on the account. **Scope it to the one zone.**
It is the highest-blast-radius credential this runtime holds — it can create and
delete DNS records — so it is a secret-bearing field and must be an opaque
reference, never a literal.

The four provisioning fields are supplied together or not at all. Three of four
registers nothing rather than silently degrading to watch-only, which would look
like success while no hostname was ever routed.

## Connector token handoff

The connector token is fetched from the API on each boot and written to
`<stateDirectory>/cloudflared/connector-token`, owner-read-only, via a temp file
and rename so the sidecar never reads a partial value.

This is the one place a credential this runtime holds is written to disk, and it
is deliberate: a sibling container cannot read another's memory, and the
alternatives are worse — a Docker socket, or making elliott a secret server.

```yaml
# compose
cloudflared:
  image: cloudflare/cloudflared:latest
  command: tunnel --no-autoupdate --metrics 0.0.0.0:20241 run
  environment:
    TUNNEL_TOKEN_FILE: /run/elliott/cloudflared/connector-token
  volumes:
    - elliott-state:/run/elliott:ro
  read_only: true
  cap_drop: [ALL]
  security_opt: [no-new-privileges:true]
  depends_on: [elliott]
```

`depends_on` matters: elliott writes the token during its own boot, so the
connector has nothing to read until it has run once.

## Health

```json
{"cloudflared":{"provisioned":1,"ready":1,"readyConnections":4,"consecutiveFailures":0,"checks":12,"lastCheckMs":1786883298106}}
```

`provisioned: 0` means the tunnel and DNS could not be established — the
hostname routes nowhere. `ready: 0` means they exist but the connector is not
carrying traffic. `readyConnections: 0` with a 200 from the metrics endpoint is
a process that is alive and routing nothing, which for inbound webhooks is the
same as down and is not treated as ready.

From nficano/elliott, MIT.

More from nficano/elliott

Signals

Stars
1
Forks
0
Open issues
0
Last commit (this folder)
Aug 16, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from nficano

Cite this page

cloudflared skill. Agent Mart. https://agentmart.dev/skills/nficano-cloudflared (last updated 2026-10-24)