muster

Run it yourself

Muster is one compiled binary and a Postgres database. You run it on your own swarm. This page is the first run guide: from nothing to a running Muster in shadow mode. Hosts use the reserved .test domain, and every value here is a placeholder.

Where this stands

You build a small image around the release binary, and this page shows how. In shadow mode Muster records every order it would give and sends nothing, so you can watch it work before it acts.

The steps

1. get the binary2. build the image3. create the secrets4. check, migrate, serve5. first owner6. settings7. webhooks

1. Prerequisites

Get the binary

The release workflow uploads the build as a workflow artifact in a private repository. The artifact muster-web-linux-amd64 holds the program, its SBOM and SHA256SUMS. Fetch it with a token that may read the repository's actions, and check it.

gh run download RUN_ID -n muster-web-linux-amd64
sha256sum -c --ignore-missing SHA256SUMS

The program picks its role from its own file name. Copy it to the name muster and a plain serve runs both web and worker in one process.

2. Build the image

The binary is static and needs CA certificates to reach the tracker and forge. Use a static base with certificates and a non root user. The name below is a placeholder.

FROM registry.example.test/base/static:nonroot
COPY muster-web-VERSION-linux-amd64 /usr/local/bin/muster
USER nonroot
ENTRYPOINT ["/usr/local/bin/muster"]
chmod 0755 muster-web-VERSION-linux-amd64
docker build -t registry.example.test/muster:VERSION .
docker push registry.example.test/muster:VERSION

The entrypoint is the binary, so a stack command starts at the subcommand: ["serve", ...].

3. Secrets

Each secret is a file in -secrets-dir. A swarm secret is immutable, so put a version in its name and map it to the file name Muster reads.

FileHoldsNeeded
database-urlthe connection addressalways
operator-token16 characters or more; without it the ops pages are not mountedyes
github-webhook-secretsone secret, or current,previousfor GitHub intake
linear-webhook-secretsthe same formfor Linear intake
tracker-token, forge-tokenread by the tally, and by the executornot for shadow mode with tally off
services:
  muster:
    image: registry.example.test/muster:VERSION
    command: ["serve", "-secrets-dir", "/run/secrets",
              "-listen", ":8080", "-webhook-listen", ":8081",
              "-ops-secure-cookies", "true"]
    secrets:
      - {source: database-url-v1, target: database-url}
      - {source: operator-token-v1, target: operator-token}
      - {source: github-webhook-secrets-v1, target: github-webhook-secrets}
      - {source: linear-webhook-secrets-v1, target: linear-webhook-secrets}

To rotate one, create github-webhook-secrets-v2 from standard input, change source and deploy again. Remove the old secret when no service uses it.

4. Check, migrate, serve

muster check -secrets-dir /run/secrets --database
muster migrate -secrets-dir /run/secrets
muster serve -secrets-dir /run/secrets

check exits 0 when nothing required is missing. migrate prints the version it reached, and a second run says the schema is already current. On a swarm, run it as a one shot service before the stack starts, and run it again before each upgrade. After serve starts, /healthz answers 200, and /readyz answers 200 once the schema matches. Until settings are saved, every webhook answers 503 and names what is missing.

5. The first owner

Open /ops/setup on the operator listener. Give the operator token, an email, a name and a password. If the page is out of reach, use the command line, which reads the password from standard input.

muster users create-owner -email owner@example.test -name Owner

6. Settings

A save is refused unless the whole settings pass validation, and 28 fields are required. They fall in these groups: connections, models and holds, budgets, roles and dispatch, guard, intake, labels and the runner. Turn Shadow runner (runner.shadow) on. No restart is needed, because the service rereads settings every five seconds. Keep the tally off until the tracker and forge tokens are in place.

workspace   example-workspace
team        example-team
tracker_url https://tracker.example.test/api
forge_url   https://forge.example.test/api
budget.ticket_cents 250
budget.day_cents    2500
budget.run_cents    100
runner.shadow       on

These are some of the neutral fixtures from the guide. Shadow mode never calls these addresses.

7. Webhooks

SourceAddressHeader read
GitHubhttps://hooks.example.test/webhooks/githubX-Hub-Signature-256
Linearhttps://hooks.example.test/webhooks/linearLinear-Signature

Send only these two paths to the webhook port. Never publish the operator port, because /metrics shares it. The signing secret is the first value of the matching secret file. For GitHub the content type must be application/json. Linear shows its signing secret only when it creates the webhook, so create the sender first and then add the secret. A bad signature is refused before anything is recorded. Linear deliveries must carry a timestamp within one minute of the server clock.

Proof for each step

StepProof
check, migrate, servecheck exits 0; /readyz answers 200
first ownersign in at /ops/login; /ops/ draws Now
settings/ops/health lists the shadow loop as ok; webhooks stop answering 503
webhooksa test delivery is listed under Webhook deliveries on /ops/intake
shadowlabel a ticket; /ops/dispatch shows its order with a rule

The way back

Configuration

All settings are parsed once, from flags and environment variables. A flag wins over the environment.

FlagEnvironmentExampleNotes
-listenMUSTER_LISTEN127.0.0.1:8080operator listener: health, metrics, ops pages
-database-urlMUSTER_DATABASE_URLpostgres://db.example.test/musterrequired, no default
-log-levelMUSTER_LOG_LEVELinfodebug, info, warn or error
-shutdown-graceMUSTER_SHUTDOWN_GRACE30stime allowed for in-flight work at shutdown

The binary in your hand

$ muster version
muster 0.58.2-0.20261113003756-419cd93ac087 (commit 419cd93, built 2026-11-13T00:37:56Z, go1.26.11)

$ muster help
usage: muster backfill|bosun|check|demo|helm|inspect|mcp|migrate|plan|roles|seats|sentry|serve|skiff|tally|ticket|users|verify|version

Or build from source with the Go toolchain: go build ./..., go vet ./..., go test ./... and go run ./cmd/muster inspect.