Self-hosting
Everything else on this site is the CLI: one binary, running pipelines on your machine or in someone else's CI. This section is the other half — the server and worker that run pipelines for a team, keep history, and put a UI in front of it. What that UI actually does is the control plane.
You don't need them. flow run in your existing CI is a complete story. Run
the server when you want runs triggered centrally, history that outlives a job, and
people who log in.
Two daemons, one image
$ docker run -d -p 4317:4317 -v flowwright-data:/data flowwrightdev/flowwright
That's the server. The worker is the same image with a different command:
$ docker run -d -v flowwright-data:/data --no-healthcheck \
flowwrightdev/flowwright /app/apps/worker/dist/main.js
No separate image, no environment variable selecting a mode — the entrypoint is node
and the argument decides. See Docker Compose for
running both.
| Server | Worker | |
|---|---|---|
| Serves HTTP | Yes, :4317 — API and web UI | No |
| Executes runs | Optionally, in-process | Yes, that's its whole job |
| Scales | One | Freely |
The server can execute in-process (FW_WORKERS, default 2) or delegate everything by
setting FW_WORKERS=0 and running separate workers. The published compose file does the
latter.
What's on npm and what isn't
The applications are container-only. server-host, worker-host and the web UI are
private packages — there is no npm install that gets you a server. The Docker image is
the distribution.
Their libraries are published, though, and that's deliberate:
@flowwright/control-plane, @flowwright/runtime, @flowwright/api-contract, the store
and provider packages. If you want to embed the control plane in something of your own,
that's the supported path. What you can't do is npm install the assembled server.
State
Everything lives under the data directory — FW_DATA_DIR, defaulting to .flowwright
relative to the working directory. In the container that's /data/.flowwright, which
is why the image runs from /data and you mount a volume there.
| Path | What |
|---|---|
state.db | SQLite: runs, projects, users, config overrides |
runs/ | Per-run logs and artifacts |
secret.key | Encryption key, mode 0600, generated if FW_SECRET_KEY is unset |
initial-admin-password | First-boot bootstrap password, mode 0600 |
flowwright.server.yaml | Config file, if you use one |
All of it must persist. Losing secret.key means every stored credential is
unrecoverable.
Which shape to run
Single host. SQLite plus a shared volume. The server and every worker mount the same
/data, and the SQLite database is the queue. Simple, and what compose gives you. The
constraint is that everything must see the same filesystem.
Multiple hosts. PostgreSQL for state and S3 for artifacts, selected by
FW_DATABASE_URL and FW_ARTIFACTS_S3_BUCKET. No shared filesystem required, so workers
can live anywhere. Everything else is identical — same image, same commands.
You can start on the first and move to the second; the selection is two environment variables.
Read next
- Docker Compose — the fastest real deployment
- Configuration — every key, and where it wins
- Authentication — first boot, roles, tokens
- Operations — health, backups, upgrades
- Control plane — the web app your team logs into