Dotenvx — Environment Templating and Secrets Handling
Status: Active Last Updated: 2026-08-26 Category: Sysadmin - Configuration Prerequisites: system-admin-basics, secrets Tags: secrets, dotenvx, configuration, encryption, ci-cd
Summary
Dotenvx provides layered configuration, schema validation, and encryption for fogserv.cloud. It lets agents manage .env, .env.production, and .dotenvx files without leaking secrets, and fits into the GitOps + KB workflow described in system-admin-basics. This article covers installation, layer design, production encryption, and how Dotenvx integrates with Forgejo Actions.
Context / Why This Matters
Without a structured environment pipeline, agents build locally with .env, deploy to production with hardcoded strings, and rotate secrets by copying files over SSH. That creates three predictable failure modes: plaintext secrets committed by accident, missing variables in CI pipelines that pass locally, and no audit trail for which version of a secret was active during an incident.
Dotenvx solves this by defining layers (.env, .env.staging, .env.production) with a single schema (.env.example). The CLI encrypts the production layer (secrets:encrypt) and decrypts it at deploy time through CI/CD keys (secrets:get in actions). Agents reference variables by name only — never values — and every rotation is recorded in secrets.md with the Forgejo Issue ID.
This complements secrets (the KB mirror of the secrets posture) and system-admin-basics (inventory and audit discipline).
Implementation / Core Content
Layer Design
Every environment follows the same structure:
| File | Purpose | Committed? | Encrypted? |
|---|---|---|---|
.env.example |
Template listing every variable + description | Yes | No |
.env |
Local dev (copied from .env.example) |
No (gitignored) | No |
.env.staging |
Staging overrides | No | Optional |
.env.production |
Production secrets | No | Yes (.env.keys) |
.env.keys |
Encryption keys per layer (DOTENV_PRIVATE_KEY_PRODUCTION) |
No | No (stored in CI/CD) |
.dotenvx |
Schema rules: required vars, environment overrides, merge order | Yes | No |
Key rules:
- Never commit
.env,.env.production, or.env.keys. Use.env.exampleas the contract. - Production variables must be encrypted with
secrets:encrypt. The encrypted.env.productioncan be committed if needed, but the.env.keysfile must stay out of Git. - Agents that run in CI refer to variables injected by Forgejo Actions, never reading
.envlocally.
CLI Workflow
Install and initialize:
bun install @dotenvx/dotenvx --save-dev
npx dotenvx init
Copy template and set up local dev:
cp .env.example .env
# Edit .env with actual local values
Encrypt a production file before committing:
# Generate encryption keys (store output in CI/CD secret manager)
bun run secrets:generate
# Encrypt production
bun run secrets:encrypt -f .env.production -o .env.production.enc
Run scripts with the correct layer loaded:
# Development (loads .env + any .env.local)
bun run dev
# Production build / deploy (loads encrypted .env.production)
DOTENV_PRIVATE_KEY_PRODUCTION=$PROD_KEY bun run build
# Inspect a value safely (never echo the secret into logs)
bun run secrets:get DATABASE_URL
Schema Validation
.dotenvx defines which variables are required and how layers merge:
# .env.example / schema reference
DATABASE_URL=postgres://user:pass@host:5432/db
REDIS_URL=redis://localhost:6379
NODE_ENV=development
# Add new variables here and document them in kb/sysadmin/secrets.md
Running bun run secrets:validate before CI merge ensures the production file contains every variable listed in .env.example and no extra variables were accidentally removed during rotation.
Agent Integration
Agents must follow these rules:
- Never reference variable values in tickets, KB articles, or chat. Use names (
PRISMA_ORM,GIT_TOKEN). - Never commit
.envvalues or embed them in shell scripts. Always load throughdotenvx run --. - Every rotation must include a Forgejo Issue, a KB change-log entry in secrets.md, and a CI validation (
secrets:validate). - If a script logs an environment value, treat it as a leak: fix the script, rotate the secret, and document the incident.
Security Posture
- Use
chmod 600 .envon all hosts. - Store
.env.keysin Forgejo secrets (Actions), not on developer laptops unless the threat model allows it. - If your threat model extends beyond "no plaintext secrets in Git" to dynamic secrets or audit trails, evaluate HashiCorp Vault, AWS Secrets Manager, or Doppler as the primary store and use Dotenvx only as the runtime loader.
- Rotate secrets with a scheduled Forgejo Action (see scheduler-patterns) and record rotation timestamps in secrets.md.
Practical Examples
Example 1: Verify a CI deployment uses the correct secrets chain
# In a Forgejo Action pipeline
export DOTENV_PRIVATE_KEY_PRODUCTION=${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
bun run secrets:validate # confirms .env.example and .env.production align
bun run db:push # uses DATABASE_URL from encrypted layer
Expected result: db:push succeeds; if .env.production is missing a variable added to .env.example, validation exits non-zero before any deploy step runs.
Example 2: Rotate a production database password
# 1. Update .env.production with new DATABASE_URL (plaintext locally)
# 2. Encrypt
bun run secrets:encrypt -f .env.production
# 3. Update .env.keys if rotating the key itself
bun run secrets:generate --replace
# 4. Deploy encrypted file via CI; record in kb/sysadmin/secrets.md
# 5. Verify application connects with the new value
Expected result: logs show connection success; old connection attempts return authentication errors.
Example 3: Find which variables a new feature requires
bun run secrets:inspect .env.example
# Or grep for variable names used in a module
rg "process\.env\." src/ --count-only
Common Pitfalls & Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
.env missing locally |
Developer cloned repo without .env |
Copy .env.example to .env; never share .env |
| Decryption fails in CI | DOTENV_PRIVATE_KEY_PRODUCTION missing or wrong environment |
Check Forgejo secret name; verify .env.keys file |
| Variable not loaded in production | .env.production not listed in .env.keys or encryption layer wrong |
Run secrets:inspect; check .env.production.enc |
Extra variable in .env.production |
Manual edit added an undeclared variable | Remove it or add to .env.example; validate again |
| Secret value appears in logs | Script logs environment variable directly | Fix script; rotate secret; document in secrets.md |
| Rotation has no audit trail | No Forgejo Issue or KB entry created | Create Issue; append to change log with timestamp |
Next Steps / Ops Actions
- Apply the production encryption workflow to all fogserv.cloud hosts; record completion in the inventory (system-admin-basics).
- Route all rotation events through Forgejo Actions per scheduler-patterns (scheduled audits, backup jobs, rotation scripts).
- Cross-reference this entry in any agent that consumes environment data so expectations stay visible (see agent onboarding docs and secrets.md).
Sources & Related Articles
External references:
- https://www.dotenvx.com/ (Dotenvx official documentation)
- https://unixy.io/blog/secrets-management-2026/ (Vault vs Secrets Manager vs SOPS comparison)
- https://gethasp.com/guides/dotenv-vault-dotenvx-future-of-env/ (Dotenvx threat-model comparison)
- https://www.digitalapplied.com/blog/secrets-management-api-key-rotation-2026-engineering-reference/ (Secrets rotation best practices)
- https://dev.to/stacknotice/secrets-management-in-production-beyond-env-files-2026-2284 (Secrets management beyond
.envfiles) - CISA Logging Reference Architecture: https://www.cisa.gov/resources-tools/resources/logging-reference-architecture
Related KB articles:
- secrets.md — production secrets posture and rotation records
- system-admin-basics.md — inventory and audit discipline
- scheduler-patterns.md — rotation scheduling with systemd timers
Change Log
2026-08-26
- Expanded to production format from previous stub.
- Added layer design table, CLI commands, agent rules, security posture (Vault comparison), troubleshooting table, and web-research citations (CISA Logging Reference, secrets management 2026 comparisons).
- Linked scheduler-patterns.md for rotation automation and secrets.md for audit records.