Skip to main content

Installer Reference

For help choosing each answer, use Answer the Installer Questions. This reference is checked against application revision 1a66a0490e (version 0.7.27) on 2026-10-26. The field contract is core/application/installer/spec.py; the private adapter is core/entrypoints/cli/installer.py.

Command boundary and prerequisites​

./install.sh
./install.sh --plain
./install.sh --non-interactive --confirm [options]

The installer has no public subcommands. Post-install management uses ./flow-steward; see CLI Reference. Both Compact and Scalable checkout installs require an already installed, running local Docker Engine/Desktop with Linux containers and Compose v2. Verify docker --version, docker compose version, and docker info. Flow Steward does not install Docker automatically. See Getting Started for setup links.

The normal launcher builds a pinned installer image, mounts the checkout and local Docker socket, mounts explicitly supplied external input files read-only, and runs the private controller. A remote Docker endpoint is unsupported. Use FS_INSTALLER_USE_HOST_PYTHON=1 only as a local-development fallback. The checkout must be a Git checkout with a resolvable revision; Git LFS is not used. The installer refuses to run as root (exit 4) and refuses subcommands such as ./install.sh up (exit 2). The host preflight accepts only amd64 (x86_64) and arm64 (aarch64) hosts (unsupported_architecture otherwise) and rejects less than 4 GiB free space (insufficient_disk_space); that minimum is not a production sizing recommendation. Linux servers, Docker Desktop on macOS, and Windows through WSL or Git Bash are the supported launch environments.

Global options​

OptionMeaning
--jsonEmit one JSON document and do not prompt (implies --non-interactive). Fresh installation still needs --confirm. The live setup link is printed separately to stderr.
--plainUse line-oriented interaction, also the default without --tui.
--tuiOpt into the full-screen form; advanced fields are behind Show advanced.
--no-colorDisable color.
--verboseRequest redacted technical output; ordinary non-JSON installation also streams progress/technical output.
--non-interactiveNever prompt; every field not given as an option takes its default. A fresh install requires --confirm. Without a terminal on stdin the installer never prompts either.
--confirmConfirm the fresh-install plan.
-h, --helpShow launcher/private installer help.

Plain mode uses numbered choices and asks visible advanced fields directly. Command-line values skip their corresponding plain questions. Review is Review pending change: followed by Apply this change?, default No. Conditional visibility controls questions, not whether incompatible CLI values are valid; model validation enforces the combinations below.

Installation fields​

“Always” means no field visibility condition. “Advanced” applies to the full-screen form; it does not hide the question in plain mode.

Exact labelOptionDisplayed default / valuesVisible when
Environment--environmentproduction (Production); development (Development)Always
Deployment profile--deployment-profilecompact (Compact single-runtime deployment); scalable (Scalable multi-container runtime)Always
Compact runtime HTTP port--runtime-http-port8080Compact; advanced
Ingress owner--ingress-modebundled_traefik (Bundled Traefik); external_traefik (Existing Traefik); external_proxy (Existing reverse proxy); platform (Hosting platform ingress)Always
Compact worker processes--worker-processes2Compact
File storage--file-storagebundled (Bundled self-hosted storage); also local_fs (Local persistent filesystem), external_s3 (External S3-compatible storage)Always
S3 endpoint--s3-endpointNo default; requiredExternal S3
S3 bucket--s3-bucketflow-steward-artifactsExternal S3
S3 region--s3-regionus-east-1External S3
S3 credentials file--s3-credentials-pathNo default; required; private JSON input pathExternal S3
Allow insecure S3 HTTP--allow-insecure-s3-httpFalseExternal S3
Network and TLS--tls-modelocal; full labels/pairs belowAlways
Public host (domain or IP)--public-hostlocalhostAlways
Public port--public-port8099Always
Plain-HTTP redirect port--redirect-http-port8080Bundled Traefik; advanced
Reverse-proxy backend host--reverse-proxy-backend-host127.0.0.1; validator requires this exact valuereverse_proxy TLS
Reverse-proxy backend port--reverse-proxy-backend-port18099reverse_proxy TLS
Reverse-proxy MCP port--reverse-proxy-mcp-port18100; separate MCP host backend is used by ScalableExisting reverse proxy; advanced
Proxy placement--proxy-placementhost (Host); docker (Docker network)Existing reverse proxy
Proxy kind--proxy-kindnginx (Nginx); apache (Apache)Existing reverse proxy
Trusted proxy CIDRs--proxy-trusted-ips127.0.0.1/32,::1/128; comma-separated immediate peersAlways; advanced
Existing Traefik network--traefik-networkNo default; required for existing TraefikExisting Traefik
Traefik HTTPS entrypoint--traefik-https-entrypointwebsecureExisting Traefik; advanced
Traefik HTTP entrypoint--traefik-http-entrypointweb; empty value omits the optional HTTP redirect overlayExisting Traefik; advanced
Traefik certificate resolver--traefik-cert-resolverNo default; required for external_resolverexternal_resolver TLS
Existing proxy network--proxy-networkNo default; required for Docker existing proxyproxy_placement=docker
ACME contact--acme-contactNo default; required for ACMEacme TLS
ACME directory URL--acme-directory-urlNo default; required for ACMEacme TLS; advanced
Extension installer origin--extension-installer-originhttp://fs-extension-installer:8099Always; advanced
Certificate path--certificate-path.ssl/cert.pemAlways; advanced
Private key path--private-key-path.ssl/key.pemAlways; advanced

Compact storage: the File storage default, bundled, is the Scalable default. On Compact, that default becomes local_fs unless --file-storage is given on the command line. An answer of Local persistent filesystem or External S3-compatible storage (with its S3 settings) is kept, in plain mode, --tui and non-interactive runs alike; the review shows the final value. For bundled storage on Compact pass --file-storage bundled. Scalable keeps the prompted or supplied value.

Ports must be 1–65535. Compact worker processes must be at least 1 (the source upper bound is 56336, not a recommended operating value). Public host is a bare hostname/IP, not a URL. The derived origin uses HTTPS and omits :443 when 443 is selected. Existing-proxy host backends are private HTTP; Docker placement uses network aliases/container ports and publishes no corresponding host port.

Valid profile and TLS combinations​

Ingress ownerPermitted Network and TLS choices
Bundled Traefik (bundled_traefik)Local/private generated certificate (local, default); Hostname generated certificate (self_signed); Operator-provided certificate (provided); Bundled ACME certificate (acme)
Existing Traefik (external_traefik)Existing Traefik resolver (external_resolver); Existing Traefik certificate (external_certificate)
Existing reverse proxy (external_proxy)Existing reverse-proxy TLS (reverse_proxy)
Hosting platform ingress (platform)Hosting platform TLS (platform_managed)

Compact requires Production. Hosting platform ingress requires Compact. Development is the complete contributor preset and uses Scalable. The plain TLS menu displays all choices; incompatible owner/TLS pairs fail validation. For non-interactive invocations, an explicitly supplied --tls-mode can infer its matching ingress owner when --ingress-mode is omitted. For a guided run, choose both consistently, or pass both options explicitly.

External Traefik needs an existing Docker network; the preflight checks that it exists and has an attached container. That is not proof of a correctly configured Docker provider, router, resolver or certificate. Docker placement for Apache/Nginx needs --proxy-network. Trusted proxy addresses reject wildcard networks such as 0.0.0.0/0 and ::/0. See the walkthrough's network, resolver and trusted-peer discovery instructions.

For public bundled ACME, set the real hostname, public port 443, redirect port 80, contact email and CA directory URL explicitly. The source uses HTTP-01. DNS, public reachability and certificate issuance remain operator prerequisites. Local/generated TLS is not a publicly trusted certificate.

Non-interactive examples​

Every question has an option, so an installation can run without prompts. A fresh installation needs --confirm; omitted fields take the defaults in the table above (on Compact, the bundled storage default becomes local_fs).

Local trial with all defaults (Compact, https://localhost:8099):

./install.sh --non-interactive --confirm

Public VPS, Compact, bundled Traefik with a Let's Encrypt certificate:

./install.sh --non-interactive --confirm \
--deployment-profile compact \
--ingress-mode bundled_traefik --tls-mode acme \
--public-host flow.example.com --public-port 443 --redirect-http-port 80 \
--acme-contact ops@example.com \
--acme-directory-url https://acme-v02.api.letsencrypt.org/directory

Nginx already on the host terminates HTTPS (the ingress owner is inferred from --tls-mode reverse_proxy when --ingress-mode is omitted):

./install.sh --non-interactive --confirm \
--tls-mode reverse_proxy --proxy-kind nginx \
--public-host flow.example.com --public-port 443

Then print the routes to add to your Nginx site with ./flow-steward proxy-fragment. Add --json to any of these to get one JSON result document on stdout; the setup link still goes to stderr.

File and credential input contract​

Relative paths must remain inside the checkout. Generated TLS output must stay inside it. Guided file inputs outside it are not mounted automatically: pass an existing absolute input path through --certificate-path, --private-key-path or --s3-credentials-path when launching. For external TLS inputs also pass --tls-mode provided. The launcher mounts those inputs read-only. Expand ~ before invocation; do not use ../ escape paths.

The installer S3 file is regular, not a symlink, with permissions 0600 or stricter, and contains access_key and secret_key. Do not substitute the aws_access_key_id / aws_secret_access_key format used by a later lifecycle storage-transition command. Production S3 endpoints require HTTPS; HTTP requires both Development and --allow-insecure-s3-http. Storage verification needs write/read/delete access.

--extension-installer-origin is a credential-free internal HTTP origin with an explicit port and no path, query, or fragment. Keep its default for the standard topology. Certificate/key fields remain visible even when another ingress owns TLS; they do not configure that external owner.

Reverse-proxy fragment​

./flow-steward proxy-fragment --json

This read-only command works in both profiles after installation configuration and CLI readiness. It requires external_proxy ingress and returns proxy_kind, proxy_placement, public_host, app_backend, mcp_backend, and fragment in the result. It selects the backend from the recorded placement, ports and project aliases. The fragment uses an HTTP port-80 virtual host and contains no TLS certificate configuration. Adapt its routes into the existing HTTPS site; see the walkthrough's Nginx and Apache examples. The installer does not install/reload that external configuration.

Source limitation: the reverse-proxy readiness probe targets a host backend port even with Docker placement, whose overlay publishes no host backend port. That can block completion of the Docker Apache/Nginx branch; it remains unverified end to end for this revision. Host reverse-proxy verification checks private HTTP, so successful installer output is not proof of external HTTPS, DNS or firewall correctness.

State classification and resume​

StateBehavior
freshCollect/review configuration and start a journaled operation.
resumableReuse journaled configuration and rerun steps whose postconditions do not hold.
installedVerify/reconcile the recorded installation; changed source enters the image/update path. Asks no questions. Rerunning the installer is not a read-only health check.
ambiguousPreserve detected resources and refuse mutation until the reported identity, journal, secret, or configuration issue is resolved.

Journaled steps cover preflight, configuration, durable secrets, TLS, images, core start, schema/seed verification, worker identity, application runtime, health, CLI runtime, storage probe, route probe, first-admin bootstrap, and initial preservation manifest. Resume from the same checkout. An operation that cannot recover cleanly may report recovery_required; inspect the error and ./flow-steward doctor before retrying. Never delete state/volumes to bypass the guard. See Installation and Updates for update behavior and supported deployment changes.

Rerunning on an installed system​

./install.sh on a completed installation reads the applied configuration (.flow-steward/stack.toml), not the spec defaults, and asks nothing. It then:

  1. Finishes an interrupted profile switch, or switches profile when --deployment-profile names the other profile.
  2. On Compact, applies --worker-processes N when it differs (prints Compact worker processes: <old> -> <new>.). This is the only setting a rerun changes. Any other option whose value differs from the installed one stops with installed_setting_not_applied (exit 7) before anything changes. On Scalable the message names ./flow-steward config set ... and config apply --confirm as the way to change it.
  3. Compares the checkout's commit with the revision the running images were built from. When they differ it runs the update steps: preflight, image build, a migration check against the database, core start, schema check, worker identity, runtime, health and CLI runtime. The output says Updated from <old> to <new>.
  4. Otherwise starts stopped services, verifies health, storage, the public route and bootstrap, and prints Flow Steward is already installed. An expired first-administrator link is reissued while no administrator exists.

If the update carries a database migration, step 3 stops with release_migration_required (exit 8) before any running service is restarted. Image variables such as FS_COMPACT_IMAGE or FS_APP_IMAGE set in the shell mark those images as yours: they are not rebuilt, and the run warns that the runtime is behind the checkout.

Environment variables read by the launcher​

./install.sh forwards only these variables from your shell into the installer container. Everything else is an answer or option above.

VariableEffect
FS_COMPOSE_PROJECT_NAMEDocker Compose project name for a new installation (default flow-steward). Use a unique name for a second installation on the same host; it is recorded and reused.
HTTP_PORT, POSTGRES_HOST_PORT, RABBITMQ_AMQP_HOST_PORT, RABBITMQ_MANAGEMENT_HOST_PORT, SEAWEEDFS_S3_HOST_PORT, SEAWEEDFS_MASTER_HOST_PORT, MCP_HOST_PORT, FRONTEND_HOST_PORT, MAILPIT_*_PORT, SONAR_PORTHost port overrides for the Compose services that publish one. Prefer --redirect-http-port over HTTP_PORT.
FS_COMPACT_IMAGE, FS_APP_IMAGE, FS_WORKER_IMAGE, FS_CONTROL_IMAGE, FS_CLI_IMAGE, FS_FRONTEND_IMAGE, MCP_IMAGE, POSTGRES_IMAGE and FS_COMPACT_IMAGE_REGISTRY_REF, FS_COMPACT_IMAGE_REVISION, FS_COMPACT_IMAGE_PLATFORMUse these existing images instead of building them. Leave unset for a normal checkout installation.
FS_RELEASE_REPOSITORY, FS_RELEASE_REGISTRIESWhere official releases and their images are looked up.
AWS_CA_BUNDLEExtra CA bundle for an external S3 endpoint.
NO_COLOR, TERMTerminal output.

Read by install.sh itself: FS_INSTALLER_IMAGE (installer image tag, or an exact sha256: image to reuse), FS_INSTALLER_STATE_DIR (state root, default .flow-steward), FS_INSTALLER_HEARTBEAT_SECONDS (progress heartbeat while the installer image builds, default 5), and FS_INSTALLER_USE_HOST_PYTHON=1 with PYTHON_BIN (development fallback without the installer container).

Exit codes​

CodeMeaning
0Installed, updated, or already installed and verified.
2Invalid usage, such as a subcommand.
3Validation failed: an invalid value or ingress/TLS pair, or a bad file path.
4Precondition failed: run as root, port in use, not enough disk.
5A required file or repository path is unreadable.
7Docker, Compose or another dependency is unavailable, the host is unsupported, or a setting cannot be applied by a rerun.
8A step failed after it started, such as a health or schema check.
9Recovery required: the installation state needs inspection before a retry.
10Cancelled or interrupted, including a fresh non-interactive run without --confirm.
70Unexpected internal error; read the printed log path.
127The Docker CLI or a required POSIX utility (awk, sed, stat, ...) is not on PATH.

Generated state and first administrator​

Default paths are relative to the checkout:

  • .flow-steward/install-state.json: installer journal.
  • .flow-steward/logs/install-*.log: owner-only operation logs.
  • .flow-steward/stack.toml, pending-config.json, and compose.env: active, pending and generated deployment state.
  • .env.prod or .env: runtime environment created by the installer, with generated passwords and keys. Keys the installer owns are rewritten on every run; other lines are kept.
  • .flow-steward/runtime/: runtime material including bundled-storage credentials and bootstrap-token state.
  • .flow-steward/secret-output/bootstrap-token: owner-only setup-token output.
  • The initial preservation manifest and release/pending-release records under installer-managed state.

On Linux with systemd and the system Docker daemon, a successful Compact installation also asks for sudo and installs flow-steward-<compose-project>.service to start the installation after a reboot; see Linux VPS automatic startup.

An explicit FS_INSTALLER_STATE_DIR relocates the installer state root; use the printed paths. Do not hand-edit installer-owned environment keys, stack.toml, compose.env, credentials, journals, or locks: the next run rewrites or rejects them. Change an installed configuration with the commands in Rerunning on an installed system.

A normal checkout installation, including loopback, prints a private /bootstrap#setup-token=... link valid for 60 minutes. Open it to create the first administrator, then sign in. Its complete secret-bearing link is excluded from JSON results and printed to stderr. If it expires while there is still no administrator, rerun ./install.sh for a new link. Normal installed loopback bootstrap also requires this token; a plain URL is not a substitute for the complete setup link. Standalone Compact can self-mint a separate startup link with a 15-minute lifetime. No AI-provider credential is required to install core.

Verification boundary​

This is a source review, not a new installation acceptance run. Docker-proxy readiness and Compact storage normalization have the limitations named above. No live VPS, external proxy, ACME CA, or S3 service was changed or tested for this documentation pass. Run ./flow-steward status and ./flow-steward doctor, open https://<host>/health/ready in a browser, and use the walkthrough's browser, WebSocket and MCP checks before treating a deployment as ready.