Files
app/docs/reference/configuration.md
T
stroblmeandClaude Opus 5 6111b90747
Docs / docs (push) Successful in 33s
Playwright Tests / test-playwright (1, 2) (push) Failing after 2m56s
Playwright Tests / test-playwright (2, 2) (push) Successful in 1m46s
pre-commit / pre-commit (push) Failing after 1m59s
Test Backend / test-backend (push) Failing after 2m23s
Compose Smoke Test / test-compose (push) Successful in 32s
Playwright Tests / merge-reports (push) Successful in 1m18s
Document the dashboard, the artifacts command and what moved with them
Covers this round of CLI work: the serve dashboard and its keys, the refusal
to start a second engine for one installation, --plain, --gpus and the
declared-not-detected card count, `fluksio artifacts`, the age column,
`fluksio.logger` inside a node, the server extra, per-directory study module
names, and an export whose columns no longer move with the selection.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Hra4ndWMCLU5F3KjUuVAc
2026-08-29 14:24:24 +02:00

9.9 KiB

Configuration

Every setting comes from the environment, or from an env file. Which file depends on how the installation was started:

Started with Reads
fluksio serve env inside the data directory ($FLUKSIO_ENV_FILE)
the Docker stack .env beside docker/

Anything already exported wins over the file.

Storage

Variable Default Notes
DATA_DIR flow-data (./.fluksio via the CLI; ~/.fluksio with --global) everything below derives from this
DATABASE_URL SQLite in DATA_DIR any SQLAlchemy URL
FLOWS_DIR $DATA_DIR/flows the git repository holding flows
SECRETS_FILE $DATA_DIR/secrets.enc encrypted credentials, deliberately outside the repo
ALERTS_FILE $DATA_DIR/alerts.json channels and rules
PROVISIONERS_FILE $DATA_DIR/provisioners.json clusters a machine can be started from; absent means none
PANELS_FILE $DATA_DIR/panels.json wall-panel pairings
OAUTH_PRIVATE_KEY_FILE $DATA_DIR/oauth-key.pem signs agent and worker tokens
CLOUD_CONFIG_FILE $DATA_DIR/cloud.json the portal enrolment, if any
NODE_VENV auto which interpreter node code runs on — see below

Set DATA_DIR and the rest follow. Set one explicitly and it wins — which is what the container images do to pin everything onto /data.

NODE_VENV is the exception, being about an environment rather than a path:

Value What node code runs on
auto (default) the venv Fluksio was installed into, when it was installed into one and there is no venv of its own already built. pip install fluksio beside your own packages is this case, and the packages are then already there — the Modules screen turns read-only, because that environment is not Fluksio's to install into.
managed a venv the engine builds under DATA_DIR and owns, which the Modules screen installs into with uv pip sync. The container images set this: the venv in them holds the app and nothing of anybody else's.
a path that interpreter, or that venv, whatever it is.

An installation that already has a managed venv keeps it on upgrade under auto, because it may hold packages somebody installed on purpose.

!!! warning "The four files that must be on persistent storage"

`secrets.enc`, `alerts.json`, `panels.json` and `oauth-key.pem` are written
at runtime. In a container, anything not on a volume lands in the writable
layer and is lost on the next rebuild — un-pairing every screen and
revoking every agent.

State

Variable Default Notes
REDIS_HOST unset without it, flow state lives in memory and does not survive a restart
REDIS_PORT 6379

Flow state is the last value of every message, node memory, and the run queue. Redis here is persistence, not a cache — run it with append-only persistence on.

Identity and access

Variable Default Notes
SECRET_KEY generated signs sessions and derives the secrets-store key
ACCESS_TOKEN_EXPIRE_MINUTES 11520 (8 days)
FIRST_SUPERUSER absent means the CLI creates one on first run
FIRST_SUPERUSER_PASSWORD absent means one is generated and printed once
DOMAIN localhost what the API and OAuth issuer are built from
FRONTEND_HOST http://localhost:5173 used in mails, OAuth metadata and panel pairing links
BACKEND_CORS_ORIGINS [] comma-separated; FRONTEND_HOST is always allowed

Where the interface looks for the API

The dashboard is a static bundle, so this one is a build argument of the frontend image rather than a setting the running stack reads.

Argument Used by Effect
VITE_API_URL frontend at build time the address the interface calls

The compose stack takes it from .env, falling back to https://api.${DOMAIN}. scripts/setup.sh writes it there with the scheme ENVIRONMENT implies, so a local build calls http:// and does not fail a certificate check nothing is there to satisfy.

Empty is the useful value: the interface then addresses the API relative to whichever origin served the page, so one image answers on a hostname, on a http://<host-ip>:<port>, and through an ssh tunnel alike — and no origin has to be added to BACKEND_CORS_ORIGINS, because there is only one. docker/compose.lan.yml builds it that way and puts an /api proxy in front of the backend to complete it; see getting started.

Set it to an absolute URL only when the API genuinely lives somewhere else, and remember it is fixed at build time: changing it means rebuilding that image.

!!! danger "Rotating SECRET_KEY"

The secrets store is encrypted with a key derived from it. Change it and
the store stops decrypting, and every session is signed out. Re-enter your
secrets, or plan the rotation properly.

Environment

Variable Default Notes
ENVIRONMENT local local, staging or production
PRIVATE_API_ENABLED false unauthenticated test-only endpoints; needs ENVIRONMENT=local too
TZ UTC the timezone every schedule is written in

TZ is the container's own, not a setting the code reads: an inject or a delay with a cron expression fires on local time. Left at UTC, "off at 02:00" means two in the morning UTC, which in most of the world is neither two o'clock nor the same hour in summer as in winter. Set it to where the installation is.

production closes /docs, /redoc and the OpenAPI document, because the schema enumerates every endpoint the installation serves — including the paths webhook nodes mounted at runtime. It also turns a changethis secret from a warning into a refusal to start.

The engine

Variable Default Notes
FLOW_MAX_WORKERS 4 node-code subprocesses run in parallel
FLOW_MAX_CASCADES 4 cascades in flight at once; throughput is this over the mean cascade time, so raise it where nodes wait on a network rather than a CPU
FLOW_MAX_RUNS 4 batch runs driven at once. A different limit from the one above: a run drives a whole graph, and its nodes are bounded by FLOW_MAX_WORKERS. This is what a sweep queues behind
FLOW_NODE_TIMEOUT 0 seconds a node may be silent, unless it sets its own; 0 is no limit
FLOW_CPUS 0 cores nodes that declare resources may be given; 0 works it out as every core but two, which are what keeps the engine answering while the machine is busy
FLOW_GPUS 0 GPUs on this machine, each held by one node at a time. Not detected — say how many there are
OBS_RETENTION_DAYS 30 how long metrics, events and run records are kept
ARTIFACT_GC_INTERVAL_S 3600 how often artifact bytes nothing refers to are swept away; 0 never sweeps
ARTIFACT_GC_GRACE_S 3600 how long a freshly written artifact is spared, whatever refers to it

The three concurrency limits are also flags on fluksio serve--max-workers, --max-cascades, --max-runs — as is the card count, --gpus. The flags outrank the file, and the engine says which numbers it started with in its first lines. Each pool size must be at least 1 and the card count at least 0: a number below that is refused as a flag error naming it, rather than read as the default. Leave one empty (or unset) to get the default.

An artifact is referred to by a run that recorded it or by a message currently holding it; anything else is what a camera published four hours ago, and the sweep is what keeps a flow streaming media from filling the disk. It stands aside entirely while a run is in flight, since a node may store a checkpoint long before it returns the reference to it.

A node that declares nothing is not accounted against FLOW_CPUS; it runs on the shared pool and is given FLOW_CPUS / FLOW_MAX_WORKERS as a thread cap, so several at once cannot each size themselves to the whole machine. Setting OMP_NUM_THREADS (or any of its siblings) on the engine yourself overrides that default.

These two are this machine's figures. An attached worker reports its own when it dials in, and a node goes to whichever machine can grant what it asked for — so a GPU on a worker needs no FLOW_GPUS here. What every machine has free, and which nodes are queued, is GET /api/v1/workers/resources and the Workers screen. Named sizes live in the database and are GET /api/v1/flavors; PROVISIONERS_FILE is where machines can be started from. See declaring resources.

Agents

Variable Default Notes
MCP_ENABLED false opens the /mcp endpoint and OAuth client registration
MCP_TOKEN_EXPIRE_MINUTES 60 an agent's token is a bearer secret held by a program
MCP_REFRESH_EXPIRE_DAYS 30
OAUTH_CODE_EXPIRE_SECONDS 60

See Agents over MCP.

Mail

Needed for password-reset mails. Without SMTP_HOST and EMAILS_FROM_EMAIL, mail is simply off.

Variable Default
SMTP_HOST
SMTP_PORT 587
SMTP_USER / SMTP_PASSWORD
SMTP_TLS / SMTP_SSL true / false
EMAILS_FROM_EMAIL
EMAILS_FROM_NAME Fluksio
EMAIL_RESET_TOKEN_EXPIRE_HOURS 48

Monitoring

Variable Default Notes
SENTRY_DSN error reporting, if you want it

Health check

GET /api/v1/utils/health/ is a deep check: it fails when the event loop is wedged or the state backend is gone, not just when the process is up. That is what the container healthcheck probes, and what an autoheal sidecar restarts on.

See also