refactor: Migrate from monolithic to modular architecture
1. **Docker-Compose für Entwicklung optimieren** 2. **Umgebungsvariablen für lokale Entwicklung** 3. **Service-Abhängigkeiten** 4. **Docker-Compose für Produktion** 5. **Dokumentation**
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
// Kafka JAAS Configuration for Production
|
||||
// =============================================================================
|
||||
// This file configures SASL authentication for Kafka in production
|
||||
// Change the passwords to strong, randomly generated values
|
||||
// =============================================================================
|
||||
|
||||
KafkaServer {
|
||||
org.apache.kafka.common.security.plain.PlainLoginModule required
|
||||
username="admin"
|
||||
password="CHANGE_ME_STRONG_KAFKA_ADMIN_PASSWORD"
|
||||
user_admin="CHANGE_ME_STRONG_KAFKA_ADMIN_PASSWORD"
|
||||
user_producer="CHANGE_ME_STRONG_KAFKA_PRODUCER_PASSWORD"
|
||||
user_consumer="CHANGE_ME_STRONG_KAFKA_CONSUMER_PASSWORD";
|
||||
};
|
||||
|
||||
Client {
|
||||
org.apache.kafka.common.security.plain.PlainLoginModule required
|
||||
username="admin"
|
||||
password="CHANGE_ME_STRONG_KAFKA_ADMIN_PASSWORD";
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
// Zookeeper JAAS Configuration for Production
|
||||
// =============================================================================
|
||||
// This file configures SASL authentication for Zookeeper in production
|
||||
// Change the passwords to strong, randomly generated values
|
||||
// =============================================================================
|
||||
|
||||
Server {
|
||||
org.apache.zookeeper.server.auth.DigestLoginModule required
|
||||
user_admin="CHANGE_ME_STRONG_ZOOKEEPER_ADMIN_PASSWORD"
|
||||
user_kafka="CHANGE_ME_STRONG_ZOOKEEPER_KAFKA_PASSWORD";
|
||||
};
|
||||
|
||||
Client {
|
||||
org.apache.zookeeper.server.auth.DigestLoginModule required
|
||||
username="kafka"
|
||||
password="CHANGE_ME_STRONG_ZOOKEEPER_KAFKA_PASSWORD";
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
# Prometheus Production Configuration
|
||||
# =============================================================================
|
||||
# This configuration provides production-ready monitoring setup with
|
||||
# security, performance optimizations, and comprehensive service discovery
|
||||
# =============================================================================
|
||||
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
external_labels:
|
||||
monitor: 'meldestelle-prod'
|
||||
environment: 'production'
|
||||
|
||||
# Alertmanager configuration
|
||||
alerting:
|
||||
alertmanagers:
|
||||
- static_configs:
|
||||
- targets:
|
||||
- alertmanager:9093
|
||||
|
||||
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
|
||||
rule_files:
|
||||
- "alert_rules.yml"
|
||||
- "recording_rules.yml"
|
||||
|
||||
# Scrape configuration
|
||||
scrape_configs:
|
||||
# Prometheus itself
|
||||
- job_name: 'prometheus'
|
||||
static_configs:
|
||||
- targets: ['localhost:9090']
|
||||
scrape_interval: 5s
|
||||
metrics_path: /metrics
|
||||
|
||||
# Application metrics
|
||||
- job_name: 'meldestelle-api'
|
||||
static_configs:
|
||||
- targets: ['host.docker.internal:8081']
|
||||
scrape_interval: 10s
|
||||
metrics_path: /actuator/prometheus
|
||||
basic_auth:
|
||||
username: 'admin'
|
||||
password: 'CHANGE_ME_METRICS_PASSWORD'
|
||||
|
||||
# PostgreSQL metrics (using postgres_exporter)
|
||||
- job_name: 'postgres'
|
||||
static_configs:
|
||||
- targets: ['postgres-exporter:9187']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Redis metrics (using redis_exporter)
|
||||
- job_name: 'redis'
|
||||
static_configs:
|
||||
- targets: ['redis-exporter:9121']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Kafka metrics (using kafka_exporter)
|
||||
- job_name: 'kafka'
|
||||
static_configs:
|
||||
- targets: ['kafka-exporter:9308']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Zookeeper metrics (using zookeeper_exporter)
|
||||
- job_name: 'zookeeper'
|
||||
static_configs:
|
||||
- targets: ['zookeeper-exporter:9141']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Keycloak metrics
|
||||
- job_name: 'keycloak'
|
||||
static_configs:
|
||||
- targets: ['keycloak:8443']
|
||||
scrape_interval: 30s
|
||||
metrics_path: /auth/realms/master/metrics
|
||||
scheme: https
|
||||
tls_config:
|
||||
insecure_skip_verify: true
|
||||
|
||||
# Nginx metrics (using nginx-prometheus-exporter)
|
||||
- job_name: 'nginx'
|
||||
static_configs:
|
||||
- targets: ['nginx-exporter:9113']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Node exporter for system metrics
|
||||
- job_name: 'node'
|
||||
static_configs:
|
||||
- targets: ['node-exporter:9100']
|
||||
scrape_interval: 30s
|
||||
|
||||
# cAdvisor for container metrics
|
||||
- job_name: 'cadvisor'
|
||||
static_configs:
|
||||
- targets: ['cadvisor:8080']
|
||||
scrape_interval: 30s
|
||||
|
||||
# Grafana metrics
|
||||
- job_name: 'grafana'
|
||||
static_configs:
|
||||
- targets: ['grafana:3000']
|
||||
scrape_interval: 30s
|
||||
metrics_path: /metrics
|
||||
|
||||
# Zipkin metrics
|
||||
- job_name: 'zipkin'
|
||||
static_configs:
|
||||
- targets: ['zipkin:9411']
|
||||
scrape_interval: 30s
|
||||
metrics_path: /actuator/prometheus
|
||||
|
||||
# Remote write configuration (for long-term storage)
|
||||
# remote_write:
|
||||
# - url: "https://your-remote-storage/api/v1/write"
|
||||
# basic_auth:
|
||||
# username: "your-username"
|
||||
# password: "your-password"
|
||||
|
||||
# Storage configuration
|
||||
storage:
|
||||
tsdb:
|
||||
retention.time: 30d
|
||||
retention.size: 10GB
|
||||
wal-compression: true
|
||||
@@ -0,0 +1,133 @@
|
||||
# Nginx Production Configuration
|
||||
# =============================================================================
|
||||
# This configuration provides secure reverse proxy with SSL termination,
|
||||
# security headers, and performance optimizations for production
|
||||
# =============================================================================
|
||||
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
# Performance and Security Settings
|
||||
worker_rlimit_nofile 65535;
|
||||
|
||||
events {
|
||||
worker_connections 4096;
|
||||
use epoll;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
# Basic Settings
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# Performance Settings
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
server_tokens off;
|
||||
|
||||
# Buffer Settings
|
||||
client_body_buffer_size 128k;
|
||||
client_max_body_size 10m;
|
||||
client_header_buffer_size 1k;
|
||||
large_client_header_buffers 4 4k;
|
||||
output_buffers 1 32k;
|
||||
postpone_output 1460;
|
||||
|
||||
# Timeout Settings
|
||||
client_body_timeout 12;
|
||||
client_header_timeout 12;
|
||||
send_timeout 10;
|
||||
|
||||
# Gzip Compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 10240;
|
||||
gzip_proxied expired no-cache no-store private must-revalidate auth;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/x-javascript
|
||||
application/xml+rss
|
||||
application/javascript
|
||||
application/json
|
||||
application/xml
|
||||
application/rss+xml
|
||||
application/atom+xml
|
||||
image/svg+xml;
|
||||
|
||||
# Security Headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# Rate Limiting
|
||||
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
|
||||
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/m;
|
||||
limit_req_zone $binary_remote_addr zone=general:10m rate=1000r/m;
|
||||
|
||||
# Logging Format
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for" '
|
||||
'$request_time $upstream_response_time';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
# SSL Configuration
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_session_tickets off;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
# Upstream Definitions
|
||||
upstream keycloak {
|
||||
server keycloak:8443;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream grafana {
|
||||
server grafana:3000;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream prometheus {
|
||||
server prometheus:9090;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
# HTTP to HTTPS Redirect
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# Health Check Endpoint
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
|
||||
# Include additional server configurations
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
# Redis Production Configuration
|
||||
# =============================================================================
|
||||
# This configuration file contains production-ready settings for Redis
|
||||
# with security, performance, and reliability optimizations.
|
||||
# =============================================================================
|
||||
|
||||
# Network and Security
|
||||
bind 0.0.0.0
|
||||
protected-mode yes
|
||||
port 6379
|
||||
|
||||
# Authentication (password will be set via command line)
|
||||
# requirepass will be set via --requirepass flag in docker-compose
|
||||
|
||||
# General Settings
|
||||
timeout 300
|
||||
tcp-keepalive 300
|
||||
tcp-backlog 511
|
||||
|
||||
# Memory Management
|
||||
maxmemory 256mb
|
||||
maxmemory-policy allkeys-lru
|
||||
maxmemory-samples 5
|
||||
|
||||
# Persistence Settings
|
||||
save 900 1
|
||||
save 300 10
|
||||
save 60 10000
|
||||
stop-writes-on-bgsave-error yes
|
||||
rdbcompression yes
|
||||
rdbchecksum yes
|
||||
dbfilename dump.rdb
|
||||
dir /data
|
||||
|
||||
# Append Only File (AOF)
|
||||
appendonly yes
|
||||
appendfilename "appendonly.aof"
|
||||
appendfsync everysec
|
||||
no-appendfsync-on-rewrite no
|
||||
auto-aof-rewrite-percentage 100
|
||||
auto-aof-rewrite-min-size 64mb
|
||||
aof-load-truncated yes
|
||||
aof-use-rdb-preamble yes
|
||||
|
||||
# Logging
|
||||
loglevel notice
|
||||
logfile ""
|
||||
syslog-enabled no
|
||||
|
||||
# Database Settings
|
||||
databases 16
|
||||
|
||||
# Slow Log
|
||||
slowlog-log-slower-than 10000
|
||||
slowlog-max-len 128
|
||||
|
||||
# Latency Monitoring
|
||||
latency-monitor-threshold 100
|
||||
|
||||
# Client Settings
|
||||
maxclients 10000
|
||||
|
||||
# Security Settings
|
||||
rename-command FLUSHDB ""
|
||||
rename-command FLUSHALL ""
|
||||
rename-command KEYS ""
|
||||
rename-command CONFIG "CONFIG_b835c3f8a5d2e7f1"
|
||||
rename-command SHUTDOWN "SHUTDOWN_a9b4c2d1e3f5g6h7"
|
||||
rename-command DEBUG ""
|
||||
rename-command EVAL ""
|
||||
|
||||
# Disable dangerous commands in production
|
||||
rename-command DEL "DEL_prod_safe"
|
||||
|
||||
# TLS Configuration (uncomment and configure for TLS)
|
||||
# port 0
|
||||
# tls-port 6380
|
||||
# tls-cert-file /tls/redis.crt
|
||||
# tls-key-file /tls/redis.key
|
||||
# tls-ca-cert-file /tls/ca.crt
|
||||
# tls-dh-params-file /tls/redis.dh
|
||||
# tls-protocols "TLSv1.2 TLSv1.3"
|
||||
# tls-ciphers "ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS"
|
||||
# tls-ciphersuites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
|
||||
# tls-prefer-server-ciphers yes
|
||||
# tls-session-caching no
|
||||
# tls-session-cache-size 5000
|
||||
# tls-session-cache-timeout 60
|
||||
|
||||
# Performance Tuning
|
||||
hash-max-ziplist-entries 512
|
||||
hash-max-ziplist-value 64
|
||||
list-max-ziplist-size -2
|
||||
list-compress-depth 0
|
||||
set-max-intset-entries 512
|
||||
zset-max-ziplist-entries 128
|
||||
zset-max-ziplist-value 64
|
||||
hll-sparse-max-bytes 3000
|
||||
stream-node-max-bytes 4096
|
||||
stream-node-max-entries 100
|
||||
|
||||
# Active Rehashing
|
||||
activerehashing yes
|
||||
|
||||
# Client Output Buffer Limits
|
||||
client-output-buffer-limit normal 0 0 0
|
||||
client-output-buffer-limit replica 256mb 64mb 60
|
||||
client-output-buffer-limit pubsub 32mb 8mb 60
|
||||
|
||||
# Client Query Buffer
|
||||
client-query-buffer-limit 1gb
|
||||
|
||||
# Protocol Buffer
|
||||
proto-max-bulk-len 512mb
|
||||
|
||||
# Replication (for Redis cluster/replica setup)
|
||||
# replica-serve-stale-data yes
|
||||
# replica-read-only yes
|
||||
# repl-diskless-sync no
|
||||
# repl-diskless-sync-delay 5
|
||||
# repl-ping-replica-period 10
|
||||
# repl-timeout 60
|
||||
# repl-disable-tcp-nodelay no
|
||||
# repl-backlog-size 1mb
|
||||
# repl-backlog-ttl 3600
|
||||
|
||||
# Security: Disable potentially dangerous features
|
||||
enable-protected-configs no
|
||||
enable-debug-command no
|
||||
enable-module-command no
|
||||
|
||||
# Notifications (disable for performance)
|
||||
notify-keyspace-events ""
|
||||
|
||||
# Advanced Configuration
|
||||
hz 10
|
||||
dynamic-hz yes
|
||||
aof-rewrite-incremental-fsync yes
|
||||
rdb-save-incremental-fsync yes
|
||||
|
||||
# Jemalloc Configuration
|
||||
jemalloc-bg-thread yes
|
||||
|
||||
# Threading (Redis 6.0+)
|
||||
# io-threads 4
|
||||
# io-threads-do-reads yes
|
||||
@@ -0,0 +1,220 @@
|
||||
# SSL/TLS Certificate Setup for Production
|
||||
|
||||
This directory contains SSL/TLS certificates and keys for securing the Meldestelle application in production.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
config/ssl/
|
||||
├── postgres/ # PostgreSQL SSL certificates
|
||||
├── redis/ # Redis TLS certificates
|
||||
├── keycloak/ # Keycloak HTTPS certificates
|
||||
├── prometheus/ # Prometheus HTTPS certificates
|
||||
├── grafana/ # Grafana HTTPS certificates
|
||||
├── nginx/ # Nginx SSL certificates
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Certificate Requirements
|
||||
|
||||
### 1. PostgreSQL SSL Certificates
|
||||
Place the following files in `config/ssl/postgres/`:
|
||||
- `server.crt` - Server certificate
|
||||
- `server.key` - Server private key
|
||||
- `ca.crt` - Certificate Authority certificate
|
||||
|
||||
### 2. Redis TLS Certificates
|
||||
Place the following files in `config/ssl/redis/`:
|
||||
- `redis.crt` - Redis server certificate
|
||||
- `redis.key` - Redis server private key
|
||||
- `ca.crt` - Certificate Authority certificate
|
||||
- `redis.dh` - Diffie-Hellman parameters
|
||||
|
||||
### 3. Keycloak HTTPS Certificates
|
||||
Place the following files in `config/ssl/keycloak/`:
|
||||
- `server.crt.pem` - Server certificate in PEM format
|
||||
- `server.key.pem` - Server private key in PEM format
|
||||
|
||||
### 4. Prometheus HTTPS Certificates
|
||||
Place the following files in `config/ssl/prometheus/`:
|
||||
- `prometheus.crt` - Prometheus server certificate
|
||||
- `prometheus.key` - Prometheus server private key
|
||||
- `web.yml` - Prometheus web configuration file
|
||||
|
||||
### 5. Grafana HTTPS Certificates
|
||||
Place the following files in `config/ssl/grafana/`:
|
||||
- `server.crt` - Grafana server certificate
|
||||
- `server.key` - Grafana server private key
|
||||
|
||||
### 6. Nginx SSL Certificates
|
||||
Place the following files in `config/ssl/nginx/`:
|
||||
- `server.crt` - Main SSL certificate
|
||||
- `server.key` - Main SSL private key
|
||||
- `dhparam.pem` - Diffie-Hellman parameters
|
||||
|
||||
## Generating Self-Signed Certificates (Development/Testing)
|
||||
|
||||
⚠️ **Warning**: Only use self-signed certificates for development and testing. Use proper CA-signed certificates in production.
|
||||
|
||||
### Generate CA Certificate
|
||||
```bash
|
||||
# Create CA private key
|
||||
openssl genrsa -out ca.key 4096
|
||||
|
||||
# Create CA certificate
|
||||
openssl req -new -x509 -days 365 -key ca.key -out ca.crt \
|
||||
-subj "/C=AT/ST=Vienna/L=Vienna/O=Meldestelle/OU=IT/CN=Meldestelle-CA"
|
||||
```
|
||||
|
||||
### Generate Server Certificates
|
||||
```bash
|
||||
# For each service, generate private key and certificate signing request
|
||||
openssl genrsa -out server.key 2048
|
||||
openssl req -new -key server.key -out server.csr \
|
||||
-subj "/C=AT/ST=Vienna/L=Vienna/O=Meldestelle/OU=IT/CN=your-domain.com"
|
||||
|
||||
# Sign the certificate with CA
|
||||
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key \
|
||||
-CAcreateserial -out server.crt
|
||||
|
||||
# Clean up
|
||||
rm server.csr
|
||||
```
|
||||
|
||||
### Generate Diffie-Hellman Parameters
|
||||
```bash
|
||||
openssl dhparam -out dhparam.pem 2048
|
||||
```
|
||||
|
||||
## Production Certificate Setup
|
||||
|
||||
### Option 1: Let's Encrypt (Recommended)
|
||||
Use Certbot to obtain free SSL certificates:
|
||||
|
||||
```bash
|
||||
# Install certbot
|
||||
sudo apt-get install certbot
|
||||
|
||||
# Obtain certificates
|
||||
sudo certbot certonly --standalone -d your-domain.com -d www.your-domain.com
|
||||
|
||||
# Copy certificates to appropriate directories
|
||||
sudo cp /etc/letsencrypt/live/your-domain.com/fullchain.pem config/ssl/nginx/server.crt
|
||||
sudo cp /etc/letsencrypt/live/your-domain.com/privkey.pem config/ssl/nginx/server.key
|
||||
```
|
||||
|
||||
### Option 2: Commercial CA
|
||||
1. Generate Certificate Signing Requests (CSRs)
|
||||
2. Submit CSRs to your Certificate Authority
|
||||
3. Download signed certificates
|
||||
4. Place certificates in appropriate directories
|
||||
|
||||
### Option 3: Internal CA
|
||||
If using an internal Certificate Authority:
|
||||
1. Generate CSRs for each service
|
||||
2. Sign certificates with your internal CA
|
||||
3. Distribute CA certificate to all clients
|
||||
|
||||
## File Permissions
|
||||
|
||||
Ensure proper file permissions for security:
|
||||
|
||||
```bash
|
||||
# Set restrictive permissions on private keys
|
||||
chmod 600 config/ssl/*/server.key
|
||||
chmod 600 config/ssl/*/redis.key
|
||||
chmod 600 config/ssl/*/prometheus.key
|
||||
|
||||
# Set readable permissions on certificates
|
||||
chmod 644 config/ssl/*/server.crt
|
||||
chmod 644 config/ssl/*/ca.crt
|
||||
|
||||
# Set directory permissions
|
||||
chmod 755 config/ssl/*/
|
||||
```
|
||||
|
||||
## Docker Volume Mounts
|
||||
|
||||
The certificates are mounted as read-only volumes in the Docker containers:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./config/ssl/nginx:/etc/ssl/nginx:ro
|
||||
- ./config/ssl/keycloak:/opt/keycloak/conf:ro
|
||||
# ... other mounts
|
||||
```
|
||||
|
||||
## Certificate Renewal
|
||||
|
||||
### Automated Renewal (Let's Encrypt)
|
||||
Set up a cron job for automatic renewal:
|
||||
|
||||
```bash
|
||||
# Add to crontab
|
||||
0 12 * * * /usr/bin/certbot renew --quiet --post-hook "docker-compose -f docker-compose.prod.yml restart nginx"
|
||||
```
|
||||
|
||||
### Manual Renewal
|
||||
1. Generate new certificates
|
||||
2. Replace old certificates in SSL directories
|
||||
3. Restart affected services:
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml restart nginx keycloak grafana prometheus
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Use Strong Encryption**: Use at least 2048-bit RSA keys or 256-bit ECDSA keys
|
||||
2. **Regular Rotation**: Rotate certificates regularly (annually or bi-annually)
|
||||
3. **Secure Storage**: Store private keys securely and limit access
|
||||
4. **Monitor Expiration**: Set up monitoring for certificate expiration
|
||||
5. **Use HSTS**: Enable HTTP Strict Transport Security
|
||||
6. **Perfect Forward Secrecy**: Use ECDHE cipher suites
|
||||
7. **Certificate Transparency**: Monitor CT logs for unauthorized certificates
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Permission Denied**
|
||||
```bash
|
||||
# Fix file permissions
|
||||
sudo chown -R $USER:$USER config/ssl/
|
||||
chmod -R 755 config/ssl/
|
||||
chmod 600 config/ssl/*/server.key
|
||||
```
|
||||
|
||||
2. **Certificate Verification Failed**
|
||||
```bash
|
||||
# Verify certificate
|
||||
openssl x509 -in config/ssl/nginx/server.crt -text -noout
|
||||
|
||||
# Check certificate chain
|
||||
openssl verify -CAfile config/ssl/nginx/ca.crt config/ssl/nginx/server.crt
|
||||
```
|
||||
|
||||
3. **TLS Handshake Errors**
|
||||
- Check certificate validity dates
|
||||
- Verify certificate matches hostname
|
||||
- Ensure proper cipher suite configuration
|
||||
|
||||
### Testing SSL Configuration
|
||||
|
||||
```bash
|
||||
# Test SSL certificate
|
||||
openssl s_client -connect your-domain.com:443 -servername your-domain.com
|
||||
|
||||
# Test with specific protocol
|
||||
openssl s_client -connect your-domain.com:443 -tls1_2
|
||||
|
||||
# Check certificate expiration
|
||||
openssl x509 -in config/ssl/nginx/server.crt -noout -dates
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
For certificate-related issues:
|
||||
1. Check service logs: `docker-compose -f docker-compose.prod.yml logs [service-name]`
|
||||
2. Verify certificate files exist and have correct permissions
|
||||
3. Test SSL configuration with OpenSSL tools
|
||||
4. Consult service-specific SSL documentation
|
||||
Reference in New Issue
Block a user