Local-first, TypeScript-native pipeline engine — server + worker
913
A local-first, TypeScript-native pipeline engine for building, testing, and shipping.
Swap sprawling, hard-to-test CI YAML for a typed, reusable pipeline.ts that behaves the
same on your laptop, in any CI provider, and on this optional team server.
This image contains the control-plane server (API + web UI) and the execution
worker. The CLI is distributed separately, on npm as
@flowwright/cli.
FlowWright is currently pre-release. The core workflow already works end to end — we're being upfront that APIs may still shift before the first stable release.
$ docker run -d -p 4317:4317 -v flowwright-data:/data flowwrightdev/flowwright
Open http://localhost:4317.
Authentication is required by default. On first boot the server creates an
administrator and writes a one-time temporary password to
<dataDir>/initial-admin-password (mode 0600), also printing it to the log. Set
FW_AUTH=disabled only when you explicitly want an open, no-auth development server —
it removes the identity boundary entirely and every caller becomes an implicit admin.
The default command runs the server. Override it to run a worker instead:
# server (default)
$ docker run -d -p 4317:4317 -v flowwright-data:/data flowwrightdev/flowwright
# worker — no HTTP server, so the image's healthcheck can't apply to it
$ docker run -d -v flowwright-data:/data --no-healthcheck \
flowwrightdev/flowwright /app/apps/worker/dist/main.js
The container runs as uid 1000 (node), not root. A new volume works with no
setup — Docker initialises an empty volume from the image, ownership included.
A volume created by an earlier, root-running image needs a one-time chown before
you upgrade, or the server exits with unable to open database file:
$ docker compose down # or: docker stop <container>
$ docker volume ls # compose prefixes it: <project>_data
$ docker run --rm -v flowwright_data:/data alpine chown -R 1000:1000 /data
$ docker compose up -d
For a bind mount, sudo chown -R 1000:1000 ./your-data-dir on the host. If you
need to defer the migration, --user 0:0 (or user: "0:0" in compose) restores
the old behaviour — set it on the server and every worker, since a root worker
plus a non-root server leaves run directories the server can't clean up.
The published compose.yml runs an enqueue-only server (FW_WORKERS=0) plus a scalable
worker pool sharing one data volume:
$ curl -O https://raw.githubusercontent.com/Flow-Wright/FlowWright/main/compose.yml
$ docker compose up -d # server + 1 worker
$ docker compose up -d --scale worker=4 # server + 4 workers
Pin a release with FLOWWRIGHT_VERSION=0.1.0 docker compose up -d.
Built for linux/amd64 and linux/arm64.
| Tag | Moves | Use it for |
|---|---|---|
X.Y.Z | never | production — pin an exact release |
X.Y | patch releases | production, if you want patches automatically |
latest | every release | trying it out |
edge | every merge to main | testing an unreleased fix |
sha-<short> | never | reproducing one exact commit |
| Variable | Default | Purpose |
|---|---|---|
PORT / FW_SERVER_PORT | 4317 | HTTP listen port |
FW_DATA_DIR | .flowwright | State, run logs, artifacts, cache, key material |
FW_AUTH | required | required or disabled |
FW_SECRET_KEY | auto-generated | Encrypts stored credentials. Set explicitly, and use the same value on server and workers |
FW_WORKERS | 2 | In-process concurrency; 0 delegates execution to external workers |
FW_CONCURRENCY | 2 | Worker concurrency (FW_WORKERS wins if both are set) |
FW_WEBHOOK_SECRET | — | HMAC secret for GitHub/GitLab webhook ingestion |
FW_DATABASE_URL | — | PostgreSQL URL, for multi-host fleets |
FW_ARTIFACTS_S3_BUCKET | — | S3-compatible bucket for shared artifacts |
FW_LOG_LEVEL | info | debug, info, warn, error |
FW_METRICS_TOKEN | — | Bearer token for scraping /api/metrics |
FW_REGISTRATION_MODE | closed | open allows self-service member sign-up |
FW_CONFIG_FILE | <dataDir>/flowwright.server.yaml | Configuration-as-code path |
Full reference: configuration.
Port 4317 · Volume /data — the container's working directory, so the data dir
lands at /data/.flowwright.
Treat that volume as sensitive: it holds execution state, logs, artifacts, cache data, and encrypted key material.
| Endpoint | Auth | Purpose |
|---|---|---|
GET /healthz | public | Liveness / readiness probes |
GET /api/health | public | Richer status (schema version, store check) |
GET /api/metrics | FW_METRICS_TOKEN | Prometheus text format |
Send SIGTERM for graceful shutdown — traffic, schedulers, GC, and the queue stop before
state closes.
FW_SECRET_KEY explicitly from a secret manager, identical across server and
workers. If unset, a key is generated onto the data volume, where it sits next to the
data it protects.FW_DATABASE_URL) and an S3-compatible bucket
(FW_ARTIFACTS_S3_BUCKET). No shared filesystem needed.See the self-hosting guide for fleets, backups, and retention.
MIT — see LICENSE.
Content type
Image
Digest
sha256:146fe18ff…
Size
134.5 MB
Last updated
about 2 months ago
docker pull flowwrightdev/flowwright