Production Secrets Management Strategy From .env to AWS Secrets Manager
Learn the complete strategy for managing production secrets in Node.js from .env files to AWS Secrets Manager, key rotation, and disaster recovery.
Production Secrets Management Strategy
Managing production secrets is a critical security responsibility. This guide covers the complete strategy from development to production.
Secrets Management Tiers
Tier 1: Development (.env)
# .env.development (never committed) MONGODB_URI=mongodb://localhost:27017/devtinder JWT_SECRET=dev_secret_random_hex_string AWS_ACCESS_KEY_ID=dev_key AWS_SECRET_ACCESS_KEY=dev_secret
Best for: Local development, small projects Security: Low (stored in plain text, but not committed)
Tier 2: Staging (.env on server)
# .env.staging on staging server MONGODB_URI=mongodb+srv://staging:[email protected]/devtinder_staging JWT_SECRET=staging_secret_different_from_dev AWS_ACCESS_KEY_ID=staging_key AWS_SECRET_ACCESS_KEY=staging_secret
Best for: Staging environments Security: Medium (stored on server, file permissions restricted)
# Restrict file permissions chmod 600 .env chown ubuntu:ubuntu .env
Tier 3: Production (AWS Secrets Manager)
// Store secrets in AWS Secrets Manager const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); const client = new SecretsManagerClient({ region: "us-east-1" }); const loadSecrets = async () => { const response = await client.send( new GetSecretValueCommand({ SecretId: "devtinder/prod" }) ); return JSON.parse(response.SecretString); }; // At startup const secrets = await loadSecrets(); const config = { mongoUri: secrets.MONGODB_URI, jwtSecret: secrets.JWT_SECRET, sesCredentials: secrets.SES_CREDENTIALS };
Best for: Production, enterprise apps Security: High (encrypted at rest, IAM-controlled, audit trail)
Key Rotation Strategy
Rotate secrets regularly to minimize the impact of a leak:
JWT Secret Rotation
// Support multiple JWT secrets during rotation const jwtSecrets = [process.env.JWT_SECRET_NEW, process.env.JWT_SECRET_OLD]; // Verify with any valid secret const verifyToken = (token) => { for (const secret of jwtSecrets) { try { return jwt.verify(token, secret); } catch (err) { continue; } } throw new Error("Invalid token"); }; // Sign with the new secret const signToken = (payload) => { return jwt.sign(payload, process.env.JWT_SECRET_NEW); };
Database Password Rotation
- Create a new database user with a new password
- Update the secret in Secrets Manager
- Restart the app (or reconnect with new credentials)
- Verify the app works
- Delete the old database user
AWS Key Rotation
- Create a new IAM access key
- Update the secret in Secrets Manager or .env
- Restart the app
- Verify the app works
- Deactivate and delete the old access key
Secrets Manager Auto-Rotation
AWS Secrets Manager can auto-rotate database credentials:
- Go to Secrets Manager → Your secret → Edit rotation
- Configure rotation interval (e.g., 30 days)
- Use the Lambda function provided by AWS
- Secrets Manager automatically rotates the password
Disaster Recovery
Backup Secrets
# Export secrets (encrypted) aws secretsmanager get-secret-value \ --secret-id devtinder/prod \ --query SecretString \ --output text | gpg --cipher-algo AES256 --compress-algo BZIP2 -o secrets.gpg # Store the encrypted backup securely (e.g., S3 with KMS encryption) aws s3 cp secrets.gpg s3://devtinder-backups/secrets/secrets-$(date +%Y%m%d).gpg
Recovery Plan
- Identify which secrets are compromised
- Generate new secrets
- Update Secrets Manager
- Restart all affected services
- Invalidate old tokens (for JWT)
- Notify affected users (if data was accessed)
Secrets Audit
Regularly audit your secrets:
# List all secrets in Secrets Manager aws secretsmanager list-secrets # Check when secrets were last rotated aws secretsmanager list-secrets --query 'SecretList[*].[Name,LastRotatedDate]' # Check who accessed secrets aws cloudtrail lookup-events \ --lookup-attribute AttributeKey=EventName,AttributeValue=GetSecretValue \ --max-results 20
The Takeaway
Production secrets management involves: .env for development, .env with restricted permissions for staging, AWS Secrets Manager for production, regular key rotation (especially after incidents), auto-rotation for database credentials, encrypted backups for disaster recovery, and regular audits. The key principles are encryption at rest, IAM-controlled access, audit trails, and least privilege.
Use AWS Secrets Manager for production (encrypted at rest, IAM-controlled, audit trail, auto-rotation). Use .env with restricted permissions (chmod 600) for staging. Use .env for development. Never commit any .env to Git. Rotate secrets regularly.
Support multiple JWT secrets during rotation: verify tokens with any of the old and new secrets, but sign new tokens with the new secret. After 7 days (token expiry), remove the old secret. Users with old tokens stay logged in until their token expires.
Export from Secrets Manager, encrypt with GPG (gpg --cipher-algo AES256), and store in an S3 bucket with KMS encryption. Store the GPG passphrase separately (e.g., in a password manager or separate KMS key). Test restoration periodically.
Secrets Manager can automatically rotate database credentials on a schedule (e.g., every 30 days). It uses a Lambda function to update the password in both the database and the secret. Your app retrieves the new credentials on the next startup or reconnect.
Use AWS CloudTrail to log all GetSecretValue API calls. Regularly review who accessed secrets and when. Use Secrets Manager's built-in rotation tracking (LastRotatedDate). Set up CloudWatch alerts for unusual access patterns (e.g., access from unknown IPs).
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.

