---
title: "Deploy celld | Open Source Cloudflare Durable Objects"
description: "Self-hosted Cloudflare Durable Objects: two-node fleet on your bucket"
category: "Storage"
url: https://railway.com/deploy/celld-durable-objects
---

# Deploy celld | Open Source Cloudflare Durable Objects

Self-hosted Cloudflare Durable Objects: two-node fleet on your bucket

**[Deploy celld | Open Source Cloudflare Durable Objects on Railway](https://railway.com/template/celld-durable-objects)**

- **Creator:** katsuba.dev
- **Category:** Storage

## Template content

### celld-peer https://celld.dev/cells-mark.svg

- **Image:** ghcr.io/denoland/celld:v0.4.0

### celld https://celld.dev/cells-mark.svg

- **Image:** ghcr.io/denoland/celld:v0.4.0
- **Health check:** /.well-known/celld/health
- **Public domain:** Yes

### welcome-seed https://celld.dev/cells-mark.svg

- **Image:** ghcr.io/denoland/celld:v0.4.0
- **Start command:** `sh -c 'if [ "$SEED_WELCOME_APP" != "1" ]; then echo "SEED_WELCOME_APP is not 1 - leaving the fleet deployment untouched"; exit 0; fi; mkdir -p /tmp/welcome/public; printf "%s" "$WRANGLER_JSON" > /tmp/welcome/wrangler.jsonc; printf "%s" "$WELCOME_HTML" > /tmp/welcome/public/index.html; exec /usr/local/bin/celld deploy /tmp/welcome'`

## Buckets

- **Storage**

## Documentation

# Deploy and Host celld on Railway

celld is Deno's open-source daemon for running Cloudflare Workers and Durable Objects on infrastructure you own. Every object is a cell: a named server with its own SQLite database, durable in object storage that belongs to you, with no control plane and no consensus service to operate.

## About Hosting celld

This template deploys a **two-node celld fleet** on the newest stable release, pinned to `ghcr.io/denoland/celld:v0.4.0` — the upstream image, not a fork.

A Railway object storage bucket is provisioned as part of the deploy and holds the fleet's durable state: the deployments, the SQLite replicas, the ownership records and the peer secret. It is verified to satisfy celld's storage contract — `celld diagnose` reports `bucket conditional write: create, reject-create, update, reject-stale` against it — which is the requirement that rules out Backblaze B2, Hetzner and DigitalOcean Spaces.

The second node is not decoration. celld acknowledges a write once a peer holds it on disk (`CELLD_DURABILITY=fleet`, the default); a single node has nobody to send to, so **every acknowledged write waits for a full round trip to object storage**, which upstream describes as "much slower". On this template a write is confirmed by the peer in a measured 2–6 ms over Railway's private network. Both nodes carry a volume for their local SQLite and replication log, so a restart does not force every cell to restore from the bucket.

The public node takes the domain and serves everything: a request for a cell the peer owns is routed over celld's versioned peer tunnel, so one domain covers the whole fleet and there is no load balancer to configure. The peer's listener stays private, which matters — celld's operator API is unauthenticated by design and must never face the internet.

A fleet with no application is not idle, it is down: each node exits with `read s3://…/deploy/current.json: no such key` and restarts. So this template ships a one-shot job that deploys an asset-only welcome page on first boot. The fleet comes up green, the URL serves a real page, and that page tells you how to deploy your own Worker.

## Common Use Cases

- **Per-user or per-document state**: one cell per entity, each with its own SQLite database, strongly consistent without a shared database tier.
- **Collaborative sessions and multiplayer**: WebSocket-backed Durable Objects with hibernation, coordinated by the object rather than by a queue.
- **Leaving Cloudflare without rewriting**: run existing Workers, Durable Objects, D1, KV, Queues, Workflows and R2 bindings from your own Wrangler configuration.
- **Scheduled and alarm-driven work**: cron triggers and Durable Object alarms on infrastructure you can inspect.

## Dependencies for celld Hosting

### Deployment Dependencies

- [celld](https://github.com/denoland/celld) — the upstream image, `v0.4.0`
- A Railway object storage bucket, created by this template
- [celld CLI](https://celld.dev/docs) on your machine to deploy applications: `curl -fsSL https://celld.dev/install.sh | sh`
- [esbuild](https://esbuild.github.io) on `PATH` for Worker code; asset-only projects need nothing

### Implementation Details

Deploy your application from any Wrangler project by pointing the CLI at the fleet bucket. The storage variables are on the `celld` service:

```sh
export CELLD_BUCKET=...   S3_ENDPOINT=...   AWS_REGION=...
export AWS_ACCESS_KEY_ID=...   AWS_SECRET_ACCESS_KEY=...

git clone https://github.com/denoland/celld
celld deploy celld/examples/counter
```

Nodes read the deployment pointer every 30 seconds and adopt a new version **without restarting**: requests in flight finish on the old code, resident Durable Objects move at a safe point and keep their storage and hibernatable WebSockets.

Set `SEED_WELCOME_APP=0` on the `welcome-seed` service once your own application is deployed. `celld deploy` replaces the fleet's single deployment pointer, so re-running that job would otherwise put the placeholder back.

Things worth knowing before you rely on it:

- **The bucket credentials are the fleet.** Anything holding them can read and rewrite every cell. Treat them the way you treat a database password.
- **Pinning is not caution here.** Upstream states that a v0.3.0 fleet must be stopped completely before v0.4.0 is deployed, because the peer tunnel protocol changed. A template on a floating tag can split a running fleet across two protocol versions on an ordinary redeploy.
- **The peer port is private on purpose.** The operator API on port 8081 permits state inspection, eviction and shutdown without authentication, and celld terminates no TLS on it. Do not give the `celld-peer` service a public domain.
- **Redeploys have a short gap.** Overlap is 0 and the drain grace is 60 seconds, so a node finishes handing its cells over before it stops; a public request during the switch can see one 502.
- **Resource use scales with resident cells.** Measured at rest on this template: about 100 MB on the serving node and 25 MB on the peer, roughly $5–8 a month for the pair plus storage. Each active cell adds a V8 isolate and an open SQLite database, so a busy fleet is a different number — raise the memory limit before you raise the node count.

## Why Deploy celld on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying celld on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

The fit is unusually close here: celld wants object storage with conditional writes and a private network its nodes can trust, and Railway provisions both inside the project — no Cloudflare R2 account, no credentials to copy, no VPC to design.


## Similar templates

- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.
- [Redis](https://railway.com/deploy/redis-1) — Self Host Latest Redis with Railway
- [EasyImg](https://railway.com/deploy/easyimg) — Simple self-hostable Nuxt.js personal image hosting system.

Open this page in a browser: https://railway.com/deploy/celld-durable-objects
