Skip to content

Set an application's configuration and secrets

Every application needs values it does not carry in its own code: a database URL, a log level, an API key. Two places hold those values. The flui.yaml in your repository says what the application needs. The platform stores what it was given, deploy after deploy. This page explains which of the two wins.

The manifest owns the keys it declares

Values pinned by hand are how configuration drifts: the file says one thing, the running application does another, and nothing reports the difference. So the manifest reclaims what it declares. On every deploy, for every key flui.yaml names, the value in the file is the value that lands.

From lowest to highest priority:

  1. A stored value on a key the manifest does not declare. Kept. This is the only place a hand-set value survives.
  2. flui.yaml. Authoritative for every key it declares, on every deploy, including a key someone had pinned by hand.
  3. --env / --env-file at deploy time. Passed by a person on this deploy, and wins over both.

So a value you set by hand outlives the next deploy only if the manifest says nothing about that key. To use a different value on a key the manifest declares, pass it at deploy time.

There is one exception, which prevents a credential from leaking. A key linked to another building block’s secret, such as a database password Flui wired in for you, is never overwritten by a plain value from the manifest. The link stays a link.

Declared keys without a value

A manifest can name a key without carrying its value. It might declare a value someone supplies later, or point at a sibling application that cannot be found right now.

A key like that keeps whatever is already stored. Declaring it tells the platform that the variable exists and its value comes from elsewhere. It does not tell the platform to blank it.

Only a key the manifest stops declaring altogether is removed. That rule is what lets an application keep its API key across a redeploy.

A deploy-time value is plain text unless you say so

--env DATABASE_URL=… stores exactly what you typed, in plain text, and it stays that way. That is fine for a log level and bad for a password.

Name the key with --secret to change that:

Terminal window
flui deploy --env-file .env \
--secret DATABASE_URL --secret API_KEY

--secret is repeatable, and each name must be a key you are passing on this deploy. Naming one you are not passing fails the command, so you never believe a credential was protected when it was not. A key marked this way is stored encrypted, delivered to the application as a secret, and never printed back by flui app env list or by flui app status -o json.

Use --env-file for anything sensitive. Values in a file never appear on the command line, so they are not written to your shell history and are not visible to other processes while the deploy runs.

Flui also warns you. If a key looks like a credential (its name contains SECRET, PASSWORD, TOKEN, PRIVATE or _KEY) and you did not mark it, the deploy prints a warning that it is about to be stored and shown in plain text. The deploy still goes ahead, since you may have a reason.

Keys awaiting a value

A sensitive variable can exist without a value. The manifest declares a key as a secret and carries no value for it, or an agent asks a person to supply one. Either way the key is recorded, by name, as awaiting a value.

Every surface lists that state beside the others. It is a distinct state, not a blank, a missing key or an error. Asking for the variables of an application that is still waiting for one is a successful request.

A key still awaiting a value is not delivered to the running application at all until a person supplies it.

Setting and reading them

flui app env list shows everything for one application: plain variables with their values, which sensitive keys are configured, and which are still waiting.

Terminal window
flui app env list my-api

Sensitive values are not shown, because none is available to show. A configured secret reads as set, and a waiting one reads as awaiting a value.

To deliver a sensitive value:

Terminal window
flui app env set my-api STRIPE_SECRET_KEY

There is no --value flag; the command prompts you instead. An argument would land in your shell history and be visible to every other process on the machine while it ran. When an agent composes the command, it would also pass through the model. For a script, pipe it in:

Terminal window
printf '%s' "$KEY" | flui app env set my-api STRIPE_SECRET_KEY --stdin

The value is not read back afterwards. The command tells you the key is configured, and nothing on this path can tell you more.

Both commands accept -c, --cluster <name|id>; it is detected for you when the profile has only one cluster.

When the new value reaches the application

Writing a variable updates what Flui stores immediately. The running application picks up the new value the next time it starts: on its next deploy, or on a restart.

Terminal window
flui app restart my-api

This is why delivering a secret is usually followed by a redeploy or restart, and why reading the variables back right after setting one shows it as configured while the application still runs with the old value.

Where this goes next

  • The flui.yaml manifest: the deploy.env block these rules are about, and what else a manifest can and cannot say.
  • The app concept: what an application is, and where its configuration sits among everything else it carries.
  • flui deploy: the full flag surface, including the install-time overrides that work the same way for a name and a domain.
  • The Flui Assistant and MCP: the surface the three tools above belong to.