This guide covers enabling TLS/HTTPS for SovereignCore in both development and production environments.
For local development with self-signed certificates:
# Generate self-signed certificates
chmod +x scripts/generate_certs.sh
./scripts/generate_certs.sh
# Update .env
TLS_ENABLED=true
TLS_CERT_PATH=./certs/cert.pem
TLS_KEY_PATH=./certs/key.pem
# Restart services
docker compose restartLet's Encrypt provides free, automated SSL/TLS certificates.
- Domain name pointing to your server
- Port 80 and 443 accessible
- Certbot installed
# Install Certbot (Ubuntu/Debian)
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
# Install Certbot (macOS)
brew install certbot
# Install Certbot (CentOS/RHEL)
sudo yum install certbot python3-certbot-nginx# Standalone mode (if no web server running)
sudo certbot certonly --standalone -d api.yourdomain.com
# Nginx mode (if Nginx is running)
sudo certbot --nginx -d api.yourdomain.com
# Manual DNS challenge (for wildcard certs)
sudo certbot certonly --manual --preferred-challenges dns -d "*.yourdomain.com"# Update .env
TLS_ENABLED=true
TLS_CERT_PATH=/etc/letsencrypt/live/api.yourdomain.com/fullchain.pem
TLS_KEY_PATH=/etc/letsencrypt/live/api.yourdomain.com/privkey.pem# Test renewal
sudo certbot renew --dry-run
# Set up auto-renewal (cron)
sudo crontab -e
# Add this line (runs twice daily)
0 0,12 * * * certbot renew --quiet --post-hook "docker compose -f /path/to/sovereigncore/docker-compose.yml restart"If you have a commercial SSL certificate:
You should have:
certificate.crt- Your SSL certificateprivate.key- Your private keyca_bundle.crt- Certificate Authority bundle (optional)
# Create fullchain certificate
cat certificate.crt ca_bundle.crt > fullchain.pem
# Copy private key
cp private.key privkey.pem# Create certs directory
sudo mkdir -p /etc/ssl/sovereigncore
# Copy certificates
sudo cp fullchain.pem /etc/ssl/sovereigncore/
sudo cp privkey.pem /etc/ssl/sovereigncore/
# Set permissions
sudo chmod 644 /etc/ssl/sovereigncore/fullchain.pem
sudo chmod 600 /etc/ssl/sovereigncore/privkey.pem
sudo chown root:root /etc/ssl/sovereigncore/*# Update .env
TLS_ENABLED=true
TLS_CERT_PATH=/etc/ssl/sovereigncore/fullchain.pem
TLS_KEY_PATH=/etc/ssl/sovereigncore/privkey.pem./scripts/generate_certs.shThis creates:
certs/cert.pem- Self-signed certificatecerts/key.pem- Private key- Valid for 365 days
# Create certs directory
mkdir -p certs
# Generate private key and certificate
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout certs/key.pem \
-out certs/cert.pem \
-days 365 \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
# Set permissions
chmod 644 certs/cert.pem
chmod 600 certs/key.pemAdd volume mounts for certificates:
services:
api:
volumes:
- ./certs:/app/certs:ro
# OR for Let's Encrypt
- /etc/letsencrypt:/etc/letsencrypt:ro
environment:
- TLS_ENABLED=true
- TLS_CERT_PATH=/app/certs/cert.pem
- TLS_KEY_PATH=/app/certs/key.pem
ports:
- "443:8528" # HTTPS
- "80:8528" # HTTP (optional, for redirect)For production, use Nginx as a reverse proxy:
# /etc/nginx/sites-available/sovereigncore
server {
listen 80;
server_name api.yourdomain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
# SSL Security Settings
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';
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Proxy to SovereignCore
location / {
proxy_pass http://localhost:8528;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Enable the site:
sudo ln -s /etc/nginx/sites-available/sovereigncore /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxTo enable TLS for Redis connections:
# Generate CA
openssl genrsa -out redis-ca-key.pem 4096
openssl req -x509 -new -nodes -key redis-ca-key.pem \
-days 3650 -out redis-ca-cert.pem \
-subj "/CN=Redis-CA"
# Generate Redis server certificate
openssl genrsa -out redis-server-key.pem 4096
openssl req -new -key redis-server-key.pem \
-out redis-server.csr \
-subj "/CN=redis-server"
openssl x509 -req -in redis-server.csr \
-CA redis-ca-cert.pem -CAkey redis-ca-key.pem \
-CAcreateserial -out redis-server-cert.pem -days 3650
# Generate client certificate
openssl genrsa -out redis-client-key.pem 4096
openssl req -new -key redis-client-key.pem \
-out redis-client.csr \
-subj "/CN=redis-client"
openssl x509 -req -in redis-client.csr \
-CA redis-ca-cert.pem -CAkey redis-ca-key.pem \
-CAcreateserial -out redis-client-cert.pem -days 3650# Enable TLS
port 0
tls-port 6379
# Certificate paths
tls-cert-file /path/to/redis-server-cert.pem
tls-key-file /path/to/redis-server-key.pem
tls-ca-cert-file /path/to/redis-ca-cert.pem
# Client authentication
tls-auth-clients yes
# TLS protocols
tls-protocols "TLSv1.2 TLSv1.3"
REDIS_URL=rediss://localhost:6379/0 # Note: rediss:// for TLS
REDIS_TLS_CERT=/path/to/redis-client-cert.pem
REDIS_TLS_KEY=/path/to/redis-client-key.pem
REDIS_TLS_CA=/path/to/redis-ca-cert.pem# Test with curl
curl -v https://localhost:8528/health
# Test with specific certificate (self-signed)
curl -v --cacert certs/cert.pem https://localhost:8528/health
# Test SSL/TLS configuration
openssl s_client -connect localhost:8528 -tls1_3# View certificate information
openssl x509 -in certs/cert.pem -text -noout
# Check certificate expiration
openssl x509 -in certs/cert.pem -noout -dates
# Verify certificate chain
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt certs/cert.pemFor production deployments, test your SSL configuration:
https://www.ssllabs.com/ssltest/analyze.html?d=api.yourdomain.com
Aim for an A+ rating.
# Only allow TLS 1.2 and 1.3
ssl_protocols TLSv1.2 TLSv1.3;# Modern cipher suite
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';# Force HTTPS for 1 year
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;ssl_compression off;ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/api.yourdomain.com/chain.pem;# Restrict permissions
chmod 600 /path/to/privkey.pem
chown root:root /path/to/privkey.pem# Set up monitoring for certificate expiration
# Renew certificates 30 days before expirationFor Development:
# Use -k flag to ignore certificate validation
curl -k https://localhost:8528/health
# Or add certificate to trusted store
sudo cp certs/cert.pem /usr/local/share/ca-certificates/sovereigncore.crt
sudo update-ca-certificatesSolution: Renew the certificate
# Let's Encrypt
sudo certbot renew
# Self-signed (regenerate)
./scripts/generate_certs.shSolution: Ensure certificate CN matches your domain
# Check certificate CN
openssl x509 -in cert.pem -noout -subject
# Regenerate with correct CN
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout key.pem -out cert.pem -days 365 \
-subj "/CN=api.yourdomain.com"Solution: Fix file permissions
# Make certificate readable
chmod 644 cert.pem
# Make key readable only by owner
chmod 600 key.pem
# Ensure correct ownership
sudo chown $USER:$USER cert.pem key.pemSolution: Ensure all resources use HTTPS
# Update CORS origins to use https://
CORS_ORIGINS=["https://app.yourdomain.com"]
# Update all API calls in frontend to use https://#!/bin/bash
# check_cert_expiry.sh
CERT_FILE="/etc/letsencrypt/live/api.yourdomain.com/cert.pem"
DAYS_WARNING=30
EXPIRY_DATE=$(openssl x509 -in "$CERT_FILE" -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt $DAYS_WARNING ]; then
echo "WARNING: Certificate expires in $DAYS_LEFT days!"
# Send alert (email, Slack, etc.)
fiAdd to cron:
# Run daily at 9 AM
0 9 * * * /path/to/check_cert_expiry.sh- Let's Encrypt Documentation
- Mozilla SSL Configuration Generator
- SSL Labs Best Practices
- OWASP TLS Cheat Sheet
After enabling TLS:
- Update DNS: Point your domain to the server
- Configure Firewall: Open ports 80 and 443
- Test Thoroughly: Verify all endpoints work over HTTPS
- Monitor Certificates: Set up expiration alerts
- Update Documentation: Document your TLS setup for your team