@phantasm0009/secure-env
v1.0.3
Published
End-to-end secret management with encrypted .env files, git protection, and runtime validation
Maintainers
Readme
@phantasm0009/secure-env
🔐 End-to-end secret management for Node.js applications with encrypted .env files, git protection, and runtime validation.
Features
- 🔐 Encrypted Environment Files - AES-256-GCM encryption with secure key generation
- 🛡️ Git Protection - Pre-commit hooks prevent accidental commits of sensitive files
- ✅ Runtime Validation - Zod-like schema validation for environment variables
- ☁️ Cloud KMS Support - AWS KMS and Google Cloud KMS integration
- 🚀 Zero Dependencies - Production-ready with Node.js 18+ built-ins
- 📦 Multiple Formats - Support for
.env.local,.env.production, etc.
Installation
npm install @phantasm0009/secure-envQuick Start
1. Basic Setup
Create a .env file with your secrets:
# .env
API_KEY=your-secret-api-key-here
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
DEBUG=true
PORT=30002. Encrypt Your Environment File
# Generate encryption key and encrypt .env
npx secure-env encrypt
# This creates:
# - .env.key (keep this secret!)
# - .env.encrypted (safe to commit)3. Setup Git Protection
# Install pre-commit hooks and update .gitignore
npx secure-env setup-git4. Load and Validate in Your Application
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
// Define validation schema
const schema = envSchema({
PORT: number().min(3000).max(8000),
API_KEY: string().length(32),
DEBUG: boolean(),
DATABASE_URL: string().regex(/^postgresql:\/\//)
});
// Load and validate environment
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
console.log('Validated environment:', env);
// Output: { PORT: 3000, API_KEY: 'your-secret-api-key-here', DEBUG: true, ... }CLI Commands
Encryption Commands
# Encrypt .env file (creates .env.encrypted and .env.key)
secure-env encrypt
# Encrypt specific file
secure-env encrypt .env.production
# Decrypt to .env
secure-env decrypt
# Decrypt to specific file
secure-env decrypt --output .env.development
# Generate new encryption key
secure-env generate-key
# Use custom key path
secure-env encrypt --key-path ./keys/production.keyValidation Commands
# Check if required variables are present
secure-env check PORT API_KEY DATABASE_URL
# Validate against schema file
secure-env validate schema.jsGit Protection
# Setup git hooks and .gitignore protection
secure-env setup-gitAPI Reference
SecureEnv Class
const { SecureEnv } = require('@phantasm0009/secure-env');
const secureEnv = new SecureEnv();
// Encryption/Decryption
secureEnv.encryptFile('.env', '.env.encrypted');
secureEnv.decryptFile('.env.encrypted', '.env');
// Key management
const key = secureEnv.generateKey();
secureEnv.saveKey(key, '.env.key');
// Load with validation
const env = secureEnv.load(schema, { override: true });
// Setup git protection
secureEnv.setupGitProtection();Schema Validation
Build validation schemas with chainable methods:
const { envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
const schema = envSchema({
// String validation
API_KEY: string()
.length(32) // Exact length
.regex(/^[a-zA-Z0-9]+$/) // Pattern matching
USERNAME: string()
.min(3) // Minimum length
.max(20), // Maximum length
// Number validation
PORT: number()
.min(3000) // Minimum value
.max(8000) // Maximum value
.int(), // Must be integer
TIMEOUT: number()
.min(0),
// Boolean validation
DEBUG: boolean(),
ENABLED: boolean()
});Environment Loading
const { loadEnv } = require('@phantasm0009/secure-env');
// Load with options
const env = loadEnv({
path: './config', // Directory to search
override: true, // Override existing values
debug: true // Log loaded files
});Manual Validation
const { validateEnv, checkRequired } = require('@phantasm0009/secure-env');
// Validate against schema
const validated = validateEnv(process.env, schema);
// Check required variables
const result = checkRequired(['API_KEY', 'DATABASE_URL']);
if (!result.valid) {
console.error('Missing:', result.missing);
}Real-World Examples
Express.js Application
const express = require('express');
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
// Define schema for your app
const schema = envSchema({
PORT: number().min(3000).max(8000),
NODE_ENV: string().regex(/^(development|production|test)$/),
JWT_SECRET: string().min(32),
DATABASE_URL: string().regex(/^postgresql:\/\//),
REDIS_URL: string().regex(/^redis:\/\//),
DEBUG: boolean()
});
// Load and validate environment
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
const app = express();
app.get('/', (req, res) => {
res.json({
message: 'Server running securely!',
environment: env.NODE_ENV,
debug: env.DEBUG
});
});
app.listen(env.PORT, () => {
console.log(`Server running on port ${env.PORT}`);
});Next.js Application
// next.config.js
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
const schema = envSchema({
NEXT_PUBLIC_API_URL: string().regex(/^https?:\/\//),
DATABASE_URL: string(),
NEXTAUTH_SECRET: string().min(32),
NEXTAUTH_URL: string().regex(/^https?:\/\//),
NODE_ENV: string().regex(/^(development|production|test)$/)
});
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
module.exports = {
env: {
CUSTOM_KEY: env.NEXT_PUBLIC_API_URL,
},
// ... other Next.js config
};Docker Deployment
# Dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy source code
COPY . .
# Decrypt environment file during build
RUN npx secure-env decrypt --output .env
# Start application
CMD ["npm", "start"]# Build with encrypted env file
docker build -t myapp .
# Or mount key at runtime
docker run -v $(pwd)/.env.key:/app/.env.key myappCI/CD Pipeline
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Create encryption key
run: echo "${{ secrets.ENV_KEY }}" > .env.key
- name: Decrypt environment
run: npx secure-env decrypt
- name: Run tests
run: npm test
- name: Deploy
run: npm run deployFile Hierarchy
The loader searches for environment files in this order (later files override earlier ones):
.env.env.local.env.development/.env.production/.env.test.env.development.local/.env.production.local/.env.test.local
Security Best Practices
Key Management
# Generate strong keys for different environments
secure-env generate-key --key-path .env.development.key
secure-env generate-key --key-path .env.production.key
# Encrypt environment-specific files
secure-env encrypt .env.development --key-path .env.development.key
secure-env encrypt .env.production --key-path .env.production.keyGit Protection
The git protection feature automatically:
- Prevents commits of
.env*files - Prevents commits of
*.keyfiles - Updates
.gitignorewith secure patterns - Shows helpful error messages when protection is triggered
Production Deployment
For production environments, consider using cloud KMS:
const { createKMSProvider } = require('@phantasm0009/secure-env');
// AWS KMS
const kms = createKMSProvider('aws', {
region: 'us-east-1',
keyId: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
});
// Google Cloud KMS
const kms = createKMSProvider('google', {
projectId: 'my-project',
keyRingId: 'my-keyring',
keyId: 'my-key'
});Error Handling
const { SecureEnv } = require('@phantasm0009/secure-env');
try {
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
console.log('Environment loaded successfully');
} catch (error) {
if (error.message.includes('Environment validation failed')) {
console.error('❌ Configuration errors:');
console.error(error.message);
process.exit(1);
}
if (error.message.includes('Encryption key not found')) {
console.error('❌ Missing encryption key. Run: npx secure-env generate-key');
process.exit(1);
}
throw error;
}Advanced Usage
Custom Validation Messages
const schema = envSchema({
EMAIL: string().regex(
/^[^\s@]+@[^\s@]+\.[^\s@]+$/,
'Must be a valid email address'
),
API_VERSION: string().regex(
/^v\d+$/,
'Must be in format v1, v2, etc.'
),
PORT: number()
.min(1024, 'Port must be above 1024')
.max(65535, 'Port must be below 65535')
});Multiple Environment Files
// Load specific environment configurations
const devEnv = loadEnv({
path: './environments/development',
debug: true
});
const prodEnv = loadEnv({
path: './environments/production',
override: true
});Schema Composition
const baseSchema = envSchema({
NODE_ENV: string().regex(/^(development|production|test)$/),
DEBUG: boolean()
});
const databaseSchema = envSchema({
DATABASE_URL: string().regex(/^postgresql:\/\//),
DB_POOL_SIZE: number().min(1).max(20)
});
const apiSchema = envSchema({
API_KEY: string().length(32),
API_TIMEOUT: number().min(1000)
});
// Combine schemas
const fullSchema = envSchema({
...baseSchema,
...databaseSchema,
...apiSchema
});Testing
Run the test suite:
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run specific test file
node --test test/encryption.test.jsTroubleshooting
Common Issues
Q: "Encryption key not found" error
# Generate a new key
npx secure-env generate-key
# Or specify custom path
npx secure-env generate-key --key-path ./custom/path/.env.keyQ: Git hooks not working
# Reinstall git hooks
npx secure-env setup-git
# Check if .git/hooks/pre-commit exists and is executable
ls -la .git/hooks/pre-commitQ: Validation errors
# Check which variables are missing
npx secure-env check API_KEY DATABASE_URL PORT
# Validate against schema file
npx secure-env validate ./config/schema.jsQ: Environment not loading
// Enable debug mode to see which files are loaded
const env = loadEnv({ debug: true });Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Add tests for new functionality
- Ensure all tests pass:
npm test - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Submit a pull request
License
MIT License - see LICENSE file for details.
Security
For security issues, please email [email protected] instead of using GitHub issues.
Changelog
v1.0.0
- Initial release
- AES-256-GCM encryption for .env files
- Git protection with pre-commit hooks
- Runtime validation with schema system
- CLI tools for encryption/decryption
- Cloud KMS integration support
- Comprehensive test suite
