Skip to main content

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.

ServerWorker
Serves HTTPYes, :4317 — API and web UINo
Executes runsOptionally, in-processYes, that's its whole job
ScalesOneFreely

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.

PathWhat
state.dbSQLite: runs, projects, users, config overrides
runs/Per-run logs and artifacts
secret.keyEncryption key, mode 0600, generated if FW_SECRET_KEY is unset
initial-admin-passwordFirst-boot bootstrap password, mode 0600
flowwright.server.yamlConfig 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.