Tabs & Spaces Developers

Self-hosting

Running your deployment

Agents

Agents run on an OpenClaw Gateway. A deployment can run one of its own, offered to one workspace (Settings → Agents); other workspaces connect their own Gateway.

With Docker Compose, add the agents profile (or install with --agents), put your model provider's key in .env (ANTHROPIC_API_KEY, OPENAI_API_KEY or OPENROUTER_API_KEY), and run docker compose up -d.

Agents' tools run in sandbox containers, which the Gateway starts through the host's Docker. So:

  • The Gateway container has the Docker socket, which amounts to root on the host. Run it only on a machine dedicated to this deployment.
  • Its state lives in TAS_DATA_DIR/openclaw (by default deploy/data/openclaw), at the same absolute path inside and outside the container, because sandboxes mount it by host path.

Agents' computers

Each agent works on a computer of its own: a sandbox with Python 3 (python-pptx, python-docx, openpyxl, reportlab, matplotlib, pandas), Node.js and fonts, so agents can make decks, documents, spreadsheets, PDFs and charts. The image (openclaw-sandbox:bookworm-slim, about 1.1 GB) is built by the gateway-sandbox-image service. A workspace's own Gateway uses its own sandbox image: build deploy/openclaw/Dockerfile.sandbox there for the same tools.

Agents save what they make to a space's Files through a one-time upload link, which needs:

SettingWhat it does
AGENT_SANDBOX_INTERNETtrue (the default) gives sandboxes network access. false keeps every agent offline; owners can also turn it off per workspace (Settings → Agents → Computers). Offline agents can still write text files
AGENT_UPLOAD_URLThe address sandboxes reach the API at (default PUBLIC_URL). Set it when sandboxes can't use the public address, e.g. http://host.docker.internal:4400 on a single Docker host

Host access: on a workspace's own Gateway only (never the deployment's), an owner can let an agent they made run some listed programs on the Gateway's machine instead of its sandbox (Settings → Agents → the agent → Host access). Anything not listed is refused.

Billing your workspaces

A deployment can charge its workspaces for what they use: seats, file and database storage, AI usage, and a flat fee.

  1. Set prices in Deployment settings → Billing. Everything is off until you price it.
  2. To be paid online, connect your own Stripe account under Payments on the same tab (Connect Stripe), with a restricted key that can write Customers, Invoices and Invoice items.
  3. When each month ends, every billed workspace gets a statement. With Stripe, it becomes an invoice Stripe emails to the workspace's owner; without, mark statements paid under Statements, on the same tab.

Payments are checked with Stripe every hour, so no webhook is needed.

Support

To be eligible for support from us, register the deployment in Deployment settings → Support with a contact email.

  • What's sent: one report a day, numbers only (counts, sizes, tokens, version), never messages, names or files. The Support section shows the next report, field by field, before you register.
  • Stopping: unregister there, and the reports stop.
  • Without internet access: a deployment can run without registering, but isn't eligible for support.
  • Asking for help: with a Standard or Priority support plan, open a ticket in the same section. Our replies appear there and are emailed to whoever opened it.

Helping your workspaces

People ask for help, report problems and share ideas from Help & feedback (their account menu). You answer in Deployment settings → Requests, and so can each workspace's owners and admins. With a support plan from us, you can pass any request on to us; to charge your workspaces for support, price the Support plan in Billing.

Health

CheckWhat it tells you
GET /api/healthThe API is up, and its version
GET /api/health/readyThe database and storage answer (503 if either doesn't)
Deployment settings → General → Service statusThe same, with response times, in the app
docker compose psEvery container's health check

To check a deployment end to end, run the smoke test from a machine with Node 22:

sh
node deploy/smoke-test.mjs https://chat.example.com <setup token>

It completes setup if needed, creates a workspace, sends a message (checking it arrives live), and uploads and downloads a file. Use it on a fresh install or a test copy: it leaves a "Smoke test" admin and workspace behind.

Upgrades

Images are pinned to TAS_VERSION. To upgrade:

sh
# 1. Back up (below).
# 2. Set TAS_VERSION=<new release> in .env, then:
docker compose pull
docker compose up -d

On Fly.io, deploy the new release with the same flyctl deploy commands.

When the API starts, it migrates the data to the new release's layout before serving anything: the deployment's database and every workspace's, wherever it lives. Migrations run once (several API instances take turns), an interrupted run resumes where it stopped, and a workspace whose database can't be reached is skipped and tried again on the next start (the logs say so).

Downgrades aren't supported. An older release refuses to start on data a newer one has migrated (Can't start: … was upgraded by a newer release). To go back, restore the backup taken before upgrading.

Backups

WhatHow
MongoDBmongodump --uri "$MONGODB_URI" --archive=backup.gz --gzip (the bundled one: docker compose exec mongo mongodump --archive --gzip > backup.gz). It covers the deployment's database and every workspace's on that server. Atlas also takes backups on paid tiers
FilesCopy the bucket (the bundled SeaweedFS: back up the s3-data volume)
SecretsKeep a copy of .env (or your Fly secrets), above all AUTH_SECRET: changing it signs everyone out, and without it saved credentials (Gateway tokens, workspaces' own database and bucket keys) can't be read

Redis holds only pending work, which the app rebuilds from MongoDB: it needs no backups. Workspaces on their own MongoDB or bucket are backed up wherever those live. Workspace owners can also download an export (Settings → Data), which can be imported into any deployment.

Building the images yourself

From the repository root:

sh
docker build -f deploy/Dockerfile --target api --build-arg TAS_VERSION=1.2.3 -t my-registry/tabs-and-spaces-api:1.2.3 .
docker build -f deploy/Dockerfile --target web --build-arg TAS_VERSION=1.2.3 -t my-registry/tabs-and-spaces-web:1.2.3 .

Then set TAS_IMAGE_PREFIX=my-registry/tabs-and-spaces and TAS_VERSION=1.2.3 in .env. Both images run as non-root users: the API is Node 22 (slim) with only its runtime dependencies, and the web image is Caddy with the built app.