dotenv and Credentials Summary Complete Security Checklist for Node.js
A comprehensive summary and checklist for managing credentials and environment variables in your Node.js application from .env to production secrets.
dotenv and Credentials Summary
This is a complete summary of everything you need to know about managing credentials in your Node.js application.
The Complete Setup
1. Install dotenv (npm install dotenv)
2. Create .env with all secrets
3. Create .env.example with placeholders
4. Add .env to .gitignore
5. Load dotenv at the top of your entry file
6. Centralize config in a config module
7. Validate required variables
8. Use IAM roles on EC2 (no AWS keys in .env)
9. Use Secrets Manager for production secrets
10. Set up pre-commit hooks to prevent leaks
11. Rotate secrets regularly
12. Audit access logs
Security Checklist
.env File
- .env in .gitignore
- .env.example with placeholder values (committed)
- No real secrets in .env.example
- .env file permissions set to 600 (chmod 600 .env)
- Different .env for development, staging, production
- No secrets in code (always use process.env)
- No secrets in comments or console.log
Git Security
- Pre-commit hooks installed (git-secrets or husky)
- GitHub Secret Scanning enabled
- No secrets in Git history (check with git log -p --all)
- If leaked: rotated secrets and cleaned history
AWS Security
- IAM role attached to EC2 (not access keys in .env)
- IAM policy follows least privilege
- MFA enabled on all IAM users
- Root account not used for daily tasks
- Access keys rotated every 90 days
- CloudTrail enabled for audit
Secrets Management
- AWS Secrets Manager for production secrets
- Secrets encrypted at rest
- IAM controls who can read secrets
- Secret rotation strategy in place
- Encrypted backups of secrets
- Disaster recovery plan documented
Application Code
- dotenv loaded at entry point
- Config centralized in a config module
- Required variables validated at startup
- Type casting (parseInt, Boolean) for non-string values
- Feature flags for conditional behavior
- Error messages don't expose secrets
Code Template
// src/config/index.js require("dotenv").config(); const { cleanEnv, str, num, bool } = require("envalid"); const config = cleanEnv(process.env, { NODE_ENV: str({ choices: ["development", "staging", "production"] }), PORT: num({ default: 3000 }), MONGODB_URI: str(), JWT_SECRET: str({ minLength: 32 }), CLIENT_URL: str(), // AWS SES (if using access keys prefer IAM roles) SES_HOST: str({ default: "" }), SES_PORT: num({ default: 587 }), SES_USER: str({ default: "" }), SES_PASS: str({ default: "" }), SES_FROM: str({ default: "[email protected]" }), // Feature flags ENABLE_EMAILS: bool({ default: false }), ENABLE_CHAT: bool({ default: true }), // Logging LOG_LEVEL: str({ choices: ["error", "warn", "info", "debug"], default: "info" }) }); module.exports = config;
.env.example Template
# Server NODE_ENV=development PORT=3000 # Database MONGODB_URI=mongodb://localhost:27017/devtinder # Authentication JWT_SECRET=replace_with_64_char_random_hex JWT_EXPIRES_IN=7d # AWS SES SES_HOST=email-smtp.us-east-1.amazonaws.com SES_PORT=587 SES_USER=replace_with_ses_username SES_PASS=replace_with_ses_password [email protected] # Frontend CLIENT_URL=http://localhost:5173 # Feature Flags ENABLE_EMAILS=false ENABLE_CHAT=true # Logging LOG_LEVEL=info
.gitignore Template
# Environment variables .env .env.local .env.*.local # Secrets *.pem *.key credentials.json service-account.json # Logs logs/ *.log # Dependencies node_modules/ # OS .DS_Store
The Takeaway
Credential management is a critical security practice. Use .env for development, .env.example as a template, .gitignore to prevent leaks, pre-commit hooks to scan for secrets, IAM roles on EC2 for AWS access, Secrets Manager for production, validation with envalid, and regular key rotation. The key principles: never commit secrets, use least privilege, encrypt at rest, audit access, and have a recovery plan.
Install dotenv, create .env with secrets, create .env.example with placeholders, add .env to .gitignore, load dotenv at the entry point, centralize config in a config module, validate required variables, use IAM roles on EC2, use Secrets Manager for production, and set up pre-commit hooks.
.env, .env.local, .env.*.local, *.pem, *.key, credentials.json, service-account.json. Also ignore logs, node_modules, and OS files. Check with git log -p --all -- .env to ensure .env was never committed.
Use envalid's cleanEnv to define a schema with types, choices, defaults, and minLength. It validates all variables, type-casts them, provides defaults, and throws an error at startup listing all missing or invalid variables. This fails fast instead of failing later with confusing errors.
All the same keys as .env but with placeholder values (replace_with_your_secret, mongodb://localhost:27017/devtinder). This serves as a template for new developers. Never put real secrets in .env.example. It should be committed to Git.
IAM roles on EC2 (not access keys), Secrets Manager for secrets, least privilege IAM policies, MFA on all users, pre-commit hooks, GitHub Secret Scanning, secret rotation strategy, encrypted backups, CloudTrail audit, and a disaster recovery plan. Rotate secrets immediately if leaked.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

