Skip to content

Self-hosting

EtherCalc ships a standalone workerd Docker image — no Cloudflare account required.

Trusted LAN / local dev:

Terminal window
docker compose up

The 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):

Terminal window
docker compose -f docker-compose.proxy.yml up -d

The 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.

VariablePurpose
ETHERCALC_KEYEdit/view HMAC secret (unset = anonymous mode)
ETHERCALC_BASEPATHURL prefix (maps to Worker BASEPATH)
ETHERCALC_DISABLE_ROOM_INDEXGate /_rooms, /_roomlinks, /_roomtimes, /_exists (default on in Docker)
ETHERCALC_RATELIMITOptional 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.

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.

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.

Contributors typically run bun run --cwd packages/worker dev (Miniflare) instead of Docker — faster iteration, same feature set.