$ aoox

DocsApplications

Environment variables

Application env, linked variable sets, and references to managed database credentials — all resolved when the container is created.

Layers
Linked variable sets + secret source + application env
Applied
When the container is created, not at build time
References
${{vars.KEY}} · ${{database.<slug>.url}}

The env editor

An application's Environment tab (after Mount) has an Environment variables editor with two modes:

ModeFor what
Per lineOne key, one input; values are masked (password input) with a reveal toggle. Good for changing a single value.
TextA free textarea — paste the contents of a .env file as-is. Good for an initial migration.

Both are stored as KEY=VALUE text, one per line. The API always returns the raw values — masking only happens in the UI.

Accepted format
PORT=3000
NODE_ENV=production
# comment lines are ignored
MESSAGE=values may contain spaces and = in the middle
EMPTY=

The tab has its own Save button that saves only the env, so saving other Settings never overwrites it. Viewers see the env without being able to change it.

Secret source (Infisical)

Instead of copying secrets into the env, an application can pull them from Infisical when its container is created.

  • Connection: owner/admin add it under Integrations → Secret manager (name, optional URL for a self-hosted instance, the machine identity's Client ID and Client secret). The client secret is stored encrypted and can't be seen again; the test button checks the connection.
  • Secret source on the Environment tab: pick the connection, then project ID, environment and path (default /). View keys lists key names only, never their values.
  • Reference one secret with ${{secret.KEY}} in the env, or turn on Sync all secrets to the container to pass them all as env.
  • Values are read when the container is created (deploy, apply config, rollback), not at build time. On a key clash the application's env wins over the secret. Pull request previews don't inherit the secret source.
  • If Infisical is unreachable during a deploy, the deployment fails and the old container keeps running.

How env gets merged

  1. 01variable setsthe linked set environments, in order (lowest)
  2. 02secret sourceInfisical, when sync is on, overrides it
  3. 03application envoverrides the same key (highest)
  4. 04resolve ${{…}}vars, secrets & databases of the same project
  5. 05containerthe final result goes into the container
  • Priority, lowest to highest: the linked variable set environments in their order (a later link wins over an earlier one) < the external secret source (Infisical, when sync is on) < the application's own env. If the same key exists in several, the higher one wins.
  • Merging and resolution happen every time the container is created: deploy, rollback, or a recreate triggered by a domain/mount change. Editing a variable set does not change running containers — it applies on the application's next deploy.
  • Env is not available at build time. For that, use Build args (non-secret).

References

SyntaxResolves to
${{vars.KEY}}The merged value of KEY across the application's linked variable set environments (a later link wins), one level deep. See Variables.
${{secret.KEY}}One secret from the Infisical source (see above).
${{database.<slug>.url}}The managed database's internal connection URL (host = container name).
${{database.<slug>.host}}The database container's name, e.g. aoox-db-app-db.
${{database.<slug>.port}}The engine's port inside the network (5432, 3306, 6379).
${{database.<slug>.username}}Username.
${{database.<slug>.password}}Password (redacted in logs).
${{database.<slug>.database}}Database name.
${{database.<slug>.url:<name>}}Another database on the same server (e.g. one created via a CREATE DATABASE query): same host/user/password, only the database name differs.

A full example

shared/production (a variable set environment linked to the app)
APP_ENV=production
SENTRY_DSN=https://abc@sentry.example.com/1
Web application env
NODE_ENV=${{vars.APP_ENV}}
SENTRY_DSN=${{vars.SENTRY_DSN}}
DATABASE_URL=${{database.app-db.url}}
REDIS_URL=${{database.cache.url}}
PORT=3000
Result in the container (illustration)
NODE_ENV=production
SENTRY_DSN=https://abc@sentry.example.com/1
DATABASE_URL=postgresql://app_db:s3cr3t@aoox-db-app-db:5432/app_db
REDIS_URL=redis://:s3cr3t@aoox-db-cache:6379
PORT=3000
  • Databases are only looked up in the same project — an application can't read another project's credentials. The slug is the name shown on the database page.
  • Changing the links so that a ${{vars.KEY}} the env references no longer exists is refused with a message naming the key. ${{project.KEY}} was renamed to ${{vars.KEY}} and is refused.
  • An unknown reference → 400 when saving Settings; if it only breaks at deploy time (e.g. the database was deleted) → the deployment is failed.
  • Rotating a database password → takes effect on the next deploy/rollback, no rebuild needed.

Secrets & logs

  • Resolved database passwords and Git tokens are automatically redacted from deployment logs and error messages.
  • Other env values are redacted only by the rules in Secret variables (variable sets); don't rely on masking and don't print env to stdout from your application.
  • Application env is stored as plain text in aoox's own database; access to the Settings page means access to its values. Variable set values are encrypted at rest and can be protected — see Variables.

Variable sets

Variables shared by several applications (or kept per stage, such as staging and production) live in variable sets: instance-wide groups with their own environments, history, compare/promote and secret flags. On the Environment tab, the Variable sets card links set environments to the application in order; the own env above always wins over them.

Compose stacks

Compose stacks use the same mechanism: resolved env is written to .aoox.env and used as --env-file — a source of ${VAR} interpolation in the compose file, not automatically injected into containers. Pass it through environment: on each service — see Compose stacks.

Common pitfalls

SymptomCause & fix
New env isn't picked up by the appNo new container yet — deploy or roll back once more.
400 when saving: unknown referenceWrong database slug, or the database is in another project.
NEXT_PUBLIC_* / build-time values are emptyEnv isn't available at build time. Move it to Build args (if not secret) or read it at runtime.
Values carry quote marks along with themWrite it without quotes: KEY=value, not KEY="value".

Next steps

Found a mistake? Edit this page on GitHub ↗