Skip to content

Latest commit

 

History

History
160 lines (124 loc) · 7.72 KB

File metadata and controls

160 lines (124 loc) · 7.72 KB

.env.app — what an app receives

CasaOS keeps the variables it needs to run and the variables it hands to the apps it manages in one environment. You cannot tell, looking at a CasaOS container's env, which half is which — and the two drift into each other.

Maison separates them:

Lives in Owned by Example
What Maison needs to run Maison's own environment (docker-compose.yml) Maison DATA_ROOT, APPSTORE_URL, HTTP_ADDR
What an app receives .env.app the deployment APP_NET, APP_DOMAIN, APP_PUBLIC_IP_DASH, APP_DEFAULT_PASSWORD

Nothing is in both, so there is never a question of which one wins.

The file

${DATA_ROOT}/AppData/maison/.env.app

AppData/maison/ is Maison's own app directory — the same folder a deployment installs the dashboard's compose stack into, and where Maison keeps its settings and store cache. Everything Maison owns is in that one place, with no hidden sibling.

It is a plain KEY=VALUE file, and it belongs to the deployment, not to Maison: on a Yundera PCS the orchestrator writes it at provisioning; on a plain install it is the operator's to edit. Maison creates it once, with a documented default, and never overwrites it — an upgrade that silently reverted the deployment's domain, network and credentials would be a bad day.

An empty value means the deployment does not have this, and the key is skipped rather than written blank: an app is better off with an unresolved ${APP_DOMAIN} — which docker compose reports — than a blank one, which silently routes it at nothing.

How it reaches an app

On install, and again on every start, Maison reads .env.app and ensures each key in the app's own .env:

  • a key already there is set to the current value, in the line it already occupies;
  • a key that is missing is appended;
  • everything else is left alone — a variable the operator added to an app's .env is theirs, and survives.

Keys are ensured one at a time, so neither file's ordering matters.

Merged in alongside are the few variables Maison computes per app and per install, which a deployment cannot state: AppID, PUID, PGID, TZ, DATA_ROOT, DATA_HOST_PATH. Setting those in .env.app has no effect.

Why it is re-applied on every start

Because an app is installed against one deployment and started against whatever that deployment has since become — a new app network, a new data root, a new domain, a new public IP. None of that invalidates the app's own configuration, so none of it should stop the app from starting.

This is why a store app's compose refers to its surroundings only through ${APP_NET}, ${DATA_ROOT}, ${APP_DOMAIN} … and never through a resolved literal. The literal is the bug: it freezes the app to the deployment it happened to be installed on, and moving the box leaves every app unstartable with reinstall as the only way out.

The references are the store's to write, not Maison's to insert. Maison used to rewrite each app's docker-compose.yml — swapping /DATA for ${DATA_ROOT} and replacing the network the app declared with one of its own — before every up. That made the file on disk differ from the file the store shipped, made a hand-run docker compose up differ from an install, and, because the rewrite re-attached only the main service, silently dropped every other service the app had put on the shared network. It no longer happens: docker-compose.yml is the store's bytes, and Maison writes only the override and this .env.

So a store app writes ${APP_NET:-pcs} and ${DATA_ROOT:-/DATA} itself — the default keeping a bare docker compose up working outside Maison — .env.app says what they currently are, and every start resolves the two afresh.

Why the values are written into the app's .env

Maison could just pass them to docker compose in its own process environment — it already runs the command. But then the app folder would only work when Maison brought it up.

Writing them into the .env is the point: a docker compose up -d you run by hand in AppData/<app>/ must bring the app up exactly as Maison does. The folder stands on its own. That is the promise of the app model (see app-model.md), and it is also what makes an app debuggable without the dashboard in the loop.

Adding a variable

Add a line to .env.app. That is the whole procedure — no rebuild, no code change. It reaches every app on its next start.

Editing it from the dashboard

Settings › App environment edits this file, for a deployment where opening a shell is not the natural move. It is the file itself in a text box, not a form: the comments are the documentation, there is no fixed schema — a deployment adds its own keys — and an empty value means something a form field cannot express.

Three things the page is careful about, all of them consequences of the above:

  • It says the file has another owner. On a PCS the orchestrator wrote it and may write it again, over your edit. Maison cannot prevent that and does not pretend to.
  • It saves nothing it cannot read back. A line that is not KEY=VALUE, a name that is not a shell identifier, a duplicated key — all rejected, with the line number, and the file on disk is left untouched. The parser is deliberately forgiving (it skips a line it cannot read); a save is not, because a typo that silently does nothing would surface days later as an app that will not start.
  • It restarts nothing. The variables land in each app's .env on that app's next start, per the section above. Unlike the domains list — which rewrites Caddy labels and so must recreate containers to mean anything — there is nothing here that recreating every container on the box would buy.

A key Maison computes per app (AppID, PUID, PGID, TZ, DATA_ROOT, DATA_HOST_PATH) is reported as having no effect rather than rejected: the file is the deployment's, and it is free to say what it likes.

Note the file holds APP_DEFAULT_PASSWORD and DefaultPassword in plain text, so the page shows credentials. It was always a readable file on a box with no auth (Maison assumes a trusted network — see the README); the page does not change who can read it, only how far they have to reach.

The default

APP_NET=mesh                 # the external network apps are attached to
APP_DOMAIN=                  # the deployment's base domain
APP_PUBLIC_IP=               # …and its public IP, in the spellings the store uses
APP_PUBLIC_IP_DASH=
APP_PUBLIC_IPV4=
APP_PUBLIC_IPV4_DASH=
APP_PUBLIC_IPV6=
APP_PUBLIC_IPV6_DASH=
domain=                      # lowercase alias: some x-compose-app webui-host use it
APP_EMAIL=
APP_DEFAULT_PASSWORD=casaos
DefaultUserName=admin
DefaultPassword=casaos

That default describes a standalone local install: apps on Maison's own mesh network, no domain, so no reachable web address. A PCS overwrites it with APP_NET=pcs and its real domain and IP; dev/docker-compose.yml does the same through its appenv init container.

A note on REF_*

CasaOS used REF_SCHEME / REF_PORT / REF_DOMAIN / REF_SEPARATOR to synthesize an app's web-UI URL as scheme://<app><sep><domain>:<port> (casa-img, route/v2/appstore_pcs.go). Maison replaced that mechanism entirely with x-compose-app's webui-host / webui-scheme / webui-port (see x-compose-app.md), so those variables have no consumer here and are gone. REF_NET and REF_DOMAIN were duplicates of APP_NET and APP_DOMAIN, which a PCS already sets; they are gone too.

A REF_* line left over in an old app's .env is inert — nothing interpolates it — and Maison leaves it alone rather than deleting a line it no longer owns.