Best Practices
This guide outlines best practices for using env-secrets
effectively and securely.
Secret Management
Secret Structure
✅ Good: Flat, focused secrets
{
"DATABASE_URL": "postgres://user:pass@localhost:5432/db",
"API_KEY": "abc123",
"REDIS_URL": "redis://localhost:6379"
}
❌ Avoid: Overly nested structures
{
"app": {
"database": {
"connection": {
"url": "postgres://user:pass@localhost:5432/db"
}
}
}
}
Secret Naming
✅ Good: Environment-specific naming
# Development
dev/myapp/database
dev/myapp/api-keys
# Staging
staging/myapp/database
staging/myapp/api-keys
# Production
prod/myapp/database
prod/myapp/api-keys
❌ Avoid: Generic names
# Too generic
database
api-keys
secrets
Secret Size
✅ Good: Keep secrets small and focused
# Separate secrets by concern
aws secretsmanager create-secret \
--name prod/myapp/database \
--secret-string '{"DATABASE_URL":"postgres://..."}'
aws secretsmanager create-secret \
--name prod/myapp/api \
--secret-string '{"API_KEY":"abc123","API_SECRET":"xyz789"}'
❌ Avoid: Large, monolithic secrets
# Too large and mixed concerns
aws secretsmanager create-secret \
--name prod/myapp/all-config \
--secret-string '{"database":"...","api":"...","redis":"...","email":"...","logging":"..."}'
Security Practices
IAM Policies
✅ Good: Least privilege access
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": [
"arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/*",
"arn:aws:secretsmanager:us-east-1:123456789012:secret:staging/myapp/*"
]
}
]
}
Note: Replace
123456789012
with your actual AWS account ID in the resource ARNs above.
❌ Avoid: Overly permissive policies
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:*",
"Resource": "*"
}
]
}
Credential Management
✅ Good: Use IAM roles
# On EC2/ECS/Lambda
env-secrets aws -s prod/myapp -r us-east-1 -- node app.js
✅ Good: Use environment variables for CI/CD
# In CI/CD pipeline
export AWS_ACCESS_KEY_ID=$CI_AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$CI_AWS_SECRET_ACCESS_KEY
export AWS_DEFAULT_REGION=us-east-1
env-secrets aws -s prod/myapp -r us-east-1 -- npm run deploy
❌ Avoid: Hardcoded credentials
# Don't do this
env-secrets aws -s prod/myapp -r us-east-1 -p my-profile -- node app.js
# Where my-profile contains hardcoded credentials
Application Integration
Environment Variable Validation
✅ Good: Validate required variables
// app.js
const requiredEnvVars = ['DATABASE_URL', 'API_KEY', 'REDIS_URL'];
for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
console.error(`Missing required environment variable: ${envVar}`);
process.exit(1);
}
}
console.log('All required environment variables are present');
Graceful Degradation
✅ Good: Handle missing secrets gracefully
#!/bin/bash
# start.sh
# Try to load secrets, but don't fail if they're not available
if env-secrets aws -s dev/myapp -r us-east-1 -- echo "Secrets loaded" 2>/dev/null; then
echo "Running with secrets from AWS"
env-secrets aws -s dev/myapp -r us-east-1 -- node app.js
else
echo "Running with local environment variables"
node app.js
fi
Development Workflow
Local Development
✅ Good: Use separate development secrets
# Create development secrets
aws secretsmanager create-secret \
--name dev/myapp \
--secret-string '{
"DATABASE_URL": "postgres://dev:dev@localhost:5432/dev",
"API_KEY": "dev-key-123"
}'
# Use in development
env-secrets aws -s dev/myapp -r us-east-1 -- npm run dev
Testing
✅ Good: Use test-specific secrets
# Create test secrets
aws secretsmanager create-secret \
--name test/myapp \
--secret-string '{
"DATABASE_URL": "postgres://test:test@localhost:5432/test",
"API_KEY": "test-key-456"
}'
# Run tests with test secrets
env-secrets aws -s test/myapp -r us-east-1 -- npm test
Deployment Patterns
Blue-Green Deployment
✅ Good: Use environment-specific secrets
# Blue environment
env-secrets aws -s prod-blue/myapp -r us-east-1 -- node app.js
# Green environment
env-secrets aws -s prod-green/myapp -r us-east-1 -- node app.js
Canary Deployment
✅ Good: Gradual secret rollout
# Deploy to 10% of traffic with new secrets
env-secrets aws -s prod-canary/myapp -r us-east-1 -- node app.js
# Monitor and gradually increase
env-secrets aws -s prod-stable/myapp -r us-east-1 -- node app.js
Monitoring and Observability
Health Checks
✅ Good: Include secret validation in health checks
#!/bin/bash
# health-check.sh
# Check if secrets are accessible
if env-secrets aws -s health/check -r us-east-1 -- echo "OK" 2>/dev/null; then
echo "Secrets accessible"
exit 0
else
echo "Secrets not accessible"
exit 1
fi
Logging
✅ Good: Log secret access (not values)
# Log secret access for audit purposes
env-secrets aws -s prod/myapp -r us-east-1 -- bash -c '
echo "Loading secrets from prod/myapp"
node app.js
'
❌ Avoid: Logging secret values
# Never do this
env-secrets aws -s prod/myapp -r us-east-1 -- bash -c '
echo "Database URL: $DATABASE_URL" # DON'T DO THIS
node app.js
'
Performance Optimization
Region Selection
✅ Good: Use secrets in the same region as your application
# If your app runs in us-west-2, store secrets there too
env-secrets aws -s prod/myapp -r us-west-2 -- node app.js
Secret Organization
✅ Good: Organize secrets by application and environment
# Clear hierarchy
prod/frontend/api-keys
prod/frontend/database
prod/backend/api-keys
prod/backend/database
staging/frontend/api-keys
staging/frontend/database
Error Handling
Robust Scripts
✅ Good: Handle errors gracefully
#!/bin/bash
# deploy.sh
set -e # Exit on any error
echo "Starting deployment..."
# Load secrets and deploy
if env-secrets aws -s prod/myapp -r us-east-1 -- npm run deploy; then
echo "Deployment successful"
else
echo "Deployment failed"
exit 1
fi
Fallback Strategies
✅ Good: Provide fallback options
#!/bin/bash
# start.sh
# Try primary secrets first
if env-secrets aws -s prod/myapp -r us-east-1 -- node app.js; then
echo "Started with primary secrets"
else
echo "Primary secrets failed, trying backup..."
# Try backup secrets
env-secrets aws -s prod/myapp-backup -r us-east-1 -- node app.js
fi
Compliance and Audit
Access Logging
✅ Good: Enable CloudTrail logging
# CloudTrail automatically logs all Secrets Manager access
# No additional configuration needed with env-secrets
Secret Rotation
✅ Good: Implement secret rotation
# Rotate secrets regularly
aws secretsmanager rotate-secret --secret-id prod/myapp/api-keys
# Update applications to use new secret versions
env-secrets aws -s prod/myapp/api-keys -r us-east-1 -- node app.js
Common Anti-Patterns
❌ Don't: Store secrets in version control
# Never commit secrets to git
echo "DATABASE_URL=postgres://..." >> .env # DON'T DO THIS
❌ Don't: Use the same secrets across environments
# Don't use production secrets in development
env-secrets aws -s prod/myapp -r us-east-1 -- npm run dev # DON'T DO THIS
❌ Don't: Share secrets between applications
# Don't use the same secret for multiple apps
env-secrets aws -s shared/secrets -r us-east-1 -- node app1.js # DON'T DO THIS
env-secrets aws -s shared/secrets -r us-east-1 -- node app2.js # DON'T DO THIS
❌ Don't: Use long-lived access keys
# Prefer IAM roles over long-lived access keys
export AWS_ACCESS_KEY_ID=AKIA... # DON'T DO THIS
export AWS_SECRET_ACCESS_KEY=... # DON'T DO THIS