.env File Secrets Workflow: From Redacted Manifest to Runtime
Redaction only works if the real values have somewhere to live. The environment-variable pattern answers that: configuration that varies between deploys, and especially credentials, belongs in the process environment rather than in files under version control, a principle the twelve-factor methodology made standard practice for web applications.1 The .env file is the local developer's bridge to that pattern, holding KEY=value lines that tooling loads into the environment at startup.1
Redaction and this environment-variable habit are two halves of one workflow, not separate concerns bolted together as an afterthought. When the Cloud Config Sanitizer redacts a manifest, its Download .env template button produces exactly this bridge: a ready-to-fill file listing every key stripped at critical or high severity, with a comment header and empty values. Filling it in, ignoring it in git, and injecting the same variables in CI completes a workflow where secrets and code never share a file again. Without this second half of the workflow, redaction is just a cosmetic edit, since the real values still need somewhere safe to go.
What the generated template contains
Precision keeps the template useful. The sanitizer derives an environment-variable name from each redacted key path, uppercasing the final segment, and writes one KEY= line per unique name, deduplicated so a credential referenced twice becomes a single entry. Only critical and high findings make the cut: provider-format tokens, connection strings, Kubernetes Secret values, and high-entropy strings all appear, while medium suspicious-key findings and info-level security smells stay out of the template, since those need judgment rather than a value swap.
The template doubles as an inventory
The file opens with a comment identifying its origin and instructing you to fill in real values before deploying. Consequently, the template doubles as an inventory: it is the definitive list of every secret your manifest used to carry inline.
That inventory turns out to be worth reading on its own, since it is often the first time every inline secret in a manifest has been listed in one place. Reviewing that inventory once, before filling anything in, is a useful moment to catch a variable name that looks wrong or a credential that should not have been in the manifest at all.
Keeping the .env file out of version control
One .gitignore line carries the whole pattern. Adding .env to your ignore file before the first fill-in prevents the classic failure where the redaction effort is undone by committing the very file that collected the secrets; adding .env.* as well covers environment-specific variants like .env.production.2 Commit an example instead: a .env.example with the same keys and empty or dummy values, which the sanitizer's template already resembles, documents required variables for new contributors without carrying anything sensitive.3
Yet local files remain local risks, readable by anything running as your user, so the .env file is a development convenience rather than a production mechanism. For deployed environments, the same variable names should come from your platform's secret facilities.4 Checking the ignore rule into the repository at project creation, before anyone has a chance to fill in a real value, removes the single most common way this pattern fails in practice.5
One ignore rule, checked in early
Adding .env to the ignore file before anyone fills in a real value is the single change that prevents the classic failure: a redaction effort undone the moment someone commits the file that collected the secrets. Covering .env.* as well catches environment-specific variants like .env.production before they slip through the same gap.
A committed .env.example, mirroring the sanitizer's template with empty or dummy values, documents the required variables for new contributors without exposing anything real. Production and other deployed environments should still draw the same variable names from the platform's own secret store rather than from a local file, keeping the same names lined up everywhere the values get read.
Injecting variables in CI and production
The variable names travel; the values never do. In GitHub Actions, define the values as repository or environment secrets and map them into steps with env: entries referencing the secrets context.6 In Kubernetes, create a Secret holding the same keys and expose it to containers with envFrom, which mounts every key as an environment variable matching the template names.7 Docker Compose reads an env_file: directive or substitutes from the shell environment.4
Building on this, a secrets manager tightens the loop further: tools like External Secrets Operator sync values from cloud secret stores into Kubernetes Secrets, so rotation happens at the store and propagates without touching manifests.8 In every variant, the manifest keeps its placeholders, and once you wire .env keys into your CI secrets, the real value only ever exists in the platform, never in the file itself. Naming the variables identically across development, CI, and production, using the template as the shared reference, keeps the whole pipeline predictable even as the underlying secret storage changes.7
Same names, different source per environment
GitHub Actions maps repository or environment secrets into a step through env: entries that reference the secrets context, while a Kubernetes Secret exposed with envFrom mounts every key as an environment variable under the same names the template already defined. Docker Compose picks the values up through an env_file: directive or the shell environment it inherits.
A secrets manager like External Secrets Operator tightens this further by syncing values from a cloud store directly into Kubernetes Secrets, so rotation happens at the store and propagates without anyone touching a manifest. Keeping the variable names identical from development through CI to production is what makes swapping the underlying secret storage a non-event.
When to use this
Reach for this workflow immediately after sanitizing any manifest, when onboarding a project that has credentials scattered through config files, or when standardizing how a team supplies secrets across development, CI, and production. It is the natural second step after redaction, turning a one-time cleanup into the project's permanent convention for separating configuration from credentials. New services adopting the pattern from day one avoid the retrofit entirely, since there is never an inline credential to migrate away from.
Examples
A sanitized Deployment produced a template with two stripped keys
# Generated by CapyToolkit Cloud Config Sanitizer # Fill in the real values before deploying DATABASE_URL= API_KEY=
DATABASE_URL=postgres://app:local-dev-pw@localhost:5432/dev API_KEY=sk-dev-key-from-your-vault
The filled file stays on your machine, listed in .gitignore; CI and production receive the same two names from platform secrets.
A new contributor needs to run the project locally
Commit a .env.example with the template's key names and no values. The contributor copies it to .env, fills values from the team vault, and never needs to see a manifest with inline credentials.
Kubernetes needs the same variables the template defined
Create a Secret with matching key names and reference it via envFrom in the container spec. The placeholders in the sanitized manifest mark exactly which fields moved to the environment.
- 1.
The Twelve-Factor App, "Config," 12factor.net, accessed July 2026. https://12factor.net/config
- 2.
Git, "gitignore Documentation," git-scm.com, accessed July 2026. https://git-scm.com/docs/gitignore
- 3.
GitHub, "Node.gitignore," github.com, accessed July 2026. https://github.com/github/gitignore/blob/main/Node.gitignore
- 4.
Docker Docs, "Set environment variables within your container's environment," docs.docker.com, accessed July 2026. https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/
- 5.
GitHub Docs, "Removing sensitive data from a repository," docs.github.com, accessed July 2026. https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository
- 6.
GitHub Docs, "Using secrets in GitHub Actions," docs.github.com, accessed July 2026. https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets
- 7.
Kubernetes, "Define Environment Variables for a Container," kubernetes.io, last modified June 2025. https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/
- 8.
External Secrets Operator, "Introduction," external-secrets.io, accessed July 2026. https://external-secrets.io/latest/