Self-hosting
EtherCalc ships a standalone workerd Docker image — no Cloudflare account required.
Docker Compose
Section titled “Docker Compose”Trusted LAN / local dev:
docker compose upThe service listens on http://127.0.0.1:8000 by default. Data persists in a Docker volume under /data. This path has no TLS and no rate limiting — do not expose it directly to the public internet.
Internet-facing (required):
docker compose -f docker-compose.proxy.yml up -dThe bundled nginx recipe terminates TLS (when you mount certs), limits request and connection rates per source address, and forwards WebSocket upgrades with long read timeouts.
Environment variables
Section titled “Environment variables”| Variable | Purpose |
|---|---|
ETHERCALC_KEY | Edit/view HMAC secret (unset = anonymous mode) |
ETHERCALC_BASEPATH | URL prefix (maps to Worker BASEPATH) |
ETHERCALC_DISABLE_ROOM_INDEX | Gate /_rooms, /_roomlinks, /_roomtimes, /_exists (default on in Docker) |
ETHERCALC_RATELIMIT | Optional in-Worker per-IP limit (default off). 1 = 10 req/s; not a substitute for nginx |
Room discovery is disabled by default on self-host images to reduce abuse surface. Override only on trusted networks.
Hardening
Section titled “Hardening”Internet-facing self-hosts must use the proxy compose (or an equivalent edge). See docs/SELFHOST_HARDENING.md for the full threat model, nginx config (deploy/nginx/ethercalc.conf), and optional ETHERCALC_RATELIMIT belt-and-suspenders.
Sandstorm
Section titled “Sandstorm”Each Sandstorm grain runs one spreadsheet (ETHERCALC_DEFAULT_ROOM=sheet1). Packaging files (run_grain.sh, sandstorm-pkgdef.capnp) and the .spk build recipe are in SANDSTORM.md. Legacy grains auto-migrate /var/dump* on first boot.
Local development
Section titled “Local development”Contributors typically run bun run --cwd packages/worker dev (Miniflare) instead of Docker — faster iteration, same feature set.