staqlydocs

Run with Docker

Run staqly as one pre-built, hardened container with docker run. No checkout, no Compose.

Edit on GitHub

The alternative to the binary for Staqly Community Edition: the pre-built image ghcr.io/staqly/staqly runs everything staqly serve runs (API, MCP, background workers and the dashboard) in one container, with all data in one volume. You need Docker and nothing else: no repository, no Compose, no make. Choose it when you already run your tools in Docker or want a read-only, capability-free container.

Start staqly

Run the container

docker run -d --name staqly --restart unless-stopped \
  -p 127.0.0.1:3333:3333 -p 8080:8080 \
  -v staqly-data:/data \
  --read-only --tmpfs /tmp:size=64m,mode=1777 \
  --cap-drop ALL --security-opt no-new-privileges:true \
  --memory 640m --pids-limit 256 \
  ghcr.io/staqly/staqly:latest

Docker pulls the image the first time. After a few seconds docker ps shows the container as healthy. With --restart unless-stopped it starts again with Docker (and with your computer, if Docker starts at login) until you stop it.

Sign in to the dashboard

Every browser signs in once, this computer included. On first start staqly made an access token, the one key of your install; print it with a link that signs the browser in:

docker exec staqly server token
stk_local_dkzqs4w2v7hn3mxa6rjtbye5cfgu8pql2nwo4ks7vd3h6mxzaqbt
Sign a browser in: http://localhost:8080/#token=stk_local_dkzqs4w2v7hn3mxa6rjtbye5cfgu8pql2nwo4ks7vd3h6mxzaqbt

Open the link (the token stays in the part after #, which never reaches a server), or open http://localhost:8080 and paste the token. docker logs staqly shows the same link from every start.

Phones and tablets scan the QR code from Connect a device instead. The container can't see your computer's Wi-Fi address, so the first time the dialog asks for it (for example 192.168.1.23) and remembers it in this browser; -e PUBLIC_DASHBOARD_URL=http://192.168.1.23:8080 sets it for every browser. See Phones & tablets.

Connect an agent

Agents and scripts use http://localhost:3333 and http://localhost:3333/mcp with the access token as Authorization: Bearer (export STAQLY_API_KEY=$(docker exec staqly server token)) — see Connect an agent. docker exec -i staqly mcp-stdio needs no token.

What the flags do

FlagWhy
-p 127.0.0.1:3333:3333The API and MCP endpoint, on this computer only. Every request needs the access token anyway; keeping the port off the network is defense in depth.
-p 8080:8080The dashboard, reachable from your network so phones can use it. Every browser signs in once.
-v staqly-data:/dataThe named volume with the database, uploads, keys and the access token. Removing or upgrading the container keeps it.
--read-only, --tmpfs /tmp:...Immutable root filesystem; all state lives in /data, plus a small /tmp.
--cap-drop ALL, --security-opt no-new-privileges:trueNo Linux capabilities, no privilege escalation. The image already runs as an unprivileged user (uid 10001).
--memory 640m, --pids-limit 256Bounded memory and processes. Raise --memory for large uploads or many channels publishing at once.
--restart unless-stoppedStarts again after a crash or a reboot, until you docker stop it.

Keep the API on 127.0.0.1

With -p 3333:3333 other computers on your network could reach the API: they would still need the access token, but there is no reason to offer it to them. Containers that call staqly (n8n) reach it over a Docker network instead.

Everyday commands

CommandDoes
docker exec staqly server tokenPrints the access token and a link that signs a browser in
docker exec staqly server token --rotateMakes a new access token: the old one stops working and every browser is signed out
docker exec staqly server connect-linkPrints a one-time sign-in link for a browser (5 minutes, single use)
docker logs -f staqlyFollows the logs (JSON lines; see Logs & tracing)
docker ps --filter name=staqlyShows whether it runs and is healthy
docker stop staqly / docker start staqlyStops / starts it again (the data volume is kept)
docker exec -i staqly mcp-stdioMCP over STDIO for clients without HTTP support — see MCP
docker exec staqly server <command>Operator commands: token, connect-link, backup, storage migrate

Backups use docker exec staqly server backup — see Backup & restore.

Settings

Pass settings with -e NAME=value, or put them in a file and add --env-file staqly.env to docker run. All variables are on Configuration. A container keeps the settings it was created with: to change one, remove the container and run it again (the data stays in the volume):

docker rm -f staqly
docker run -d --name staqly ... -e LOG_FORMAT=text ghcr.io/staqly/staqly:latest   # the full command from above

For example, -e LOCAL_USER_NAME="$USER" shows your name instead of Local in the activity log.

Other ports

The host ports are the left side of -p. The image listens on 3333 and 8080 inside the container; tell staqly the host ports so links, QR codes and snippets point to them:

docker run -d --name staqly --restart unless-stopped \
  -p 127.0.0.1:4333:3333 -p 9090:8080 \
  -e PUBLIC_API_URL=http://localhost:4333 -e DASHBOARD_PORT=9090 \
  ...

Update your MCP client URLs to the new API port.

Reach n8n on this computer (Linux)

Docker Desktop (macOS, Windows) resolves host.docker.internal to your computer. On Linux, add --add-host host.docker.internal:host-gateway so webhooks can reach n8n or other receivers running on the host. See n8n.

Data

All state is in the volume staqly-data, mounted at /data:

/data/workspace.db          SQLite database (WAL: -wal / -shm side files while running)
/data/uploads/              media files, one folder per workspace (uploads/workspaces/<id>/)
/data/access_token          the access token every request needs (created on first start, owner-only)
/data/secret.key            key for channel credentials and developer app secrets (created on first start, unless STAQLY_SECRET_KEY is set)
/data/notify_secret.key     key for alert secrets (created with the first alert, unless NOTIFY_SECRET_KEY is set)
/data/backups/              scratch space for server backup

Back it up with Backup & restore. To delete everything:

docker rm -f staqly
docker volume rm staqly-data     # deletes the database and uploads for good

Upgrade

Back up first, then pull the new image and recreate the container with the same command:

docker pull ghcr.io/staqly/staqly:latest
docker rm -f staqly
docker run -d --name staqly ... ghcr.io/staqly/staqly:latest   # the full command from above

Migrations run automatically on start. To stay on one release, use its tag instead of latest, for example ghcr.io/staqly/staqly:v0.2.0. See Upgrades.

The image

ghcr.io/staqly/staqly is published for linux/amd64 and linux/arm64 with every release (:v0.2.0, and :latest for the newest), the same version as the staqly binary. It runs one process (server) as uid 10001 and is health-checked via /health and the dashboard. The dashboard relays /api/* to the API in the same process without buffering request bodies, capped at 110 MB (the API's default upload limit is 100 MB); larger bodies get 413 too_large.

Binaries in the image: server (the server and its operator commands) and mcp-stdio.

Working on staqly itself? Develop with Docker Compose builds the image from a checkout.

Next steps

On this page