Self-hosting
Self-hosting Tabs & Spaces
Tabs & Spaces is free to run yourself. A deployment is one installation: your server (or the cloud services you choose), your domain, your data. People sign up on it and work in workspaces, each with its own spaces, agents and data.
This section covers:
- Install (this page): one server with Docker Compose.
- First-run setup: naming the deployment and creating the first admin account and workspace.
- Managed services: using a hosted database, Redis, storage and email instead, and running on Fly.io.
- Running your deployment: agents, billing, support, upgrades, backups and health.
What it's made of
A deployment runs two containers:
- The API, which keeps the data and does the work.
- The web server (Caddy), which serves the app, forwards
/apito the API (including its real-time connection), and gets HTTPS certificates for you.
They need a few services:
| Service | What it's for | Bundled, or your own |
|---|---|---|
| MongoDB 8 | All data: the deployment's and each workspace's (a database per workspace) | Bundled, or any MongoDB, such as Atlas |
| Redis or Valkey | The job queue: schedules, tasks and background work | Bundled Valkey, or any Redis 6.2+ |
| S3-compatible storage | Files | Bundled SeaweedFS, or AWS S3, Cloudflare R2, Backblaze B2, MinIO… |
| SMTP | Email: sign-up confirmation, invitations, password resets | Bundled Mailpit (for trying it out only), or any email service |
| OpenClaw Gateway | Agents (optional) | Bundled, or each workspace connects its own |
Requirements
- Docker with Compose v2.20 or later.
- Memory: about 2 GB for the app, MongoDB and storage. Add about 1.5 GB to run the agents' Gateway.
- For a public server: a domain pointing at the machine, with ports 80 and 443 open.
- The repository, which has everything under
deploy/:
| File | What it is |
|---|---|
docker-compose.yml | The stack |
setup.sh | Writes .env with fresh secrets, and prints the first-run link |
Dockerfile | Builds the images (--target api, --target web) |
web/Caddyfile | The web server's config |
openclaw/ | The agents' Gateway image and its first-start config |
smoke-test.mjs | Checks a running deployment end to end |
fly/ | Configs for running on Fly.io (see Managed services) |
Install
cd deploy
./setup.sh --domain chat.example.com # or just ./setup.sh to try it on this machine
docker compose up -dsetup.sh writes .env, readable only by you. It holds generated secrets, the bundled services to run, and your address. At the end, it prints the first-run setup link: open it to set up the deployment.
Its options:
| Option | What it does |
|---|---|
--domain NAME | Serve https://NAME. Caddy gets and renews the certificate |
--agents | Also run an OpenClaw Gateway (see Agents) |
--version X.Y.Z | The release to run. The default is latest: pin a version in production |
--http-port N | Use a port other than 80 when trying it locally |
Without --domain, the app is at http://localhost, and email goes to the bundled Mailpit, which only catches it: read it at http://localhost:8025. With --domain, set the SMTP_* settings in .env to a real email service before people sign up.
Choosing what runs here
COMPOSE_PROFILES in .env lists the bundled services to run. To use your own service instead, remove its profile, set its settings, and run docker compose up -d.
| Profile | Service | To use your own instead |
|---|---|---|
mongo | MongoDB 8 | Set MONGODB_URI, e.g. mongodb+srv://user:pass@cluster.example.net/tabs-and-spaces |
redis | Valkey 8 | Set REDIS_URL, e.g. rediss://user:pass@redis.example.net:6379 |
s3 | SeaweedFS | Set S3_ENDPOINT (blank for AWS), S3_REGION, S3_BUCKET and the keys. The bucket is created if it's missing |
agents | OpenClaw Gateway | Leave OPENCLAW_GATEWAY_* empty. Workspaces can still connect their own Gateway |
mail | Mailpit (trying it out) | Set SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASSWORD and MAIL_FROM |
Hosted services need a few things set up right, such as a database user that may delete databases, and Redis that never evicts: Managed services goes through each one.
Workspaces can also keep their data in their own MongoDB and bucket, chosen when they're created. A deployment admin can turn that off in Deployment settings. If those databases or buckets are on your private network, set WORKSPACE_INFRASTRUCTURE_PRIVATE_NETWORKS=true.
Behind your own proxy
Set SITE_ADDRESS=:80, choose a port with HTTP_PORT, and set PUBLIC_URL to the address people use, e.g. https://chat.example.com. Your proxy must:
- forward everything to that port, including WebSocket upgrades on
/api/ws; - allow large request bodies: attachments up to
ATTACHMENT_MAX_MB, Docs files up toDOCS_MAX_MB, imports up toIMPORT_MAX_MB; - send
X-Forwarded-For, so sign-ins are recorded with the visitor's address. The web server trusts it from private networks.