Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/denoland/celld/llms.txt

Use this file to discover all available pages before exploring further.

celld is in alpha and is not safe for hostile multi-tenant use. Security fixes apply to the latest release only — older alpha builds do not receive backported patches. Review this page in full before exposing a celld fleet to untrusted traffic.

Separate the public and internal listeners

celld opens two independent HTTP listeners. Understanding what each one does — and does not — serve is the foundation of the security model.
ListenerFlagDefaultPurpose
Public--listen127.0.0.1:8080Serves the deployed Worker to end users
Internal--internal-listen127.0.0.1:0Serves the peer replication protocol and the operator API
Only the public listener should be reachable from the internet, through a load balancer, a reverse proxy, or a public firewall rule. The internal listener must not be visible outside the fleet. The internal listener defaults to 127.0.0.1:0 — a random loopback port chosen at each start. The startup output reports the selected address. For a multi-node fleet, bind the internal listener to a private interface and use --advertise to tell peers the address they can reach:
celld \
  --listen 0.0.0.0:8080 \
  --internal-listen 10.0.0.12:8081 \
  --advertise node-a.internal:8081 \
  --bucket "$CELLD_BUCKET" \
  --endpoint "$S3_ENDPOINT" \
  --region "$AWS_REGION"
An explicit --advertise value requires an explicit --internal-listen address. celld also rejects an explicit non-loopback public listener that does not have an explicit internal listener, to catch obsolete single-listener configurations.
celld cannot verify that an advertised hostname or translated port actually reaches the internal listener. You are responsible for routing the advertised address to the internal listener — not to the public Worker listener.

Public listener

The public listener reserves only one path:
PathHealthyDraining
/__celld/health200 {"ok":true}503
Every other path — including /health — belongs to the deployed Worker. The internal listener returns 404 for any path it does not recognise, so a misrouted operator request cannot accidentally become an application request.

Protect the internal listener

The operator API has no authentication. A client that can reach the internal listener can inspect node state, start direct work, evict resident cells, or stop the process. Restrict access with a firewall rule or a private network overlay. Do not expose the internal listener to the public internet under any circumstances.
celld does not terminate TLS on the internal listener. If the private network does not provide the required confidentiality, use an encrypted overlay such as WireGuard or Tailscale.

Internal operator API paths

The following paths are available on the internal listener:
PathDescription
/stateReports current occupancy, eviction, and restoration values. Remains available during graceful shutdown drain.
/cell/NAMEResolves or activates a cell for an operator check.
/evict/NAMEEvicts a resident cell.
/do/NAMESends a direct Durable Object request.
POST /shutdownStarts a graceful ownership handoff.
POST /shutdown?handoff=preservePrepares a clean same-node reload and keeps the ownership records.
GET /__celld/probeServes the signed diagnostic probe used by celld diagnose. Also available during graceful shutdown drain.
The operator API is an alpha interface. A release can change its paths or response formats without notice. Keep your operator tooling and the celld release at the same version.

Peer authentication

Peer requests on the internal listener use a separate authentication layer from the operator API. Each peer request carries:
  • An HMAC over the request metadata
  • A body signature that covers the request payload
  • A clock bound that rejects requests with a timestamp too far from the current time
  • Replay protection that prevents a captured request from being replayed
The fleet’s shared peer-authentication secret is stored in the fleet bucket. A private network adds defence in depth but does not replace peer authentication — always use a private overlay and peer auth together.

Protect the fleet bucket

The fleet bucket is the root of authority for the entire fleet. Anyone who holds valid bucket credentials has full administrative control. Treat bucket credentials with the same care as root credentials.
The bucket stores:
  • Deployed Worker bundles and static assets
  • SQLite cell state (replicated data for every cell)
  • Ownership leases (which node owns each cell)
  • Node leases (used for fleet discovery)
  • The shared peer-authentication secret
Recommendations:
  • Give each credential access to one fleet bucket only.
  • Use a key prefix (s3://BUCKET/PREFIX) to isolate multiple fleets in one bucket, but give each fleet its own credential scoped to its prefix.
  • Replace a credential immediately after a suspected disclosure.

Cell isolation

Each cell is a SQLite database with one writer at a time. A cell can access only its own database — there is no shared storage between cells at the application level. A defective or compromised cell can consume CPU, memory, and file descriptors on its fleet nodes, but it cannot read or modify another cell’s data. The fleet has no shared multi-tenant scheduler or account service. One application deployment runs per fleet.

Application authentication

celld does not authenticate the users of the deployed application, and it does not terminate public TLS. Both concerns belong in front of the public listener:
  • TLS termination — use an ingress proxy (nginx, Caddy, a cloud load balancer) to terminate HTTPS before traffic reaches --listen.
  • User authentication — enforce authentication in the ingress proxy or in the deployed Worker itself before requests reach cell handlers.
Deploying celld without TLS in front of the public listener sends all Worker traffic — including credentials and session tokens — in plaintext. Always terminate TLS at the ingress layer.

Build docs developers (and LLMs) love