Self-host with Docker
The production compose file runs two containers: the daemon and the web dashboard behind nginx.
Start it
Section titled “Start it”You need Docker with Compose, and a git repository. From a clone of the Natamux repository:
export NATAMUX_TOKEN="$(openssl rand -base64 32)"export NATAMUX_REPO=/path/to/the/git/repositorydocker compose -f compose.prod.yaml up -d --buildOpen http://localhost:8080 and paste the token into the Daemon token field. Write the token down: you also need it for the CLI.
Try it with demo data
Section titled “Try it with demo data”To look around the dashboard without your own repository, start the images that CI builds on main. From a clone of the Natamux repository, with Docker and the GitHub CLI:
scripts/e2e.sh upThe script pulls ghcr.io/lenhatthanh20/natamux-daemon and natamux-web, checks their build attestation with gh, starts them, and adds demo tasks. Open http://localhost:8080 and sign in with the token e2e-token. The demo uses a fake agent, and its data lives in Docker volumes. scripts/e2e.sh down stops it and removes the demo data. See docs/e2e.md in the repository.
Settings
Section titled “Settings”| Variable | Meaning |
|---|---|
NATAMUX_TOKEN |
Required. The token every request needs. Use a long random value |
NATAMUX_REPO |
Required. The git repository that tasks get worktrees from. Mounted at /repo |
NATAMUX_BIND |
Where the dashboard listens. Default 127.0.0.1. Change it only for a reverse proxy that adds TLS |
NATAMUX_PORT |
Dashboard port. Default 8080 |
Compose refuses to start when NATAMUX_TOKEN or NATAMUX_REPO is missing.
What runs
Section titled “What runs”- daemon: Node.js, git and the built daemon. Its data (tasks, index, worktrees) is in the volume
natamux-data, mounted at/data. Its port 4317 is not published: only the web container reaches it. - web: nginx with the built dashboard. It passes
/apito the daemon, WebSocket too. - Both containers have a read-only file system, no Linux capabilities and
no-new-privileges, and restart unless you stop them.
Use the CLI against it
Section titled “Use the CLI against it”Point the CLI at the dashboard’s /api address, with your token:
export NATAMUX_TOKEN=<your token>export NATAMUX_URL=http://localhost:8080/apinatamux task listAgent hooks reach the daemon the same way: set NATAMUX_URL=http://host:8080/api where natamux hook runs.
Security notes
Section titled “Security notes”- There is no TLS. The token travels in clear text. Put a reverse proxy with TLS in front before you open the dashboard beyond localhost, and only then change
NATAMUX_BIND. - Keep the token secret. It is the only lock on the API.
- The repository must be writable by user 1000 inside the container. Otherwise
workspace createfails, although reading tasks still works. compose.prod.yamlbuilds the images locally, with the taglocal. Base images are tags, not pinned digests. The images thatscripts/e2e.shpulls are built by CI frommainand carry a build attestation.
Stop and update
Section titled “Stop and update”docker compose -f compose.prod.yaml down # stops; the volume with your tasks staysdocker compose -f compose.prod.yaml up -d --build # rebuilds with new codeDevelopment setup
Section titled “Development setup”compose.yaml is the development setup: Vite dev server on port 5173, daemon on 4317 published to loopback, and the default token devtoken. It is meant for a codespace and for working on Natamux itself. See docs/docker.md in the repository.