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:

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:

Security Posture

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

Sources & Related Articles

External references:

Related KB articles:

Change Log

2026-08-26

Choose Theme

Your selection is saved locally.

Neural Cacophony
Aperture v2
Flux v1
Mosaic Chaos
Nexus v1
Nexus Zest
Prism v2
Synapse