Get started

Multi-env vars

Layered .env files, dev/staging/prod switching, per-project path overrides, and Infisical inheritance — the parts that don't fit on the basics page.

6 min readUpdated 3 days agoEdit on GitHub

This page picks up where basics: configure env vars ended. Prerequisites: you've already set a value with one env set and you understand the difference between dotenv and Infisical backends. Here we cover layered overrides, multi-environment trees, and per-project paths.

dotenv: layered files per environment

For each project, four files are loaded in order. Later files override earlier ones:

<project>/.env
<project>/.env.<env>
<project>/.env.local
<project>/.env.<env>.local

Concrete example for services/api/ with --env staging:

FileShould commit?Contents typically
services/api/.envyesDefaults checked in for all environments — e.g. LOG_LEVEL=info, non-sensitive flags
services/api/.env.stagingyesStaging-specific values that aren't secret — e.g. feature flag overrides
services/api/.env.localno (gitignored)Developer-machine overrides — e.g. local DB URL
services/api/.env.staging.localno (gitignored)Local override scoped to staging

one env set KEY=VALUE -p api --env staging writes to services/api/.env.staging. To write to a .local file, edit it directly.

one env get KEY -p api --env staging reads the resolved value after all four layers.

one env list -p api --env staging shows the resolved set with origin file for each key, when run with -o json.

Multi-environment switching

The list of environments lives in one.manifest.json#environments.names:

{
  "environments": {
    "names": ["dev", "staging", "prod"],
    "default": "dev"
  }
}

Add a new environment — say qa — by adding it to the array. Commands then accept it:

one env set DATABASE_URL=... --env qa -p api
one env pull --env qa            # Infisical
one run -p api --env qa -- npm run e2e

Environment names are arbitrary strings; the manifest is the single source of truth.

Infisical: folder tree mirrors workspace layout

In Infisical, every project gets its own folder, path = relativeDir. Environment is orthogonal (dev / staging / prod live as separate environment branches under the same folder tree):

Infisical project
├── env=dev
│   ├── /                       (workspace-root folder)
│   ├── /services/api/
│   └── /apps/web/
├── env=staging
└── env=prod

Inheritance rules (Layer 1):

  • Root folder keys are inherited by every project.
  • Project folders don't see each other's keys.

So apps/web never gets apps/api/DATABASE_URL, even at the same environment.

Per-project path override

Default path = project's relativeDir. A project can override under domains.env:

{
  "name": "charge",
  "relativeDir": "services/charge",
  "domains": {
    "env": {
      "path": "/teams/payments/services/charge",
      "inherits": true,
      "keys": ["DATABASE_URL", "STRIPE_SECRET"]
    }
  }
}
FieldEffect
pathOverride the inferred Infisical folder path
inheritsDefault true — inherit root folder keys. Set false for total isolation.
keysOptional allowlist — only these keys land in this project's .env, even if the folder has more
disabledIf true, one env pull skips this project entirely

CI integration

For CI, set the Universal Auth credentials as repository secrets and pull once at job start:

env:
  INFISICAL_UNIVERSAL_AUTH_CLIENT_ID:     ${{ secrets.INFISICAL_CLIENT_ID }}
  INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
steps:
  - uses: actions/checkout@v4
  - run: curl -fsSL https://1cli.dev/install.sh | bash
  - run: one env pull --env staging
  - run: pnpm install && pnpm test

The action takes One CLI's env vars rather than profiles — no ~/.config/one/credentials.json to manage in CI.

Conflict protection on pull

one env pull --env dev
# ENV_PULL_CONFLICT if any local .env differs from Infisical

Comparison is semantic — parsed dotenv records, not byte diff. Quote-style or trailing-newline differences won't false-positive.

To overwrite intentionally:

one env pull --env dev --force

To preview without writing:

one env pull --env dev --dry-run

Common errors

CodeSymptomFix
ENV_UNKNOWN_ENVIRONMENT--env qa but qa isn't in manifest.environments.namesAdd it to the manifest
ENV_PULL_CONFLICTLocal .env differs from InfisicalInspect; rerun with --force if intentional
INFISICAL_PROJECT_CREATE_FORBIDDENMachine identity lacks permission to auto-create the Infisical projectGrant admin role, or create the project manually and pin projectId
ENV_KEY_NOT_FOUNDone env get returned nothingWrong project / env / key spelling — check with one env list

Full table: error codes.

Next