Self-hosting
Muster is local-first by default, but it can run as a single-user web service you self-host and open in any browser — no Electron, no macOS requirement. The same harness server and React UI, packaged into one Docker image. Self-hosting is free forever.
Quick start
From a checkout of the project (the compose file is included):
docker compose up -d --build
Open http://localhost:8799. Bots, transcripts, config, and keys persist in the muster-data volume.
To reach it from another machine, port-forward or reverse-proxy port 8799:
# on the server, listen on all interfaces (the image already does):
docker compose up -d
# then browse to http://YOUR_SERVER:8799
Prefer the prebuilt image over building? It's published as ghcr.io/orazen/muster:latest:
docker run -d --name muster \
-p 8799:8799 \
-v muster-data:/data \
ghcr.io/orazen/muster:latest
The image sets OMB_HOST=0.0.0.0 (self-hosted) and keeps state in /data, which the volume maps — data survives rebuilds and upgrades in both the compose and image paths.
Configuration
All settings are environment variables on the muster service. The essentials:
| Variable | Default | What it does |
|---|---|---|
OMB_HOST | 127.0.0.1 | Bind host for the harness + UI. The image sets 0.0.0.0 (self-hosted). |
OMB_PORT | 8799 | Port the service listens on. |
OMB_DATA_DIR | ~/.muster | Where bots/transcripts/config live. The image uses /data (a volume). |
OMB_PUBLIC_HOST | *(unset)* | Public hostname (no port) when serving over a domain, e.g. muster.example.com. |
OMB_ALLOWED_ORIGINS | *(unset)* | Comma-separated extra origins allowed to call the API cross-origin (e.g. https://app.example.com). |
BETTER_AUTH_SECRET | — | Required when self-hosting. Signs session tokens; generate with openssl rand -base64 32. The server refuses to boot without it once the host is non-loopback. Keep it stable — changing it signs out every session — and never leak it: a leaked secret lets sessions be forged. If left empty, the entrypoint generates one on first boot and persists it to the volume. |
OMB_PUBLIC_URL | *(derived)* | Absolute base URL including scheme, e.g. https://muster.example.com. Falls back to https://$OMB_PUBLIC_HOST, then loopback. Set it if you terminate TLS on a non-default port or serve under a path. |
OMB_ALLOW_SIGNUPS | *(closed)* | true reopens email sign-up on the deployment. Default closed; sign-in for existing accounts always works. |
RESEND_API_KEY | *(unset)* | Enables outbound email (verification, password reset) via Resend. Without it those flows are hidden in the UI and links are logged to the console instead. |
EMAIL_FROM | Muster <noreply@localhost> | From address for verification and reset mail. Must be a domain verified with Resend. |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET | *(unset)* | Enables "Sign in with GitHub". Both halves required. Callback: $OMB_PUBLIC_URL/api/auth/callback/github. |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | *(unset)* | Enables "Sign in with Google". Callback: $OMB_PUBLIC_URL/api/auth/callback/google. |
Provider and integration credentials can also be pre-seeded via env instead of pasted in Settings: XAI_API_KEY, COMPOSIO_API_KEY, BOX_TOKEN, OPENCODE_API_KEY, OMB_TTS_KEY (ElevenLabs). They're all optional.
Security model
- Default is loopback-only. On
127.0.0.1the server rejects non-loopback hosts and origins (DNS-rebinding + CSRF protection) and keeps peer-agent comms (/api/internal/*) loopback-only with a per-boot token. - Binding to
0.0.0.0opts in. The host gate widens and same-origin browser requests are allowed. Cross-origin clients still requireOMB_ALLOWED_ORIGINS. - Peer-agent comms never leave loopback — even under
0.0.0.0, a remote socket to/api/internal/*is rejected before the token check. - Every API route requires a session when self-hosting. Requests to
/api/*without a valid session get a401, except/api/auth/*(so sign-in is reachable) and/api/health(so load balancers can probe). Sign-in is rate-limited to 5 attempts per minute per IP; passwords must be at least 12 characters. - Optional flows are hidden, not broken. Password reset and email verification only appear once
RESEND_API_KEYis set; social buttons only appear for providers with both client id and secret present. The UI never offers a button that cannot work. - Still put TLS in front. Sessions travel as cookies — terminate HTTPS at a reverse proxy before exposing this to the internet.
TLS behind a reverse proxy (recommended)
Terminate TLS at a proxy and forward to port 8799. SSE for the live event stream must not be buffered:
server {
listen 443 ssl;
server_name muster.example.com;
# TLS + optional basic auth here.
location / {
proxy_pass http://127.0.0.1:8799;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# SSE for the live event stream must not be buffered.
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_set_header Connection "";
}
}
Set OMB_PUBLIC_HOST=muster.example.com and OMB_ALLOWED_ORIGINS=https://muster.example.com on the muster service to match.
Models and computers
The model picker reflects whichever agent CLIs are installed and logged in on the machine running the harness. The stock image ships no agent CLIs — bots show as unavailable until you provide one:
- Build a custom image that installs
claude,codex, orgrok(and their auth) on top of Muster, - Use engine credentials where a driver only needs a key (OpenCode Go, Compose/Box), or
- Run the container on a machine where the CLIs are already on
PATHvia a bind mount.
FROM muster:latest
# Install a CLI and log it in — but bake no secrets into the image.
RUN npm install -g @anthropic-ai/claude-code
# …then run as usual; the model picker lists Claude once it is logged in.
Cloud computers (Box) work out of the box with a BOX_TOKEN. "This Mac" local computer control is not available in a container — it requires the desktop app.
Updating
docker compose pull && docker compose up -d
Data survives upgrades because it lives in the muster-data volume.
Next steps
Operate
Engines & models
Wire up providers and keys once the container is running.
Operate
Approvals & privacy
How approval cards, scopes, and the Privacy Shield behave on your deployment.
Reference
Security & license
Threat model, data flows, and what the Business Source License lets you do.
Start
Quick start
The desktop-first path, if a server is more than you need today.