Security Best Practices
Security is built into Easy Deploy by default, but following these best practices will help you maintain the highest level of protection for your applications and data.
Security Fundamentals
Section titled “Security Fundamentals”Secure by Default
Section titled “Secure by Default”Easy Deploy provides security features out of the box:
- HTTPS Everywhere: Automatic SSL certificates for all applications
- Network Isolation: Applications run in isolated environments
- Encrypted Storage: All data encrypted at rest
- Secure Defaults: Security-first configuration out of the box
Shared Responsibility Model
Section titled “Shared Responsibility Model”- Easy Deploy Provides: Infrastructure security, platform security, network security
- You Are Responsible For: Application security, data security, access management, secure coding practices
SSL/TLS Encryption
Section titled “SSL/TLS Encryption”Automatic SSL Certificates
Section titled “Automatic SSL Certificates”All applications include free SSL certificates:
- Let’s Encrypt: Automatic certificate provisioning and renewal
- Multiple Domains: Support for multiple domains per application
- Wildcard Certificates: Available for Enterprise plans
- Perfect Forward Secrecy: Advanced encryption protocols
SSL Configuration
Section titled “SSL Configuration”security: ssl: force_https: true min_tls_version: "1.2" hsts: enabled: true max_age: 31536000 include_subdomains: true preload: trueCustom SSL Certificates
Section titled “Custom SSL Certificates”Upload your own SSL certificates (Pro plan):
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ https://api.easydeploy.com/v1/applications/APP_ID/sslSSL Security Headers
Section titled “SSL Security Headers”Implement security headers for enhanced protection:
// Express.js security headersconst helmet = require('helmet');
app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], scriptSrc: ["'self'"], imgSrc: ["'self'", "data:", "https:"], }, }, hsts: { maxAge: 31536000, includeSubDomains: true, preload: true }}));Authentication & Authorization
Section titled “Authentication & Authorization”User Authentication
Section titled “User Authentication”Implement secure user authentication:
JWT Authentication
Section titled “JWT Authentication”const jwt = require('jsonwebtoken');const bcrypt = require('bcrypt');
// Login endpointapp.post('/login', async (req, res) => { const { email, password } = req.body;
// Find user const user = await User.findOne({ email }); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); }
// Verify password const isValid = await bcrypt.compare(password, user.password); if (!isValid) { return res.status(401).json({ error: 'Invalid credentials' }); }
// Generate JWT const token = jwt.sign( { userId: user.id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '24h' } );
res.json({ token, user: { id: user.id, email: user.email } });});
// Auth middlewarefunction authenticateToken(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1];
if (!token) { return res.status(401).json({ error: 'Access token required' }); }
jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) { return res.status(403).json({ error: 'Invalid token' }); } req.user = user; next(); });}OAuth Integration
Section titled “OAuth Integration”const passport = require('passport');const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy({ clientID: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL: "/auth/google/callback"}, async (accessToken, refreshToken, profile, done) => { try { // Find or create user let user = await User.findOne({ googleId: profile.id }); if (!user) { user = await User.create({ googleId: profile.id, email: profile.emails[0].value, name: profile.displayName }); } return done(null, user); } catch (error) { return done(error, null); }}));Access Control
Section titled “Access Control”Implement role-based access control:
// Role-based authorization middlewarefunction authorize(roles = []) { return (req, res, next) => { if (!req.user) { return res.status(401).json({ error: 'Authentication required' }); }
if (roles.length && !roles.includes(req.user.role)) { return res.status(403).json({ error: 'Insufficient permissions' }); }
next(); };}
// Usageapp.get('/admin', authenticateToken, authorize(['admin']), (req, res) => { res.json({ message: 'Admin only content' });});
app.get('/user', authenticateToken, authorize(['user', 'admin']), (req, res) => { res.json({ message: 'User content' });});Data Security
Section titled “Data Security”Environment Variables
Section titled “Environment Variables”Secure management of sensitive data:
- Encryption at Rest: All environment variables encrypted
- Access Control: Team-based access permissions
- Audit Logging: Track all variable changes
- Secrets Rotation: Regular rotation of sensitive values
Database Security
Section titled “Database Security”Secure your database connections:
// Secure database configurationconst dbConfig = { connectionString: process.env.DATABASE_URL, ssl: { rejectUnauthorized: false, sslmode: 'require' }, max: 20, // connection pool limit idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000,};
// Parameterized queries (prevent SQL injection)const getUser = async (userId) => { const query = 'SELECT * FROM users WHERE id = $1'; const result = await db.query(query, [userId]); return result.rows[0];};
// Input validationconst { body, validationResult } = require('express-validator');
app.post('/user', [ body('email').isEmail().normalizeEmail(), body('password').isLength({ min: 8 }).matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/), body('name').trim().escape()], (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); }
// Process validated input});API Security
Section titled “API Security”Secure your API endpoints:
Rate Limiting
Section titled “Rate Limiting”const rateLimit = require('express-rate-limit');
// General rate limitingconst generalLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // limit each IP to 100 requests per windowMs message: 'Too many requests from this IP'});
// Strict rate limiting for auth endpointsconst authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 5, // limit each IP to 5 requests per windowMs skipSuccessfulRequests: true});
app.use('/api/', generalLimiter);app.use('/auth/', authLimiter);CORS Configuration
Section titled “CORS Configuration”const cors = require('cors');
app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || 'https://yourdomain.com', credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization']}));API Validation
Section titled “API Validation”// Request validation middlewareconst validateApiKey = (req, res, next) => { const apiKey = req.headers['x-api-key'];
if (!apiKey) { return res.status(401).json({ error: 'API key required' }); }
// Validate API key if (!isValidApiKey(apiKey)) { return res.status(401).json({ error: 'Invalid API key' }); }
next();};
// Content type validationconst validateJson = (req, res, next) => { if (req.method === 'POST' || req.method === 'PUT') { if (!req.is('application/json')) { return res.status(400).json({ error: 'Content-Type must be application/json' }); } } next();};Network Security
Section titled “Network Security”Firewall Rules
Section titled “Firewall Rules”Configure network access rules:
security: firewall: inbound: - port: 443 protocol: tcp source: "0.0.0.0/0" - port: 80 protocol: tcp source: "0.0.0.0/0" redirect_to: 443
outbound: - port: 443 protocol: tcp destination: "0.0.0.0/0" - port: 53 protocol: udp destination: "0.0.0.0/0"DDoS Protection
Section titled “DDoS Protection”Easy Deploy includes DDoS protection:
- Traffic Analysis: Real-time traffic pattern analysis
- Rate Limiting: Automatic rate limiting for suspicious traffic
- Geographic Filtering: Block traffic from specific regions
- Challenge-Response: CAPTCHA challenges for suspicious requests
IP Restrictions
Section titled “IP Restrictions”Restrict access by IP address:
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "allowed_ips": ["192.168.1.0/24", "10.0.0.0/8"], "blocked_ips": ["192.168.1.100"] }' \ https://api.easydeploy.com/v1/applications/APP_ID/ip-restrictionsSecure Development
Section titled “Secure Development”Input Validation
Section titled “Input Validation”Always validate and sanitize user input:
const validator = require('validator');const xss = require('xss');
// Input sanitizationfunction sanitizeInput(input) { if (typeof input !== 'string') return input;
// Remove XSS input = xss(input);
// Trim whitespace input = input.trim();
return input;}
// Validation functionsfunction validateEmail(email) { return validator.isEmail(email);}
function validatePassword(password) { return validator.isLength(password, { min: 8 }) && /[A-Z]/.test(password) && /[a-z]/.test(password) && /\d/.test(password) && /[!@#$%^&*]/.test(password);}
function validateUrl(url) { return validator.isURL(url, { protocols: ['http', 'https'], require_protocol: true });}Secure Headers
Section titled “Secure Headers”Implement security headers:
// Security headers middlewareapp.use((req, res, next) => { // Prevent XSS attacks res.setHeader('X-XSS-Protection', '1; mode=block');
// Prevent clickjacking res.setHeader('X-Frame-Options', 'DENY');
// Prevent MIME type sniffing res.setHeader('X-Content-Type-Options', 'nosniff');
// Referrer policy res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
// Content Security Policy res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" );
next();});Error Handling
Section titled “Error Handling”Secure error handling:
// Production error handlerapp.use((err, req, res, next) => { // Log error details (server-side only) console.error('Error:', { message: err.message, stack: err.stack, url: req.url, method: req.method, ip: req.ip, userAgent: req.get('User-Agent') });
// Send generic error response (don't leak sensitive info) const isDevelopment = process.env.NODE_ENV === 'development';
res.status(err.status || 500).json({ error: 'Internal Server Error', message: isDevelopment ? err.message : 'Something went wrong', ...(isDevelopment && { stack: err.stack }) });});Compliance & Auditing
Section titled “Compliance & Auditing”Audit Logging
Section titled “Audit Logging”Log security-relevant events:
const auditLogger = require('./audit-logger');
// Authentication eventsapp.post('/login', async (req, res) => { const { email } = req.body;
try { const user = await authenticateUser(email, password);
auditLogger.log('user.login.success', { userId: user.id, email: user.email, ip: req.ip, userAgent: req.get('User-Agent') });
res.json({ token, user }); } catch (error) { auditLogger.log('user.login.failure', { email, ip: req.ip, userAgent: req.get('User-Agent'), reason: error.message });
res.status(401).json({ error: 'Invalid credentials' }); }});
// Data access eventsapp.get('/user/:id', authenticateToken, async (req, res) => { const { id } = req.params;
auditLogger.log('user.data.access', { accessedBy: req.user.id, targetUser: id, ip: req.ip, timestamp: new Date().toISOString() });
const user = await User.findById(id); res.json(user);});GDPR Compliance
Section titled “GDPR Compliance”Implement data protection features:
// Data export (Right to portability)app.get('/user/:id/export', authenticateToken, authorize(['user', 'admin']), async (req, res) => { const userData = await User.findById(req.params.id).lean(); const userActivity = await Activity.find({ userId: req.params.id }).lean();
const exportData = { user: userData, activities: userActivity, exportedAt: new Date().toISOString() };
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Disposition', 'attachment; filename=user-data.json'); res.json(exportData);});
// Data deletion (Right to erasure)app.delete('/user/:id', authenticateToken, authorize(['admin']), async (req, res) => { const userId = req.params.id;
// Delete user data across all systems await User.findByIdAndDelete(userId); await Activity.deleteMany({ userId }); await UserPreferences.deleteMany({ userId });
auditLogger.log('user.data.deleted', { deletedBy: req.user.id, targetUser: userId, timestamp: new Date().toISOString() });
res.json({ message: 'User data deleted successfully' });});Security Monitoring
Section titled “Security Monitoring”Security Alerts
Section titled “Security Alerts”Set up alerts for security events:
# Security alert configurationsecurity_alerts: - name: "Multiple Failed Logins" condition: "failed_logins > 5 within 10 minutes from same IP" action: "block_ip"
- name: "Suspicious API Usage" condition: "api_requests > 1000 per minute from single IP" action: "rate_limit"
- name: "Admin Account Access" condition: "admin login from new location" action: "require_2fa"Vulnerability Scanning
Section titled “Vulnerability Scanning”Automated security scanning:
- Dependency Scanning: Check for vulnerable packages
- Code Analysis: Static security analysis
- Container Scanning: Scan Docker images for vulnerabilities
- Infrastructure Scanning: Check for misconfigurations
Incident Response
Section titled “Incident Response”Security Incident Workflow
Section titled “Security Incident Workflow”- Detection: Automated alerts and monitoring
- Assessment: Evaluate scope and impact
- Containment: Isolate affected systems
- Investigation: Analyze logs and evidence
- Recovery: Restore normal operations
- Lessons Learned: Improve security measures
Emergency Procedures
Section titled “Emergency Procedures”# Emergency: Rotate all API keyscurl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ https://api.easydeploy.com/v1/applications/APP_ID/rotate-keys
# Emergency: Enable maintenance modecurl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"enabled": true, "message": "Maintenance in progress"}' \ https://api.easydeploy.com/v1/applications/APP_ID/maintenance
# Emergency: Block suspicious IPcurl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"ip": "192.168.1.100", "reason": "suspicious activity"}' \ https://api.easydeploy.com/v1/applications/APP_ID/block-ipSecurity Checklist
Section titled “Security Checklist”Pre-Deployment
Section titled “Pre-Deployment”- Enable HTTPS for all endpoints
- Implement proper authentication
- Validate all user inputs
- Set up rate limiting
- Configure security headers
- Review environment variables
- Scan dependencies for vulnerabilities
Post-Deployment
Section titled “Post-Deployment”- Monitor security alerts
- Review access logs regularly
- Update dependencies
- Rotate secrets periodically
- Conduct security audits
- Test incident response procedures
- Monitor compliance requirements
Need help with security? Check our troubleshooting guide or contact our security team.