Contents
Managing Configurations with dotenv
Modern applications often require a flexible and secure way to manage environment-specific settings—API keys, database credentials, feature flags, and more. The dotenv methodology popularized by the Twelve-Factor App paradigm advocates for storing configuration in environment variables. The dotenv libraries (Node.js, Python, Ruby, and others) provide a simple mechanism to load these variables from a .env
file into the application’s runtime environment. This article explores how to leverage dotenv effectively, securely, and at scale.
Why Use dotenv
- Separation of code and config: Keep secrets and settings out of source code.
- Environment consistency: Simplify switching between development, testing, staging, and production.
- Portability: Share
.env.example
without leaking credentials. - Simplicity: Tiny footprint, zero dependencies on heavy frameworks.
Core Concepts
dotenv works by reading a plain text file named .env
at the root of your project and loading each KEY=VALUE
pair into process.env
(Node.js) or os.environ
(Python).
Basic rules:
- Lines starting with
#
are comments. - Keys and values are separated by
=
values may be quoted if containing spaces. - Existing environment variables are not overwritten by default (Node.js
dotenv
behavior).
Installation Initialization
Node.js
npm install dotenv --save
Then, at the very top of index.js
(or your entry point):
require(dotenv).config() // now process.env.MY_SECRET is available
Python
pip install python-dotenv
Usage in app.py
:
from dotenv import load_dotenv load_dotenv() # loads .env into os.environ
Example .env Files
.env | .env.example |
---|---|
# Local development DB_HOST=localhost DB_USER=dev_user DB_PASS=s3cr3t API_KEY=abcdef123456 |
# Copy this file to .env and fill in values DB_HOST=your-db-host DB_USER=your-username DB_PASS=your-password API_KEY=your-api-key |
Best Practices
- Never commit
.env
: Add it to.gitignore
to avoid leaking secrets. - Use
.env.example
: Document required variables and defaults for collaborators. - Validate early: Use dotenv-safe (Node.js) or python-dotenv validation to enforce variable presence.
- Override order: In CI/CD, inject real secrets as environment variables dotenv only fills missing keys.
- Secure storage: For production, prefer secret managers (AWS Secrets Manager, HashiCorp Vault) and inject into the environment at runtime.
Advanced Usage
- Custom file paths:
require(dotenv).config({path:.env.local})
. - Multiple environments:
dotenv-flow
or manual loading of.env.development
,.env.production
. - Parsing options:
config({encoding:latin1, debug:true})
for non-UTF8 or verbose logs. - Integration with frameworks: Automatically load before scripts in
package.json
or inwsgi.py
for Django/Flask.
Security Considerations
Key Points:
- Avoid storing long-lived secrets in plaintext.
- Rotate credentials periodically.
- Combine dotenv for local dev and a dedicated secret manager for production.
- Ensure CI logs do not print sensitive values.
Continuous Integration Deployment
In CI pipelines (GitHub Actions, Jenkins, GitLab CI), define environment secrets in the project settings. During the build, these are injected automatically, making .env
unnecessary:
# GitHub Actions example - name: Install dependencies run: npm ci - name: Run tests env: DB_HOST: {{ secrets.DB_HOST }} DB_USER: {{ secrets.DB_USER }} DB_PASS: {{ secrets.DB_PASS }} run: npm test
Further Resources
- dotenv (Node.js) official repository
- python-dotenv official repository
- The Twelve-Factor App: Configuration
- Node.js process.env documentation
Conclusion
The dotenv approach strikes a balance between simplicity and control, enabling developers to manage environment-specific settings without bloating codebases or complicating deployments. By adhering to best practices—ignoring .env
, validating required variables, and integrating with secret-management systems—you build secure, maintainable, and portable applications across development stages.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |