Security Hardening
This guide covers security best practices for deploying FireBackup Enterprise in production environments. Follow these recommendations to protect your backup data and infrastructure.
Security Overview
FireBackup implements multiple layers of security:
Security Layers
Network Security:
- TLS 1.3 encryption
- Firewall rules
- Rate limiting
Authentication:
- Google OAuth 2.0
- JWT tokens
- Session management
Authorization:
- Role-based access control
- Organization isolation
- Resource-level permissions
Data Protection:
- AES-256-GCM encryption
- Encryption at rest
- Secure key management
Audit & Monitoring:
- Audit logging
- Activity monitoring
- Alerting
TLS Configuration
Minimum Requirements
- TLS 1.2 minimum (TLS 1.3 recommended)
- Strong cipher suites only
- Valid certificates from trusted CA
Nginx TLS Configuration
# Modern TLS configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
# Session settings
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Certificate chain
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
# DH parameters (generate with: openssl dhparam -out dhparam.pem 4096)
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
Security Headers
# HSTS (HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Content Security
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Content Security Policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.firebackup.io wss://api.firebackup.io;" always;
# Permissions Policy
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
Authentication Security
JWT Configuration
# Strong JWT secret (minimum 32 bytes)
JWT_SECRET=$(openssl rand -hex 32)
# Short token lifetime
JWT_EXPIRES_IN=24h
# Refresh token configuration
JWT_REFRESH_EXPIRES_IN=7d
OAuth Security
# Use HTTPS callback URLs only
GOOGLE_CALLBACK_URL=https://api.firebackup.io/api/v1/auth/google/callback
# Limit OAuth scopes
OAUTH_SCOPES=email,profile,https://www.googleapis.com/auth/firebase
Session Security
# Secure session configuration
SESSION_SECURE=true
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=strict
SESSION_MAX_AGE=86400000
Encryption
Backup Encryption
All backups are encrypted with AES-256-GCM:
Backup Process:
- Export data from Firebase
- Compress with Brotli
- Generate random IV (12 bytes)
- Encrypt with AES-256-GCM
- Append auth tag (16 bytes)
- Upload to storage
Key Management
# Generate encryption key
ENCRYPTION_KEY=$(openssl rand -hex 32)
# Store in secure location
# - Kubernetes Secret
# - AWS Secrets Manager
# - HashiCorp Vault
# - Azure Key Vault
Key Rotation
For Enterprise license, enable key rotation:
ENCRYPTION_KEY_ROTATION=true
ENCRYPTION_KEY_ROTATION_INTERVAL=90d
ENCRYPTION_OLD_KEYS=key1,key2,key3
Database Security
PostgreSQL Hardening
-- Disable remote root access
ALTER USER postgres PASSWORD 'strong-password';
-- Create application user with limited permissions
CREATE USER firebackup WITH PASSWORD 'secure-password';
GRANT CONNECT ON DATABASE firebackup TO firebackup;
GRANT USAGE ON SCHEMA public TO firebackup;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO firebackup;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO firebackup;
-- Enable row-level security (optional)
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
Connection Security
# Use SSL connections
DATABASE_URL=postgresql://user:pass@host:5432/db?sslmode=verify-full
# Certificate verification
DATABASE_SSL_CA=/path/to/ca-certificate.crt
DATABASE_SSL_CERT=/path/to/client-cert.crt
DATABASE_SSL_KEY=/path/to/client-key.key
Redis Security
# Enable authentication
REDIS_URL=redis://:strong-password@redis:6379
# Use TLS
REDIS_URL=rediss://:password@redis:6379
# Disable dangerous commands (in redis.conf)
# rename-command FLUSHALL ""
# rename-command FLUSHDB ""
# rename-command DEBUG ""
Network Security
Firewall Rules
# Allow HTTPS only
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # Redirect to HTTPS
# Internal services (adjust for your network)
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4000 -j ACCEPT # API
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 5432 -j ACCEPT # PostgreSQL
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 6379 -j ACCEPT # Redis
# Drop all other traffic
iptables -A INPUT -j DROP
Kubernetes Network Policies
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: firebackup-api
namespace: firebackup
spec:
podSelector:
matchLabels:
app.kubernetes.io/component: api
policyTypes:
- Ingress
- Egress
ingress:
# Allow from ingress controller
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 4000
egress:
# Allow to PostgreSQL
- to:
- podSelector:
matchLabels:
app: postgresql
ports:
- protocol: TCP
port: 5432
# Allow to Redis
- to:
- podSelector:
matchLabels:
app: redis
ports:
- protocol: TCP
port: 6379
# Allow to external services (Firebase, storage)
- to:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 443
Rate Limiting
# API rate limiting
RATE_LIMIT_ENABLED=true
RATE_LIMIT_WINDOW=60000
RATE_LIMIT_MAX=100
# Auth rate limiting (stricter)
AUTH_RATE_LIMIT_WINDOW=60000
AUTH_RATE_LIMIT_MAX=5
Nginx rate limiting:
# Define rate limit zones
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/m;
limit_conn_zone $binary_remote_addr zone=conn:10m;
# Apply rate limits
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_conn conn 20;
}
location /api/v1/auth/ {
limit_req zone=auth burst=5 nodelay;
}
Access Control
Role-Based Access Control (RBAC)
| Role | Permissions |
|---|---|
| Owner | Full organization access, billing, can delete |
| Admin | Manage members, projects, settings |
| Member | Create/manage backups, schedules |
| Viewer | Read-only access |
Permission Matrix
| Action | Owner | Admin | Member | Viewer |
|---|---|---|---|---|
| View backups | ✓ | ✓ | ✓ | ✓ |
| Create backups | ✓ | ✓ | ✓ | - |
| Restore backups | ✓ | ✓ | ✓ | - |
| Delete backups | ✓ | ✓ | - | - |
| Manage projects | ✓ | ✓ | - | - |
| Manage members | ✓ | ✓ | - | - |
| Manage billing | ✓ | - | - | - |
| Delete org | ✓ | - | - | - |
API Key Scopes
{
"permissions": [
"backups:read",
"backups:write",
"schedules:read",
"schedules:write",
"projects:read"
]
}
Audit Logging
Audit Events
All security-relevant actions are logged:
| Category | Events |
|---|---|
| Authentication | Login, logout, failed attempts |
| Authorization | Permission checks, access denied |
| Data Access | Backup create, restore, delete |
| Configuration | Settings changes, member changes |
| Admin | Organization changes, billing |
Log Format
{
"timestamp": "2024-01-15T10:30:45.123Z",
"level": "info",
"event": "backup.created",
"actor": {
"id": "user_abc123",
"email": "user@example.com",
"ip": "192.168.1.100"
},
"resource": {
"type": "backup",
"id": "bkp_xyz789"
},
"organization": "org_abc123",
"metadata": {
"projectId": "proj_abc123",
"type": "full"
}
}
Log Retention
# Retain audit logs
AUDIT_LOG_RETENTION_DAYS=365
# Export to external system
AUDIT_LOG_EXPORT=true
AUDIT_LOG_EXPORT_DESTINATION=s3://audit-logs/firebackup/
Secret Management
Kubernetes Secrets
apiVersion: v1
kind: Secret
metadata:
name: firebackup-secrets
namespace: firebackup
type: Opaque
stringData:
jwt-secret: "${JWT_SECRET}"
encryption-key: "${ENCRYPTION_KEY}"
Encrypt secrets at rest:
# EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: ${ENCRYPTION_KEY}
- identity: {}
External Secret Managers
AWS Secrets Manager:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: firebackup-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: firebackup-secrets
data:
- secretKey: jwt-secret
remoteRef:
key: firebackup/production
property: JWT_SECRET
HashiCorp Vault:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: firebackup-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: vault
kind: SecretStore
target:
name: firebackup-secrets
data:
- secretKey: jwt-secret
remoteRef:
key: secret/data/firebackup/production
property: JWT_SECRET
Container Security
Dockerfile Best Practices
# Use distroless base image
FROM gcr.io/distroless/nodejs20-debian12
# Run as non-root user
USER nonroot:nonroot
# Read-only filesystem
WORKDIR /app
# Copy only production files
COPY dist/ ./dist/
COPY node_modules/ ./node_modules/
COPY package.json ./
# No shell access
CMD ["dist/main.js"]
Pod Security Standards
apiVersion: v1
kind: Pod
metadata:
name: firebackup-api
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: api
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
Compliance
SOC 2 Readiness
| Control | Implementation |
|---|---|
| Access Control | RBAC, OAuth, session management |
| Encryption | AES-256-GCM, TLS 1.3 |
| Audit Logging | Comprehensive event logging |
| Availability | Multi-zone deployment, backups |
| Change Management | Version control, CI/CD |
GDPR Compliance
| Requirement | Implementation |
|---|---|
| Data Encryption | All data encrypted at rest and in transit |
| Access Control | Role-based permissions |
| Data Portability | Export functionality |
| Right to Erasure | Delete user data capability |
| Audit Trail | Complete audit logging |
HIPAA Considerations
For healthcare data:
# Enhanced security settings
ENCRYPTION_ALGORITHM=aes-256-gcm
AUDIT_LOG_RETENTION_DAYS=2190 # 6 years
SESSION_TIMEOUT=1800000 # 30 minutes
FORCE_MFA=true
Security Checklist
Pre-Deployment
- Generate strong secrets (JWT, encryption key)
- Configure TLS with valid certificates
- Set up database with SSL
- Configure Redis authentication
- Review firewall rules
- Enable audit logging
- Test authentication flow
Post-Deployment
- Verify HTTPS redirect works
- Test rate limiting
- Review access logs
- Set up monitoring alerts
- Document incident response
- Schedule security reviews
Ongoing
- Rotate secrets quarterly
- Update dependencies monthly
- Review audit logs weekly
- Conduct penetration testing annually
- Security awareness training
Incident Response
Security Incident Procedure
- Detection: Alert triggered or user report
- Triage: Assess severity and scope
- Containment: Isolate affected systems
- Investigation: Analyze logs and evidence
- Remediation: Fix vulnerability
- Recovery: Restore normal operations
- Post-mortem: Document and improve
Contact Information
For security issues:
- Email: security@firebackup.io
- Response Time: 24 hours for critical issues
Related
- Environment Variables - Security configuration
- High Availability - Resilience
- Docker Deployment - Container security
- Kubernetes Deployment - K8s security
Next: High Availability - Multi-node deployment configuration.