Local development

Three patterns for running Flux on a laptop — bare pip install, docker-compose for the full stack, and devcontainer / nix recipes.

Three patterns cover the laptop case. Pick the lightest one that fits the workflow you’re prototyping; switch up only when you hit its ceiling.

1. Bare pip install

The simplest path. Two terminals, no containers, SQLite on disk.

pip install flux-core
flux start server                # terminal 1
flux start worker my-worker      # terminal 2

Workers need a bootstrap token. The server auto-generates one on first start and writes it to <FLUX_HOME>/bootstrap-token (default ~/.flux/bootstrap-token, mode 0600). Either let the CLI read it back:

export FLUX_WORKERS__BOOTSTRAP_TOKEN="$(flux server bootstrap-token)"
flux start worker my-worker

…or print and copy:

flux server bootstrap-token
# 8a3f...  (64 hex chars)

The worker crashes at startup if FLUX_WORKERS__BOOTSTRAP_TOKEN is missing or whitespace-only. There is no fallback.

Storage

Persistent state lives in .flux/flux.db (SQLite) under whatever directory you ran the server from, unless you’ve set FLUX_DATABASE_URL to a Postgres URL. Workflow definitions, execution history, schedules, and secrets all live in the database; the auto-generated bootstrap token sits next to it as .flux/bootstrap-token. The schema is Alembic-managed and migrates automatically whenever the server opens the database, so upgrading flux-core in place is safe — flux db current shows the revision if you’re curious.

SQLite is a single-node backend: one server plus one colocated worker is the supported shape (the server logs a warning if a second worker registers). That’s exactly the laptop topology — but it means the multi-worker and multi-replica behaviors need the docker-compose pattern with Postgres to reproduce locally.

Resetting state

Stop both processes and delete the directory:

rm -rf .flux/

Next flux start server regenerates schema, regenerates the bootstrap token, and starts fresh. Re-export FLUX_WORKERS__BOOTSTRAP_TOKEN for the worker — the previous value is gone.

For the actual walkthrough — defining a workflow, registering it, running it — see Quickstart.

2. docker-compose for the full stack

When you want the production shape on a laptop: server + workers + Postgres, networked, restartable. Useful for testing schema migrations, exercising the Postgres path before deploying, or running a quick load test against a representative topology.

The compose file lives on Docker; copy it and run docker compose up. From the developer’s seat, the difference vs the bare install is:

The trade-off is rebuild latency. Edit a workflow, register it, and the running server picks it up over the catalog — no rebuild needed. Edit the server’s own code (rare for application developers) and you’re rebuilding the image. Most teams reserve compose for end-to-end testing and stay on the bare install for the inner loop.

3. Devcontainer / nix develop

For teams that want every developer to land in an identical environment, with no “works on my machine” debugging.

Flux 0.56.0 does not ship an official devcontainer or nix flake. The shape you’d author:

Both are community-maintained where they exist. If you build one worth sharing, contribute it to flux-recipes.

The honest summary on this tier: it pays off when you have more than a handful of developers and “set up Flux” is taking real onboarding time. For a solo developer or a small team, the bare pip install is faster to live with.

Picking a pattern

Roughly:

Switching between them is fine — the workflows you author work identically across all three.

What can go wrong

Worker crashes immediately

Symptom. flux start worker my-worker exits with RuntimeError: Worker bootstrap token is not configured.

Cause. FLUX_WORKERS__BOOTSTRAP_TOKEN is unset, or set to whitespace. Workers never auto-generate.

Fix. Export the token before launching the worker:

export FLUX_WORKERS__BOOTSTRAP_TOKEN="$(flux server bootstrap-token)"
flux start worker my-worker

If you’ve rotated the server or deleted .flux/, re-run the export — the old value is invalid.

Permission errors on .flux/flux.db

Symptom. Server crashes with sqlite3.OperationalError: unable to open database file, or workers can’t read state set by a different account.

Cause. You started the server as one user (or via sudo) and the worker as another. SQLite is owned by whoever wrote it first.

Fix. Run both processes as the same user. If you need to recover, chmod -R u+rw .flux/ and chown to your user.

Port 8000 already in use

Symptom. Server exits with OSError: [Errno 98] Address already in use.

Cause. Another process — a previous Flux server you forgot to stop, or an unrelated service — is bound to 8000.

Fix. Either stop the other process (lsof -i :8000, then kill) or pick a free port:

flux start server --port 8001
flux start worker my-worker --server-url http://localhost:8001

A worker started with a plain flux start worker reads its server URL from FLUX_WORKERS__SERVER_URL (or the --server-url flag) — there is no bare FLUX_SERVER_URL config field. The CLI subcommands derive their target from FLUX_SERVER_HOST / FLUX_SERVER_PORT, or accept --server-url per command.

Next