Skip to content

Environments

The env topic manages the lifecycle of the control cluster, the Flui cluster that runs the platform itself: API, dashboard, identity provider and observability backend. Workload clusters (the ones that host user applications) are managed with Clusters and nodes.

env destroy permanently deletes the control cluster and all its data. To delete a workload cluster, use flui cluster destroy, never env destroy.

For a walkthrough of the first install, and of the ways back when a run does not finish, see Get Flui running. This page is the reference.

Provisioning

flui env create

Brings the control cluster up. It prompts when provider credentials or the admin email are missing (see Getting started for the first-run experience).

Terminal window
flui env create # all defaults, streams provisioning live
flui env create --node-size cx32 # pick a specific server size
flui env create --node-count 2 # add two worker nodes
flui env create --region fsn1 # pin a region
flui env create --acme-staging # use Let's Encrypt staging
flui env create -d # detached: queue and exit
flui env create --wait # block with a single spinner instead of streaming logs

Node sizes and region codes are provider-specific: a code that exists on one provider means nothing on another. To see what each provider offers, use flui server-types list:

Terminal window
flui server-types list --provider <name> # all sizes for a provider
flui server-types list --provider <name> --region <r> # filter by region
flui server-types list --provider <name> --json # machine-readable

If you omit --node-size or --region, env create picks the provider’s recommended default for each, so you rarely need to set them.

FlagDefaultDescription
-p, --providerthe profile’s configured providerhetzner, scaleway or ovh. See Profiles and config for what each one needs.
-r, --regionprovider defaultRegion code, provider-specific (flui server-types list --provider <name> to list).
--node-sizeprovider recommendedServer type, provider-specific (flui server-types list --provider <name> to list).
--node-count0Number of worker nodes (0 = master-only).
--disk-sizeincluded with the sizeRoot disk size in GB. Required for network-storage instance types; optional for types that bundle a local SSD.
--[no-]configure-firewalltrueConfigure the firewall after creation.
--firewall-ipauto-detectSource IPs / CIDRs allowed by the firewall (comma-separated).
--acme-stagingfalseUse Let’s Encrypt staging (non-trusted cert, no practical rate limits).
--image-registryghcrWhere builds from GitHub push their images. ghcr keeps them on each owner’s GitHub Container Registry. flui runs a registry on this installation, so connecting GitHub needs no container token. See Where the image is kept.
--image-registry-storagevolumeWith --image-registry flui, where that registry keeps images. volume uses a volume on the control cluster. s3 uses a bucket you connect once the installation is up, with flui registry storage connect, and lets more than one copy of the registry serve builds and pulls.
--no-shared-storagefalseDisable Flui shared storage (NFS+fscache). Falls back to dedicated local-disk placement on each node. See Storage classes and dedicated placement.
--shared-storage-size20Size in GB of the master shared-storage volume (only when shared storage is enabled). Minimum: 10.
--ssh-modecaHow the cluster is reached while it is built. ca enrols this machine’s SSH certificate authority on every node and leaves it there. ephemeral-key creates no authority at all and uses a throwaway key that is revoked and deleted before the run ends. The cluster is then sealed until its owner runs flui env adopt.
--non-interactivefalseNever prompt. A missing answer becomes an error instead of a question, which is what you want from a script or a runner, where a prompt would hang while holding paid resources.
-d, --detachedfalseQueue the operation and exit immediately.
--waitfalseWait for the cluster to be ready before returning, polling the operation instead of streaming logs.
--allow-undersizedfalseSkip the confirmation when --node-size is below the minimum for a control cluster (2 vCPUs, 4 GB, 40 GB): everything Flui runs shares that one node, and an undersized one may never reach ready.
--no-flui-networkfalseLeave the Flui network off, for a control cluster nothing else can reach or a host without WireGuard. Clusters on another provider then cannot be created. Switch it later with flui env overlay.
--latestfalseInstall the rolling development component tags (bootstrap master, :latest images) instead of the versions pinned to this CLI release. See flui version.

By default the command streams the master’s cloud-init log live over SSH, which is the recommended path for interactive use. -d is for scripts and CI, and --wait for degraded modes; see Getting started for the reasons.

Installing on a machine you already own

Pass --host and Flui installs over SSH onto a Linux machine you already have, instead of asking a provider for one. Nothing else about the command changes. The machine has to run Ubuntu 22.04 or 24.04.

Terminal window
flui env create --host 203.0.113.10
flui env create --host box.example.com --user ubuntu --port 2222
FlagDefaultDescription
--hostnoneAddress to install onto. Passing it is what turns this mode on.
--userrootSSH user on that host.
--port22SSH port.
--ssh-keyreuse, else authorize onePrivate key for the host. If omitted, Flui reuses a key that already works, otherwise it authorizes one, asking for the host password once and never storing it. A passphrase-protected key works only when it is loaded in your ssh-agent.
--ssh-passwordnoneHost password for unattended runs. Prefer the FLUI_SSH_PASSWORD variable, so it stays out of your shell history.
--master-public-ip--hostThe address the world should use, when it differs from the one you install over.
--skip-precheckfalseSkip the host readiness check.
--best-effortfalseContinue even when the readiness check reports problems.

Status and credentials

flui env status

One-shot status of the control cluster: state (creating, ready, error or stopped), its nodes and, once it is ready, the health of its services and its addresses.

Terminal window
flui env status

flui env credentials

Shows how to sign in: the public addresses of the dashboard and the API, the bootstrap admin login, and the identity provider’s own console. Secrets are hidden unless you ask for them. The bootstrap password is meant to be changed the first time you log in.

Terminal window
flui env credentials # endpoints, secrets hidden
flui env credentials --format json # machine-readable output
flui env credentials --show-secrets # include secret values
FlagEffect
--format text|jsonOutput format. Default: text.
--show-secretsPrint secret values in plain text. Prefer flui dev creds for local development: it writes them to a file instead of your terminal.

Power state

flui env stop / flui env restart

Power off the control-cluster servers without deleting their volumes, then power them back on. Useful for cutting costs on idle development installations. Both work on Hetzner only.

Terminal window
flui env stop
flui env restart

flui env destroy

Permanently destroys the control cluster. On a provider, that means the servers, their attached volumes and the shared storage are deleted at the provider, and the environment’s private network with them. Data survives only if an active backup policy already covered it.

It asks you to type the cluster’s name back before it starts, and backs up your local profile first. --force skips the question.

Terminal window
flui env destroy
flui env destroy --force # skip the confirmation prompt

On a machine you own, destroy also cleans the machine

There is nothing to delete at a provider, so the leftovers would be on the host itself, and a host left dirty cannot be installed onto again. On a bring-your-own-server installation, destroy therefore tears the host down by default: Flui, the cluster runtime and all their data are removed over SSH, leaving a machine you can install onto again. SSH trust is kept so that flui env create --host can run a second time.

Terminal window
flui env destroy # de-register and tear the host down
flui env destroy --keep-host # de-register only, leave the host as it is
flui env destroy --remove-access # also stop the host trusting Flui at all
flui env destroy --dry-run # print the teardown script, run nothing
FlagEffect
-f, --forceSkip the typed confirmation.
--keep-hostSkip the host teardown. The host stays dirty, and a later install on it fails until it is cleaned.
--purge-hostAsk for the teardown explicitly. It is already the default on your own machine; on a provider-created cluster it is ignored, because the servers are deleted at the provider anyway.
--remove-accessFull decommission: also removes Flui’s SSH certificate trust and its managed key, and re-enables password login, so the host no longer trusts Flui.
--dry-runPrint the host teardown script without running it or deleting anything.
--host, --user, --port, --ssh-keyClean a host when no local record of it survives, such as an install that half-failed or a profile that is gone.

If the host teardown fails, the local records are still removed and the command says so; clean the machine by hand.

flui env reinstall

Sometimes the server is fine and the installation on top of it is not. flui env reinstall wipes Flui off the existing server and runs the install again from the start, without deleting the server, its firewall, its network attachment or its attached shared-storage volume.

Everything inside the cluster is lost: your applications, the database, the dashboard’s state. It is the same data loss as env destroy, but you keep the machine.

Terminal window
flui env reinstall
flui env reinstall --dry-run # print the teardown, run nothing
flui env reinstall --force # skip the typed confirmation
flui env reinstall --detached # start it and exit

It works only on single-node clusters that Flui provisioned on a provider. On your own machine the equivalent is flui env destroy --purge-host followed by flui env create --host again.

Capacity and scaling

flui env capacity

Reports the capacity of the control cluster’s master node (allocatable, used and free CPU and memory) and a sorted list of server types to upgrade or downgrade to, with the monthly cost difference. Use it to plan a flui env scale-master operation, especially when a dedicated workload that has to run on the master (because the control cluster has no free worker to take it) does not fit on the current size. See Storage classes and dedicated placement for how dedicated apps choose a node.

Terminal window
flui env capacity
flui env capacity --top 5 # show 5 candidates instead of 10
flui env capacity --direction upgrade # only larger sizes
flui env capacity --direction downgrade # only smaller sizes
FlagDefaultEffect
--top <n>10Maximum number of candidates listed.
--directionallFilter candidates: all, upgrade, or downgrade.

flui env scale-master / flui env scale-node

Vertically scales the control cluster’s master or a worker node to a different server type. These are planned-maintenance operations: the cluster stops the node accepting new work, powers it down, asks the provider to change the type, powers it back up, re-opens it and waits for the cluster to report healthy. Expect about 3 to 5 minutes of downtime. Applications pinned to the node (a dedicated database, for instance) are unavailable for that window, so snapshot them first. See Storage classes and dedicated placement for the concepts.

Terminal window
flui env scale-master # auto-pick next upgrade candidate
flui env scale-master --type cpx41 # pick a specific type
flui env scale-node flui-cluster-worker-1 --type cpx31
flui env scale-node flui-cluster-worker-1 --type cx32 --confirm
FlagEffect
-t, --type <name>Target server type. If omitted, auto-picks the next-bigger candidate (smallest positive cost delta).
--upgradeDisk(Hetzner) Also grow the local OS disk. This is one-way: a later downgrade cannot reverse it.
--confirmSkip the typed confirmation prompt.

scale-node requires the worker’s full server name as a positional argument (for example flui-cluster-worker-1); an unknown name is refused with the list of known nodes. scale-master takes none (the master is unambiguous).

flui env set-master-protection <on|off|show>

On a multi-node control cluster, Flui reserves the master for the control plane so newly scheduled workloads land on the workers, keeping the node that runs the platform free. The protection is applied automatically when the cluster grows past a single node and lifted when it shrinks back; this command lets you set it explicitly or inspect the current state. It is best-effort: a failed change never fails the scaling that triggered it. See Nodes and cluster topology for the model.

Terminal window
flui env set-master-protection show # report current state
flui env set-master-protection on # reserve the master (new workloads go to workers)
flui env set-master-protection off # lift the reservation

flui env storage

Shows the status of the cluster’s shared storage: the underlying provider volume, the NFS export, and a summary of the storage claimed by applications.

Terminal window
flui env storage
flui env storage --cluster my-workload --usage

-c, --cluster looks at a workload cluster instead of the control cluster, which is where applications keep their data. --usage also measures how much disk each application really takes; it runs a short job on every node, so it takes a few seconds.

flui env storage-expand

Grows the cluster’s shared-storage volume on the provider and extends the filesystem on top over SSH. It runs online, with no downtime and no application restarts, but it is one-way: the providers Flui integrates with let volumes grow but not shrink.

Terminal window
flui env storage-expand --size 50 # new size in GB
flui env storage-expand --size 100 --confirm # skip the typed confirmation
flui env storage-expand # defaults to current + 10 GB
FlagEffect
-s, --size <gb>New volume size in GB (must be greater than current). Default: current size + 10 GB.
--confirmSkip the typed confirmation prompt.

Firewall

flui env update-firewall

This command manages the list of addresses allowed to reach SSH. You typically run it when your workstation’s public IP has changed or another operator needs access.

Terminal window
flui env update-firewall # replace the list with your current IP
flui env update-firewall --ip 203.0.113.42
flui env update-firewall --ip "203.0.113.0/24,198.51.100.5/32"
flui env update-firewall --add # add your current IP, keep the rest
flui env update-firewall --add --ip 203.0.113.42
flui env update-firewall --remove --ip 198.51.100.5/32
flui env update-firewall --list # print the list, change nothing

It is built to be safe to run:

  • It touches only the SSH rule. Every other rule on the firewall is read and written back exactly as it was. A rule you added yourself, such as an extra allowed address or a non-standard port, is not affected.
  • It still works when you are locked out. It writes the rules Flui keeps, so a later reconcile does not undo them. When the Flui API does not answer, it writes to your provider directly and brings the saved rules in line on the next run.

Without --add or --remove, the list is replaced by what you pass, or by your auto-detected public address when you pass no --ip at all. --add and --remove edit the existing list instead, and both accept --ip the same way. --list only reads.

The command refuses a change that would leave the list empty, because that locks everyone out of SSH, and tells you so. It also does nothing when there is nothing to do: an address you are adding that is already there, or one you are removing that was never there.

One case behaves differently: if the cluster has no firewall, a plain run creates one from the default rules (SSH from the addresses you named, ports 80 and 443 open to the world). --add, --remove and --list need a firewall to exist first.

On a machine you own, there is no provider firewall to change. The command says so instead of failing, and points you to the two commands below. SSH stays reachable there; see Firewall as a policy for why.

flui env firewall apply / flui env firewall status

These commands cover the firewall as a whole, not only its SSH list.

Terminal window
flui env firewall apply
flui env firewall status

apply makes sure a firewall exists, seeding the default rules if there is none, and then applies it. Everything inbound is denied except the rules Flui declares. It is idempotent: re-running it is safe, and it fixes most of what goes wrong here.

status reads it back: whether a firewall is configured at all, the reconciliation state, when it was last applied, whether it has drifted from the rules Flui wants, and the rules actually in force. If there is none, it says so (nothing is filtering inbound traffic) and tells you to apply one.

Which mechanism enforces the rules is decided by the provider: a firewall the provider runs in front of the machine, or a ruleset on the machine itself. The command and its rules are the same either way.

Handing an installation over

flui env adoption-token

Issues a one-time token that lets someone take ownership of this installation from a machine that has never touched it. It exists for the handoff at the end of a provisioning run someone did on your behalf, and as the recovery path when the original token is lost.

Terminal window
flui env adoption-token
flui env adoption-token --format json

Single use, valid for one hour, tied to that one installation. Anyone holding it can register a certificate authority there, so treat it like a password.

flui env adopt <token>

Run on the new owner’s machine. It asks the installation to describe itself, writes a local profile pointing at it, and creates the SSH certificate authority on this machine, so the key that opens those servers is created where it will live and whoever built the installation never holds it. The public half is registered with the installation.

Terminal window
flui env adopt flui_adopt_eyJlbmRwb2ludCI...
flui env adopt <token> --endpoint https://your-install.example.com
flui env adopt <token> --skip-ca
FlagEffect
--endpointThe installation’s address. Only needed when the token does not carry one.
--profileProfile to write the adopted cluster into. Default: the active profile.
--skip-caRebuild the local profile only, and leave SSH dormant. The right choice if you only ever use the dashboard.

The installation then enrols the key on every node and the command reports how many. If a node could not be enrolled, it names it and why. The token is spent either way: run flui env adopt again with a new token. The key already registered is kept, and only the nodes are enrolled again.

Cleaning up after a failed run

flui env scrub

Provisioning creates real, billable things before it finishes: a server, a firewall, an SSH key. A run that dies partway cannot always clean up after itself, and leaves a few resources in your provider account with nothing pointing at them.

flui env scrub removes them, working from the JSON resource list that run reported.

Terminal window
flui env scrub --ledger ./flui-run.json
cat flui-run.json | flui env scrub --stdin
flui env scrub --ledger ./flui-run.json --delete

Without --delete it changes nothing: it asks the provider what exists, matches that against the list, and prints what it would remove. The list decides what to look for and the provider decides what is really there; anything not in both is left alone. If part of the account could not be listed, it refuses to delete at all, because the part it could not see may still hold resources.

FlagEffect
--ledger <file>The resource list the run reported.
--stdinRead that list from standard input instead.
-p, --providerLook at one provider only, hetzner or scaleway. Default: every provider configured in this profile.
--deleteActually remove what the plan resolved.
-y, --yesSkip the confirmation prompt.
--non-interactiveNever prompt; fail instead of asking.

flui env orphan-volumes

The other kind of leftover: Flui-managed provider volumes left behind by a previous failed env destroy. Useful to recover quota after an incident, and safe to run at any time.

Terminal window
flui env orphan-volumes # list orphans (all configured providers)
flui env orphan-volumes --provider hetzner # scan a single provider
flui env orphan-volumes --cleanup # detach and delete the listed orphans
flui env orphan-volumes --cleanup --yes # skip the confirmation prompt

-p, --provider takes hetzner or scaleway.

Updates

flui env upgrade

Updates the installation to a new Flui release: backs it up, brings the system manifests forward, rolls out the platform components, upgrades the cluster runtime and checks the result. It shows the plan and changes nothing unless you ask; --apply with the plan’s id carries it out.

Terminal window
flui env upgrade
flui env upgrade --to 0.20.0
flui env upgrade --to 0.20.0 --plan <plan-id> --apply
flui env upgrade --resume <operation-id>
FlagEffect
--to <version>The release to go to.
--plan <id>, --applyCarry out the plan that was shown.
--cluster <name|id>Show only this cluster in the plan. The update itself always covers every cluster.
--without-backupSkip the backup step. You type a confirmation sentence at the prompt, and it is recorded in the operation and the audit log.
--acknowledge <sentence>With --without-backup and no terminal to type in: that sentence, exactly.
--resume <id>Continue an update that stopped.
--jsonMachine-readable output.

flui env refresh-manifests

Brings the manifests the cluster restarts from into line with a release. It shows what would change and writes nothing unless asked (--apply --plan <id>). --ref picks the release; --only limits it to some manifests.

Terminal window
flui env refresh-manifests # the plan, nothing written
flui env refresh-manifests --ref v0.13.0
flui env refresh-manifests --apply --plan 3f9c2a1
FlagEffect
--ref <release>The release to compare against. Defaults to the one this CLI pins.
--only <file>Limit to these manifests, by file name. Repeatable.
--applyWrite the plan. Needs --plan from a dry run.
--plan <id>The plan id a dry run printed.
--allow-stateful-image-changeAllow a file that changes the image of something holding a volume. Read the release notes first.
--overwrite-modifiedReplace a file that was changed on the master by hand, which no release reproduces. What was there is kept in the backup folder the apply prints.
--jsonMachine-readable output.

It reads the master through the API, with the same permissions as the dashboard; when the control plane does not answer, it says so and stops.

flui env install-values

Rebuilds the record of the values the installation was built with, so an update can bring its templated manifests forward. A value is kept only when rendering a file with it reproduces the copy on the master exactly. It shows what it proved and writes nothing unless asked (--apply --plan <id>).

flui env reconcile-images

Declares the component images that are actually running, so a reboot cannot hand back an older one. It changes nothing that is running.

flui env maintenance get|set|clear

A cluster’s maintenance window: weekly slots in one time zone. Changes held “for the next window” run when it opens, and applications follow it unless they set their own. get shows the window, when it next opens and the changes held for it; set writes it; clear removes it.

Terminal window
flui env maintenance get --cluster production
flui env maintenance set --slot "tue,thu 02:00 2h" --timezone Europe/Rome
flui env maintenance clear

The Flui network

flui env overlay enable|disable|status

Switches the Flui network on or off for the installation, or shows it: whether it is on, why it cannot be, and every member with its last handshake. enable is refused, with the reason, where it cannot work, for example on a control cluster with no reachable address. disable tears nothing down, but no new cluster joins it and clusters on another provider than the control cluster cannot be created.

Diagnostics and maintenance

flui env logs

Tails the local log files Flui writes while it drives an infrastructure operation: cluster create, node scale, storage expand, destroy, firewall update and so on. Each operation produces one file at ~/.flui/logs/<operationId>.log on the workstation that ran the command, and this view reads from there.

Terminal window
flui env logs # most recent operation
flui env logs -t 50 # --tail, default 100
flui env logs -l # --list operations that have logs
flui env logs -o <id> # --operation: one specific operation

For runtime cluster logs use flui env inspect, and for application logs use flui app logs. This command shows the diagnostic trail of the operation the CLI just ran: what step it was on, what the provider answered, where it failed.

flui env inspect

Connects to a node over SSH and tails one of its system logs. Useful when the high-level diagnostics are not enough and you need to see what the machine itself is doing.

Run with no flags, flui env inspect shows the same view that flui env create streams live during provisioning (the master’s cloud-init-output log). Run it afterwards, or against another node, to watch what happened again or see what is happening now.

Terminal window
flui env inspect # master, cloud-init-output, last 100 lines
flui env inspect --node worker-1 --log cloud-init
flui env inspect -f --log k3s # follow live
FlagDefaultEffect
-n, --nodemasterNode name (master, worker-1, …).
-l, --logcloud-init-outputOne of cloud-init, cloud-init-output, k3s (the cluster runtime), syslog.
-t, --tail100Number of lines to show.
-f, --follownoneFollow the log in real time.

flui env cordon / flui env uncordon

cordon stops a node accepting new work. What is already running on it keeps running. Use it before planned maintenance on a node you are about to touch by hand.

Terminal window
flui env cordon master
flui env cordon flui-cluster-worker-1
flui env uncordon flui-cluster-worker-1

uncordon re-opens the node. It is also the recovery helper for scale-master and scale-node: those close the node before resizing it and re-open it afterwards, so an operation interrupted in the middle (a crash, a timeout, a network blip) leaves the node closed. This command opens it again. On a healthy cluster you should not need it, since a successful scale leaves nothing to recover.

Both take the node as a positional argument: master, or a worker’s full server name.

flui env force-ready

Forces the cluster status to ready when it is actually operational but the platform left it stuck in error or creating after a transient failure during an async operation. This is a recovery helper: use it only after confirming the cluster really is healthy.

Terminal window
flui env force-ready
flui env force-ready --skip-health-checks # bypass health validation
flui env force-ready --force # skip the confirmation

flui env diag-ca

Diagnoses the cluster’s certificate authority configuration. The first thing to run when you see TLS or self-signed certificate errors from the dashboard or the API.

Terminal window
flui env diag-ca

flui env refresh-kubeconfig

Re-fetches the cluster’s authentication material from the master over SSH and refreshes the locally cached copy. Use it after a manual intervention on the master that may have rotated the credentials.

Terminal window
flui env refresh-kubeconfig

flui env repair-ssh-ca

Backfills the SSH certificate authority’s private key into the cluster’s own secret bundle. Run it on a cluster whose bundle lacks that key. The symptom is the dashboard’s SSH terminal failing with “CA private key not available.” The key is opened from the active profile’s vault and written into the cluster over SSH, and the Flui API is restarted afterwards unless --no-restart is set.

Terminal window
flui env repair-ssh-ca
flui env repair-ssh-ca --no-restart # skip the API restart
flui env repair-ssh-ca --profile <name> # read the key from another profile

flui env repair-storage

Backfills the shared-storage volume id into the cluster’s records, for clusters whose storage entry was left incomplete at install. The symptom is flui env storage-expand reporting no Flui-managed shared storage volume. After patching, it restarts the Flui API unless --no-restart is passed.

Terminal window
flui env repair-storage
flui env repair-storage --no-restart

Contributor-only commands

The commands below are not part of the normal operator workflow. They exist for Flui contributors running the API and dashboard repos locally against a remote cluster, or for one-off recovery scenarios that require platform-internal knowledge. End users can skip this section.

flui env sync

Reads the live endpoint URLs (API, identity provider, observability) from the cluster and writes them into the API repo’s .env and the dashboard’s config.json, so a local dev API/dashboard talks to the right remote endpoints. Read-only on the cluster side; it never touches database or cache credentials.

Terminal window
flui env sync
flui env sync --dry-run # show the diff without writing
flui env sync --debug # print the raw cluster discovery output

flui env export-config

Writes the control cluster’s endpoints (and non-sensitive defaults) into the .env of the API repo, so you can run the API locally against a remote cluster. It does not write secrets; use flui dev creds for those.

Terminal window
flui env export-config
flui env export-config --dry-run
flui env export-config --no-backup
FlagEffect
--dry-runShow the diff without writing.
--[no-]backupBack up an existing .env.
--forceSkip confirmation.
--no-dashboardDo not update the dashboard’s config.json.
--api-path <path>One-off override of the apiPath preference.
--dashboard-path <path>Override dashboardPath.
--certificate-mode <mode>Override certificateMode (production / staging / preflight).
--email <email>Override email.
--savePersist any value entered at the prompt into the active profile.