📚 Learning Objectives
By the end of this module, you will: - Understand SSL/TLS basics - Generate SSL certificates - Configure NGINX for HTTPS - Set up Let's Encrypt certificates - Configure certificate auto-renewal - Understand SSL best practices
🔒 What is SSL/TLS?
SSL (Secure Sockets Layer) and TLS (Transport Layer Security) are cryptographic protocols that provide secure communication over the internet. They encrypt data between the client and server.
Current Standard: TLS (SSL is deprecated, but the term "SSL" is still commonly used)
Benefits
- Encryption: Data is encrypted in transit
- Authentication: Verifies server identity
- Data Integrity: Ensures data hasn't been tampered with
- SEO: Google favors HTTPS sites
- Trust: Shows security badge in browsers
📜 SSL Certificate Types
1. Self-Signed Certificate
- Free, quick to generate
- Not trusted by browsers (shows warning)
- Good for development/testing
2. Let's Encrypt (Free)
- Free, trusted by browsers
- Valid for 90 days
- Auto-renewal available
3. Commercial Certificates
- Paid certificates
- Extended validation options
- Longer validity periods
🔑 Generating Self-Signed Certificate
Step 1: Create Certificate Directory
sudo mkdir -p /etc/nginx/ssl
Step 2: Generate Private Key
sudo openssl genrsa -out /etc/nginx/ssl/server.key 2048
Step 3: Generate Certificate Signing Request (CSR)
sudo openssl req -new -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.csr
You'll be prompted for: - Country Name - State/Province - City - Organization Name - Common Name (your domain): example.com
Step 4: Generate Self-Signed Certificate
sudo openssl x509 -req -days 365 -in /etc/nginx/ssl/server.csr \
-signkey /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt
Step 5: Set Permissions
sudo chmod 600 /etc/nginx/ssl/server.key
sudo chmod 644 /etc/nginx/ssl/server.crt
One-Line Command
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/server.key \
-out /etc/nginx/ssl/server.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=example.com"
🔧 Basic HTTPS Configuration
Minimal HTTPS Server Block
server {
listen 443 ssl;
server_name example.com;
# SSL Certificate paths
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
HTTP to HTTPS Redirect
# Redirect HTTP to HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
# HTTPS server
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
✅ Let's Encrypt Setup
Let's Encrypt provides free, trusted SSL certificates.
Step 1: Install Certbot
Ubuntu/Debian:
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
CentOS/RHEL:
sudo yum install certbot python3-certbot-nginx -y
macOS:
brew install certbot
Step 2: Basic NGINX Configuration
First, set up a basic HTTP server block:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Step 3: Obtain Certificate
sudo certbot --nginx -d example.com -d www.example.com
Certbot will: - Automatically obtain certificates - Configure NGINX for HTTPS - Set up auto-renewal
Step 4: Verify Auto-Renewal
# Test renewal (dry run)
sudo certbot renew --dry-run
# Check renewal timer
sudo systemctl status certbot.timer
Manual Certificate Renewal
sudo certbot renew
sudo systemctl reload nginx
🔐 SSL/TLS Best Practices
Strong SSL Configuration
server {
listen 443 ssl http2;
server_name example.com;
# Certificate paths
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL Protocols (disable old, insecure versions)
ssl_protocols TLSv1.2 TLSv1.3;
# SSL Ciphers (strong, modern ciphers)
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;
# Session caching
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP to HTTPS redirect
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
🔄 HTTP/2 Support
HTTP/2 improves performance over HTTPS:
server {
listen 443 ssl http2; # Add http2
server_name example.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# ... rest of config
}
🌍 Multiple Domains with SSL
Separate Certificates
# Domain 1
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
root /var/www/example.com;
# ...
}
# Domain 2
server {
listen 443 ssl http2;
server_name another-site.com;
ssl_certificate /etc/nginx/ssl/another-site.com.crt;
ssl_certificate_key /etc/nginx/ssl/another-site.com.key;
root /var/www/another-site.com;
# ...
}
SAN (Subject Alternative Names) Certificate
A single certificate for multiple domains:
server {
listen 443 ssl http2;
server_name example.com www.example.com api.example.com;
ssl_certificate /etc/nginx/ssl/multi-domain.crt;
ssl_certificate_key /etc/nginx/ssl/multi-domain.key;
# ...
}
🔍 SSL Certificate Testing
Test SSL Configuration
# Online tools
# https://www.ssllabs.com/ssltest/
# https://observatory.mozilla.org/
# Command line
openssl s_client -connect example.com:443 -servername example.com
Check Certificate Validity
# View certificate details
openssl x509 -in /etc/nginx/ssl/server.crt -text -noout
# Check expiration date
openssl x509 -in /etc/nginx/ssl/server.crt -noout -dates
Verify NGINX SSL Configuration
# Test configuration
sudo nginx -t
# Check if SSL is working
curl -I https://example.com
📝 Practical Example: Complete HTTPS Setup
# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
# HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# SSL Certificate
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL 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';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Root and index
root /var/www/example.com;
index index.html;
# Logging
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ =404;
}
# Cache static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
🔧 Troubleshooting
Certificate Not Found
# Check certificate file exists
sudo ls -la /etc/nginx/ssl/
# Check file permissions
sudo chmod 644 /etc/nginx/ssl/server.crt
sudo chmod 600 /etc/nginx/ssl/server.key
SSL Handshake Failed
- Verify certificate is valid
- Check certificate and key match
- Ensure firewall allows port 443
- Verify SSL protocols are supported
Browser Shows "Not Secure"
- Certificate may be self-signed
- Certificate may be expired
- Certificate may not match domain
- Mixed content (HTTP resources on HTTPS page)
📝 Exercises
- Generate a self-signed certificate for testing
- Configure NGINX to serve HTTPS with your certificate
- Set up Let's Encrypt certificate using Certbot
- Configure HTTP to HTTPS redirect
- Implement SSL best practices (TLS 1.2+, strong ciphers)
- Enable HTTP/2
- Set up auto-renewal for Let's Encrypt certificates
- Test your SSL configuration using SSL Labs
✅ Checklist
- [ ] Understand SSL/TLS basics
- [ ] Can generate self-signed certificates
- [ ] Can set up Let's Encrypt certificates
- [ ] Can configure HTTPS in NGINX
- [ ] Understand SSL best practices
- [ ] Can set up HTTP to HTTPS redirect
- [ ] Can enable HTTP/2
- [ ] Understand certificate renewal
➡️ Next Steps
Proceed to Module 2: Reverse Proxy to learn how to use NGINX as a reverse proxy.