Security

Security Best Practices

Security guidelines for SelfHostedDB deployments

This guide covers security best practices for deploying and operating SelfHostedDB in production environments.


Table of Contents


Authentication Security

HTTP Basic Authentication

Best Practices:

  1. Use Strong Passwords:

    # Generate strong password (Linux/Mac)
    openssl rand -base64 32
     
    # Windows PowerShell
    [Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 }))
  2. Change Default Credentials:

    • Never use default admin/secret in production
    • Use environment variables, not hardcoded values
    • Rotate passwords regularly (every 90 days)
  3. Password Requirements:

    • Minimum 16 characters
    • Mix of uppercase, lowercase, numbers, symbols
    • No dictionary words
    • No personal information
  4. Storage:

    • Store in secrets manager (AWS Secrets Manager, Azure Key Vault, etc.)
    • Never commit to version control
    • Use different credentials per environment

API Keys

Best Practices:

  1. Key Generation:

    • Keys are automatically generated (64-character hex strings)
    • Cryptographically secure random generation
    • Store keys securely (only shown once on creation)
  2. Key Management:

    • Use descriptive key names
    • Rotate keys regularly
    • Revoke compromised keys immediately
    • Use different keys for different services/environments
  3. Key Types:

    • anon: For read-only access (when applicable)
    • service_role: For full access (use sparingly)
  4. Storage:

    • Store in environment variables or secrets manager
    • Never log or expose in error messages
    • Use HTTPS for all API requests

Database Security

Connection Security

  1. Use SSL/TLS:

    # Always use SSL in production
    DATABASE_URL=postgres://user:pass@host:5432/db?sslmode=require
  2. Connection String Security:

    • Never hardcode connection strings
    • Use environment variables or secrets manager
    • Rotate database passwords regularly
  3. Database User Permissions:

    • Use least privilege principle
    • Create dedicated users for application
    • Grant only necessary permissions
    • Avoid using superuser accounts

SQL Injection Prevention

The application uses parameterized queries to prevent SQL injection:

// ✅ SAFE: Parameterized query
await pool.query('SELECT * FROM users WHERE id = $1', [userId]);
 
// ❌ DANGEROUS: String concatenation (never do this)
await pool.query(`SELECT * FROM users WHERE id = ${userId}`);

All endpoints use parameterized queries. However, be cautious with:

  • Table names (validated with regex)
  • Schema names (validated with regex)
  • Custom SQL queries (user-provided)

Database Access Control

  1. Network Isolation:

    • Use private subnets for databases
    • Restrict database port (5432) to app containers only
    • Use security groups/firewall rules
  2. Connection Pooling:

    • Limit connection pool size
    • Monitor active connections
    • Set appropriate timeouts

Network Security

Firewall Configuration

Recommended Rules:

  1. Application Server:

    • Allow inbound: Port 3001 (or 80/443 with reverse proxy)
    • Allow inbound: SSH (port 22) from trusted IPs only
    • Allow outbound: Port 5432 to database
  2. Database Server:

    • Allow inbound: Port 5432 from application servers only
    • Block all other inbound traffic
    • Use security groups (cloud) or iptables (self-hosted)

HTTPS Configuration

Always use HTTPS in production:

  1. Reverse Proxy (nginx):

    server {
        listen 443 ssl http2;
        server_name your-domain.com;
        
        ssl_certificate /path/to/cert.pem;
        ssl_certificate_key /path/to/key.pem;
        
        location / {
            proxy_pass http://localhost:3001;
        }
    }
  2. Let's Encrypt (Free SSL):

    sudo certbot --nginx -d your-domain.com
  3. Cloud Load Balancers:

    • AWS: Application Load Balancer with ACM certificate
    • Azure: App Gateway with SSL certificate
    • GCP: Cloud Load Balancer with managed SSL

HSTS Headers

Enable HTTP Strict Transport Security:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Container Security

Image Security

  1. Base Images:

    • Use official, minimal base images (node:18-slim)
    • Regularly update base images
    • Scan images for vulnerabilities
  2. Image Scanning:

    # Using Trivy
    trivy image selfhosteddb:latest
     
    # Using Snyk
    snyk test --docker selfhosteddb:latest
  3. Multi-stage Builds:

    • Use multi-stage builds to reduce image size
    • Exclude unnecessary files from final image
    • Don't include secrets in images

Runtime Security

  1. Non-root User:

    • Run containers as non-root user (if possible)
    • Use read-only filesystems where applicable
  2. Resource Limits:

    # docker-compose.yml
    services:
      app:
        deploy:
          resources:
            limits:
              cpus: '1'
              memory: 2G
  3. Container Isolation:

    • Use separate networks for different services
    • Limit container capabilities
    • Use security profiles

License System Security

License Key Storage

Local License Cache:

  • License keys are stored locally in license.json file
  • Optionally encrypted using LICENSE_ENCRYPTION_KEY environment variable
  • Recommended to encrypt in production deployments

Encryption Setup:

# Generate encryption key
openssl rand -hex 32
 
# Set in environment
LICENSE_ENCRYPTION_KEY=your-generated-key-here

License Server Communication

HTTPS Required:

  • Always use HTTPS for LICENSE_SERVER_URL in production
  • License validation requests are sent over HTTPS
  • Prevents man-in-the-middle attacks

Example:

# Production
LICENSE_SERVER_URL=https://license.yourdomain.com
 
# Development (local testing)
LICENSE_SERVER_URL=http://localhost:3002

License Validation

Email-Based Validation:

  • License keys are tied to purchaser's email address
  • Prevents license sharing between different owners
  • Same owner can deploy on unlimited machines/platforms

Best Practices:

  • Store LICENSE_SERVER_URL in environment variables
  • Use HTTPS for license server communication
  • Encrypt local license cache in production
  • Rotate LICENSE_ENCRYPTION_KEY if compromised

Secrets Management

Never Do This

Hardcode secrets in code:

// BAD
const password = "my-secret-password";

Commit secrets to Git:

# BAD - .env file in repository
git add .env

Include secrets in Docker images:

# BAD
ENV AUTH_PASS=secret123

Share secrets via email/chat:

  • Use secure channels only

Best Practices

Use Secrets Managers:

AWS:

# Store secret
aws secretsmanager create-secret \
  --name selfhosteddb/auth-pass \
  --secret-string "your-password"
 
# Use in ECS/EKS
# Reference in task definition or Kubernetes secrets

Azure:

# Store in Key Vault
az keyvault secret set \
  --vault-name selfhosteddb-vault \
  --name auth-pass \
  --value "your-password"

GCP:

# Store in Secret Manager
echo -n "your-password" | gcloud secrets create auth-pass --data-file=-

Use Environment Variables:

# At runtime (not in image)
docker run -e AUTH_PASS="$(cat secret.txt)" selfhosteddb:latest

Rotate Secrets Regularly:

  • Rotate passwords every 90 days
  • Rotate API keys every 90 days
  • Update database passwords regularly

SSL/TLS Configuration

Database SSL

Always use SSL for database connections in production:

# Connection string with SSL
DATABASE_URL=postgres://user:pass@host:5432/db?sslmode=require

SSL Modes:

  • sslmode=require - Require SSL (recommended)
  • sslmode=prefer - Prefer SSL, fallback to non-SSL
  • sslmode=verify-full - Require SSL and verify certificate
  • sslmode=disable - Disable SSL (not recommended)

Application SSL

Use HTTPS for all API requests:

  1. Development:

    • Can use HTTP for local development
    • Never use HTTP in production
  2. Production:

    • Always use HTTPS
    • Redirect HTTP to HTTPS
    • Use valid SSL certificates
    • Enable HSTS headers

Security Checklist

Pre-Deployment

  • Changed default AUTH_USER and AUTH_PASS
  • Generated strong passwords (16+ characters)
  • Database connection uses SSL (?sslmode=require)
  • Secrets stored in secrets manager (not in code)
  • Firewall rules configured
  • HTTPS enabled (reverse proxy or load balancer)
  • .env file excluded from Git and Docker images
  • Database user has least privilege permissions

Post-Deployment

  • Test authentication with new credentials
  • Verify HTTPS is working
  • Test database SSL connection
  • Monitor logs for suspicious activity
  • Set up security alerts
  • Document security procedures
  • Plan for incident response

Ongoing Maintenance

  • Rotate passwords every 90 days
  • Rotate API keys every 90 days
  • Update Docker images regularly
  • Scan images for vulnerabilities
  • Review access logs
  • Update dependencies (npm audit)
  • Monitor for security advisories

Common Security Mistakes

1. Default Credentials

Mistake: Using default admin/secret in production

Fix: Always change default credentials before deployment

2. Exposed Secrets

Mistake: Committing .env files or hardcoding secrets

Fix: Use secrets manager, never commit secrets

3. No SSL/TLS

Mistake: Using HTTP or unencrypted database connections

Fix: Always use HTTPS and database SSL in production

4. Weak Passwords

Mistake: Using simple, guessable passwords

Fix: Use password generator, enforce strong passwords

5. Overly Permissive Database User

Mistake: Using superuser or overly permissive database user

Fix: Create dedicated user with least privilege


Incident Response

If Credentials Are Compromised

  1. Immediately:

    • Rotate all compromised credentials
    • Revoke affected API keys
    • Review access logs
  2. Investigation:

    • Check for unauthorized access
    • Review database logs
    • Check for data exfiltration
  3. Remediation:

    • Update all credentials
    • Patch vulnerabilities
    • Improve security measures

If Database Is Compromised

  1. Immediately:

    • Isolate affected systems
    • Change all database passwords
    • Review database access logs
  2. Recovery:

    • Restore from backup if needed
    • Verify data integrity
    • Update security measures

Security Monitoring

Log Monitoring

Monitor logs for:

  • Failed authentication attempts
  • Unusual query patterns
  • High error rates
  • Suspicious IP addresses

Tools

  • AWS: CloudWatch Logs, GuardDuty
  • Azure: Application Insights, Security Center
  • GCP: Cloud Logging, Security Command Center
  • Self-hosted: ELK Stack, Grafana Loki

Related Documentation

Security Resources:


Additional Resources


Last Updated: 2025-01-27