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 destroypermanently deletes the control cluster and all its data. To delete a workload cluster, useflui cluster destroy, neverenv 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).
flui env create # all defaults, streams provisioning liveflui env create --node-size cx32 # pick a specific server sizeflui env create --node-count 2 # add two worker nodesflui env create --region fsn1 # pin a regionflui env create --acme-staging # use Let's Encrypt stagingflui env create -d # detached: queue and exitflui env create --wait # block with a single spinner instead of streaming logsNode 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:
flui server-types list --provider <name> # all sizes for a providerflui server-types list --provider <name> --region <r> # filter by regionflui server-types list --provider <name> --json # machine-readableIf you omit --node-size or --region, env create picks the
provider’s recommended default for each, so you rarely need to set
them.
| Flag | Default | Description |
|---|---|---|
-p, --provider | the profile’s configured provider | hetzner, scaleway or ovh. See Profiles and config for what each one needs. |
-r, --region | provider default | Region code, provider-specific (flui server-types list --provider <name> to list). |
--node-size | provider recommended | Server type, provider-specific (flui server-types list --provider <name> to list). |
--node-count | 0 | Number of worker nodes (0 = master-only). |
--disk-size | included with the size | Root disk size in GB. Required for network-storage instance types; optional for types that bundle a local SSD. |
--[no-]configure-firewall | true | Configure the firewall after creation. |
--firewall-ip | auto-detect | Source IPs / CIDRs allowed by the firewall (comma-separated). |
--acme-staging | false | Use Let’s Encrypt staging (non-trusted cert, no practical rate limits). |
--image-registry | ghcr | Where 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-storage | volume | With --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-storage | false | Disable Flui shared storage (NFS+fscache). Falls back to dedicated local-disk placement on each node. See Storage classes and dedicated placement. |
--shared-storage-size | 20 | Size in GB of the master shared-storage volume (only when shared storage is enabled). Minimum: 10. |
--ssh-mode | ca | How 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-interactive | false | Never 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, --detached | false | Queue the operation and exit immediately. |
--wait | false | Wait for the cluster to be ready before returning, polling the operation instead of streaming logs. |
--allow-undersized | false | Skip 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-network | false | Leave 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. |
--latest | false | Install 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.
flui env create --host 203.0.113.10flui env create --host box.example.com --user ubuntu --port 2222| Flag | Default | Description |
|---|---|---|
--host | none | Address to install onto. Passing it is what turns this mode on. |
--user | root | SSH user on that host. |
--port | 22 | SSH port. |
--ssh-key | reuse, else authorize one | Private 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-password | none | Host password for unattended runs. Prefer the FLUI_SSH_PASSWORD variable, so it stays out of your shell history. |
--master-public-ip | --host | The address the world should use, when it differs from the one you install over. |
--skip-precheck | false | Skip the host readiness check. |
--best-effort | false | Continue 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.
flui env statusflui 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.
flui env credentials # endpoints, secrets hiddenflui env credentials --format json # machine-readable outputflui env credentials --show-secrets # include secret values| Flag | Effect |
|---|---|
--format text|json | Output format. Default: text. |
--show-secrets | Print 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.
flui env stopflui env restartflui 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.
flui env destroyflui env destroy --force # skip the confirmation promptOn 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.
flui env destroy # de-register and tear the host downflui env destroy --keep-host # de-register only, leave the host as it isflui env destroy --remove-access # also stop the host trusting Flui at allflui env destroy --dry-run # print the teardown script, run nothing| Flag | Effect |
|---|---|
-f, --force | Skip the typed confirmation. |
--keep-host | Skip the host teardown. The host stays dirty, and a later install on it fails until it is cleaned. |
--purge-host | Ask 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-access | Full 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-run | Print the host teardown script without running it or deleting anything. |
--host, --user, --port, --ssh-key | Clean 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.
flui env reinstallflui env reinstall --dry-run # print the teardown, run nothingflui env reinstall --force # skip the typed confirmationflui env reinstall --detached # start it and exitIt 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.
flui env capacityflui env capacity --top 5 # show 5 candidates instead of 10flui env capacity --direction upgrade # only larger sizesflui env capacity --direction downgrade # only smaller sizes| Flag | Default | Effect |
|---|---|---|
--top <n> | 10 | Maximum number of candidates listed. |
--direction | all | Filter 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.
flui env scale-master # auto-pick next upgrade candidateflui env scale-master --type cpx41 # pick a specific typeflui env scale-node flui-cluster-worker-1 --type cpx31flui env scale-node flui-cluster-worker-1 --type cx32 --confirm| Flag | Effect |
|---|---|
-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. |
--confirm | Skip 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.
flui env set-master-protection show # report current stateflui env set-master-protection on # reserve the master (new workloads go to workers)flui env set-master-protection off # lift the reservationflui 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.
flui env storageflui 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.
flui env storage-expand --size 50 # new size in GBflui env storage-expand --size 100 --confirm # skip the typed confirmationflui env storage-expand # defaults to current + 10 GB| Flag | Effect |
|---|---|
-s, --size <gb> | New volume size in GB (must be greater than current). Default: current size + 10 GB. |
--confirm | Skip 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.
flui env update-firewall # replace the list with your current IPflui env update-firewall --ip 203.0.113.42flui 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 restflui env update-firewall --add --ip 203.0.113.42flui env update-firewall --remove --ip 198.51.100.5/32flui env update-firewall --list # print the list, change nothingIt 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.
flui env firewall applyflui env firewall statusapply 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.
flui env adoption-tokenflui env adoption-token --format jsonSingle 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.
flui env adopt flui_adopt_eyJlbmRwb2ludCI...flui env adopt <token> --endpoint https://your-install.example.comflui env adopt <token> --skip-ca| Flag | Effect |
|---|---|
--endpoint | The installation’s address. Only needed when the token does not carry one. |
--profile | Profile to write the adopted cluster into. Default: the active profile. |
--skip-ca | Rebuild 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 adoptagain 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.
flui env scrub --ledger ./flui-run.jsoncat flui-run.json | flui env scrub --stdinflui env scrub --ledger ./flui-run.json --deleteWithout --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.
| Flag | Effect |
|---|---|
--ledger <file> | The resource list the run reported. |
--stdin | Read that list from standard input instead. |
-p, --provider | Look at one provider only, hetzner or scaleway. Default: every provider configured in this profile. |
--delete | Actually remove what the plan resolved. |
-y, --yes | Skip the confirmation prompt. |
--non-interactive | Never 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.
flui env orphan-volumes # list orphans (all configured providers)flui env orphan-volumes --provider hetzner # scan a single providerflui env orphan-volumes --cleanup # detach and delete the listed orphansflui 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.
flui env upgradeflui env upgrade --to 0.20.0flui env upgrade --to 0.20.0 --plan <plan-id> --applyflui env upgrade --resume <operation-id>| Flag | Effect |
|---|---|
--to <version> | The release to go to. |
--plan <id>, --apply | Carry out the plan that was shown. |
--cluster <name|id> | Show only this cluster in the plan. The update itself always covers every cluster. |
--without-backup | Skip 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. |
--json | Machine-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.
flui env refresh-manifests # the plan, nothing writtenflui env refresh-manifests --ref v0.13.0flui env refresh-manifests --apply --plan 3f9c2a1| Flag | Effect |
|---|---|
--ref <release> | The release to compare against. Defaults to the one this CLI pins. |
--only <file> | Limit to these manifests, by file name. Repeatable. |
--apply | Write the plan. Needs --plan from a dry run. |
--plan <id> | The plan id a dry run printed. |
--allow-stateful-image-change | Allow a file that changes the image of something holding a volume. Read the release notes first. |
--overwrite-modified | Replace 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. |
--json | Machine-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.
flui env maintenance get --cluster productionflui env maintenance set --slot "tue,thu 02:00 2h" --timezone Europe/Romeflui env maintenance clearThe 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.
flui env logs # most recent operationflui env logs -t 50 # --tail, default 100flui env logs -l # --list operations that have logsflui env logs -o <id> # --operation: one specific operationFor 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.
flui env inspect # master, cloud-init-output, last 100 linesflui env inspect --node worker-1 --log cloud-initflui env inspect -f --log k3s # follow live| Flag | Default | Effect |
|---|---|---|
-n, --node | master | Node name (master, worker-1, …). |
-l, --log | cloud-init-output | One of cloud-init, cloud-init-output, k3s (the cluster runtime), syslog. |
-t, --tail | 100 | Number of lines to show. |
-f, --follow | none | Follow 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.
flui env cordon masterflui env cordon flui-cluster-worker-1flui env uncordon flui-cluster-worker-1uncordon 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.
flui env force-readyflui env force-ready --skip-health-checks # bypass health validationflui env force-ready --force # skip the confirmationflui 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.
flui env diag-caflui 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.
flui env refresh-kubeconfigflui 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.
flui env repair-ssh-caflui env repair-ssh-ca --no-restart # skip the API restartflui env repair-ssh-ca --profile <name> # read the key from another profileflui 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.
flui env repair-storageflui env repair-storage --no-restartContributor-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.
flui env syncflui env sync --dry-run # show the diff without writingflui env sync --debug # print the raw cluster discovery outputflui 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.
flui env export-configflui env export-config --dry-runflui env export-config --no-backup| Flag | Effect |
|---|---|
--dry-run | Show the diff without writing. |
--[no-]backup | Back up an existing .env. |
--force | Skip confirmation. |
--no-dashboard | Do 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. |
--save | Persist any value entered at the prompt into the active profile. |