Public: anyone can read this; the crew can change it.

Spike: spawn a forge on Cloudflare with OpenTofu from a crew run, state in the forge's own bucket #377

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

This adds an OpenTofu module for a forge behind a Cloudflare Worker front door, plus a provisional verdict. I never ran `tofu plan`, `apply` or `destroy`, so the acceptance items that need a real apply are not met. This run had no `tofu`, no Cloudflare token, no bucket credential and no `bwrap`.

shipped production is serving it deploy 40e21c3

opened this

This adds an OpenTofu module for a forge behind a Cloudflare Worker front door, plus a provisional verdict. I never ran tofu plan, apply or destroy, so the acceptance items that need a real apply are not met. This run had no tofu, no Cloudflare token, no bucket credential and no bwrap.

What changed

  • infra/forge-cloudflare/: a Worker and one Durable Object that forwards to the forge's body and answers /healthz with 503 when the body is down. It also has a proxied DNS record and, when body_url is empty, a tunnel for a body with no public address.
  • State: the S3 backend uses use_lockfile and a per-forge key. The credentials come from the environment, so none is in the repository.
  • spike- guard: the name variable must match ^spike-[a-z0-9-]{1,40}$, so the module cannot address production tunnel or zone records. Every DNS record carries a comment naming the spike.
  • test/forge-cloudflare.test.ts: covers request forwarding, the 503/502 behaviour when the body is down, and the name guard. It passes. I added it to the forge.json check.
  • docs/SPIKE-CLOUDFLARE.md: the answers to the five open questions and the Container vs Fly vs Firecracker verdict.
  • docs/EXTRACT.md: tofu is now on the host binary list.

What to look at

  • Unverified module: I wrote the Cloudflare provider v5 syntax from memory, and tofu validate has not seen it.
  • Open questions: none of the five is measured. The doc labels each one as reading rather than evidence.

- bubblewrap inside the container is probably unavailable. - A crew run probably does not keep the container awake. - HTTPS git replaces SSH on Containers. - SQLite WAL and the 30-day snapshot retention are untested. The forge's own S3 snapshot avoids both.

  • Container gap: the Cloudflare provider has no Containers resource. A Container body has to be deployed with wrangler and passed in as body_url.
  • Verdict: Fly is the default for a forge people work in daily. A Container fits a mostly idle forge. Firecracker on metal only pays off when many forges share hardware.

Not done: tofu is not installed for runs, the module has not been applied, and destroy is not proven. The checklist at the end of the spike doc lists the remaining steps.

bun x tsc --noEmit fails here with a missing bun type definition, which comes from this environment's node_modules, not from the change. I did not run the full forge.json check.

🤖 Generated with Claude Code

Closes #339

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs