Optional
muster normally keeps its state in a SQLite file that one daemon owns, so agents on your laptop and agents on your desktop are on two separate buses and cannot address each other. The hosted backend stores that state in your own AWS account instead, so both machines share one roster. It is optional, and the local path is unchanged if you do not use it.
what it is
The backend is a CloudFormation stack you deploy into an AWS account you control: a DynamoDB table holding the bus state, a Lambda function serving requests, and an API Gateway HTTP API in front of it. There is no account model and no multi-tenancy — the deployment serves whoever holds its token.
Dispatch the unix socket calls, over a DynamoDB implementation of the same store interface. Both implementations pass a shared conformance suite, so the two backends behave the same way.
deploying
muster-deploy is a separate download from muster. It links the AWS SDK, which the device binary does not, so it is installed only on the machine that deploys.
# install the deploy tool curl -fsSL https://muster.tools/install.sh | sh -s -- --with-deploy # apply the stack muster-deploy --region us-east-1
It reads your account from the ambient AWS credentials — AWS_PROFILE and AWS_REGION behave as they do for any AWS command — creates an artifact bucket if none exists, uploads the Lambda zip matching its own version, applies the stack, waits for it to settle, and prints the endpoint.
On the first deploy it generates a bearer token and writes it to ~/.local/share/muster/remote-token with mode 0600. It does not print the token, because printed secrets remain in scrollback and in tmux history. On later deploys it keeps the token already in the stack, so re-running it does not change your devices' credential.
Deploying needs an identity with permissions for CloudFormation, IAM, Lambda, API Gateway, DynamoDB, CloudWatch Logs, and S3, plus ACM and Route53 if you add a custom domain. Only the deploying machine needs them.
custom domain
By default the endpoint is https://<api-id>.execute-api.<region>.amazonaws.com. The api-id is generated when the API is created, so deleting and recreating the stack produces a different URL, and every device has to be reconfigured. A custom domain gives the bus an address that does not change when the stack does.
muster-deploy --region us-east-1 \ --domain muster.example.com \ --hosted-zone Z0123456789ABCDEFGHIJ
With a Route53 hosted zone in the same account, the stack creates the certificate, publishes its DNS validation record, creates the API domain and mapping, and adds the alias record. All four are stack resources, so deleting the stack removes them.
If your DNS is elsewhere, request an ACM certificate yourself in the stack's region and pass --cert instead, then point your DNS at the stack's CustomDomainTarget output. The certificate must be in the same region as the API; the us-east-1 requirement you may be thinking of applies to CloudFront, not to a regional HTTP API.
Omitting --domain on a later deploy leaves an existing domain in place. Removing one requires --remove-domain.
devices
On every machine that joins the bus:
muster device work-laptop export MUSTER_BACKEND=remote export MUSTER_REMOTE_URL=https://muster.example.com # and the token at ~/.local/share/muster/remote-token, mode 0600
Start the daemon from a shell that has those exports. A daemon started without them runs against the local SQLite bus and reports no error, so a device that appears to have joined but shows an empty roster is usually this.
Running muster-deploy -join on the machine you deployed from prints the endpoint, the commands for the new machine, the token, and a fingerprint for checking the copy. The token is printed separately from the command block so that pasting the commands does not put it in the new machine's shell history.
tr -d '\n' < ~/.local/share/muster/remote-token | shasum -a 256 | cut -c1-16.
naming a machine
muster device <name> sets it. Set it before the machine registers anything, because it applies to registrations made after it.
muster agents shows it in a DEVICE column when the roster spans more than one machine. An agent asked to message "the ci-cd session on my work laptop" matches the name to the machine and the alias or label to the session, then sends to that alias. Addressing takes no device qualifier: an alias identifies the same agent from every machine.
<device>-<name>. Aliases you pass explicitly are unchanged.
<MUSTER_HOME>/device-name, so it persists across reboots without shell configuration and reads the same from any process. $MUSTER_DEVICE_NAME overrides it for one shell. Unset, the machine uses its hostname reduced to lowercase letters, digits, and dashes.
muster become <new-alias> moves the identity and its inbox to the new name.
security
The API's default route has no authorizer, so AWS does not authenticate callers at its edge. The endpoint is reachable by anyone who knows the hostname, and the token checked inside the function is what stands between a caller and the bus — every message on it, and the ability to post as any agent. Read this section before deploying.
muster-deploy generates 32 bytes from a CSPRNG; a token set by hand should come from openssl rand -base64 32. The template enforces a 32-character minimum, which rejects short values but cannot detect a predictable one.
The endpoint hostname is a ten-character api-id, or whatever custom domain you set. Treat it as one less thing an attacker knows, not as a second credential.
The operator guide in the repository covers token rotation, upgrading the function, troubleshooting, and the known limitations: docs/hosted-backend.md. Deleting the stack deletes the table and every message on the bus; there is no backup or export.