Operations

Self-hosting

Morrow has no hosted service — every instance runs on infrastructure the operator provisions and controls.

Docker

shell
docker run -e MORROW_API_KEY=secret -v morrow-data:/data -p 3000:3000 ghcr.io/jekyo/morrow:latest

All profile directories, the SQLite database, and other durable state live under /data inside the container. Mount a named volume or bind mount there — without it, everything is lost when the container is removed.

Environment variables

VariableDefaultWhat it does
MORROW_API_KEY(none — required)The single bearer key gating every request. Required — the server refuses to start without it.
MORROW_PORT3000Port the HTTP/websocket server listens on.
MORROW_DATA_DIR/dataWhere profile directories, the SQLite database, and other on-disk state live.
MORROW_MAX_PROFILES5How many profiles may be running (browser processes launched) at once.
MORROW_LAUNCH_TIMEOUT60Seconds to wait for a profile's browser to finish launching before failing.
MORROW_DEV_ORIGINS(unset)Dev-only: extra hosts (comma-separated, no protocol/port) allowed to load /_next/* assets when running npm run dev from something other than localhost — a LAN IP, hostname, or tunnel. Not used in production.

Deploying with jekyo

Morrow's own repo is set up to deploy with jekyo, a Docker-compose-to-k3s deployment tool — write a jekyo.yaml pointing at the published image, mount a persistent volume for /data, and set MORROW_API_KEY as a secret. Any container host that gives you a persistent volume and a TLS-terminating reverse proxy in front works the same way — jekyo is a convenience, not a requirement.

Security posture

  • Single API key. One MORROW_API_KEY gates the whole instance — every profile, session, and stored artifact. There is currently no per-user or per-profile access separation.
  • Run behind TLS. Terminate TLS in front of Morrow (nginx, Caddy, or similar) so the API key and profile data are never sent in the clear. Morrow is not hardened for direct exposure to the open internet.
  • Encryption at rest is the operator's responsibility today. Morrow does not encrypt the /data volume itself. If encryption at rest is required, provide it at the disk or volume level on the host.
  • Avoid exposing the Playwright/viewer WebSocket endpoints publicly — the API key travels as a query parameter there and may be logged by upstream infrastructure.
  • Keep the host, its dependencies, and the Morrow version itself up to date.

Full security policy

Reporting a vulnerability, supported versions, and the complete operating checklist live in SECURITY.md.