HTTPS is no longer optional—browsers flag HTTP sites as insecure, search engines prefer HTTPS, and users expect encrypted connections. SSL/TLS certificates make HTTPS possible, and with Let's Encrypt providing free certificates, there's no reason to skip this essential security layer. This guide covers certificate setup, configuration best practices, and troubleshooting common issues.

đź“‹ Key Takeaways
  • Let's Encrypt provides free, automated SSL certificates
  • Certbot handles certificate issuance and renewal automatically
  • Modern TLS configuration improves security and performance
  • Mixed content errors are the most common post-migration issue

I. Understanding SSL/TLS Basics

Know what you're implementing before diving into setup.

A. What Certificates Do

  • Encryption: Protects data in transit between browser and server.
  • Authentication: Proves your server is who it claims to be.
  • Integrity: Detects if data was modified in transit.

B. Certificate Types

  • Domain Validation (DV): Verifies domain ownership. Fast, cheap/free. Sufficient for most sites.
  • Organization Validation (OV): Verifies organization identity. Shows company name on inspection.
  • Extended Validation (EV): Rigorous verification. Once showed green bar (no longer in modern browsers).

C. Why Let's Encrypt

  • Free: No cost for certificates.
  • Automated: Renewal can be fully automatic.
  • Trusted: Supported by all major browsers.
  • Fast: Certificates issued in seconds.

II. Installing Certbot

Certbot is the recommended tool for obtaining Let's Encrypt certificates.

A. Ubuntu/Debian Installation

# Update packages
sudo apt update

# Install Certbot
sudo apt install certbot

# For Apache
sudo apt install python3-certbot-apache

# For Nginx
sudo apt install python3-certbot-nginx

B. CentOS/RHEL Installation

# Enable EPEL repository
sudo yum install epel-release

# Install Certbot
sudo yum install certbot

# For Nginx
sudo yum install python3-certbot-nginx

III. Obtaining Certificates

Get your first certificate with a single command.

A. Nginx with Automatic Configuration

# Obtain certificate and auto-configure Nginx
sudo certbot --nginx -d example.com -d www.example.com

# Follow prompts:
# - Enter email for renewal notices
# - Agree to terms of service
# - Choose whether to redirect HTTP to HTTPS

B. Apache with Automatic Configuration

# Obtain certificate and auto-configure Apache
sudo certbot --apache -d example.com -d www.example.com

C. Manual Certificate Only

# Get certificate without modifying server config
sudo certbot certonly --webroot -w /var/www/html \
    -d example.com -d www.example.com

# Certificates saved to:
# /etc/letsencrypt/live/example.com/fullchain.pem
# /etc/letsencrypt/live/example.com/privkey.pem
Ad Space - Mid Content

IV. Nginx SSL Configuration

Optimal configuration for security and performance.

A. Modern Nginx SSL Config

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;

    # Certificates
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # 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;
    ssl_prefer_server_ciphers off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # Session settings
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Security headers
    add_header Strict-Transport-Security "max-age=63072000" always;

    root /var/www/html;
    index index.php index.html;

    # ... rest of your config
}

B. HTTP to HTTPS Redirect

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    
    # Redirect all HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

V. Automatic Renewal

Let's Encrypt certificates expire in 90 days. Automate renewal to avoid downtime.

A. Testing Renewal

# Test the renewal process without actually renewing
sudo certbot renew --dry-run

# If successful, you'll see "Congratulations" message

B. Cron Job for Renewal

# Edit crontab
sudo crontab -e

# Add renewal check (runs twice daily)
0 0,12 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

C. Systemd Timer (Modern Method)

# Check if certbot timer is active
sudo systemctl status certbot.timer

# Enable if not active
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

VI. WordPress HTTPS Migration

Update WordPress after installing your certificate.

A. Update WordPress URLs

# In wp-config.php, add:
define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');

# Or update in database:
UPDATE wp_options SET option_value = 'https://example.com' 
    WHERE option_name = 'siteurl';
UPDATE wp_options SET option_value = 'https://example.com' 
    WHERE option_name = 'home';

B. Search and Replace URLs

# Use WP-CLI to update all URLs in content
wp search-replace 'http://example.com' 'https://example.com' \
    --all-tables --precise

# Or use Better Search Replace plugin for GUI option

C. Force HTTPS in WordPress

# Add to wp-config.php
define('FORCE_SSL_ADMIN', true);

// If behind a proxy/load balancer
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 
    $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

VII. Troubleshooting Common Issues

A. Mixed Content Errors

  • Symptom: Padlock shows warning, browser console shows "Mixed Content" errors.
  • Cause: Page loads resources (images, scripts) via HTTP.
  • Fix: Update all resource URLs to HTTPS or use protocol-relative URLs.
// Find mixed content in browser console
// Or scan with online tools like Why No Padlock

// Fix in WordPress - add to functions.php
function fix_mixed_content($content) {
    $content = str_replace('http://example.com', 
                          'https://example.com', $content);
    return $content;
}
add_filter('the_content', 'fix_mixed_content');

B. Certificate Not Trusted

  • Symptom: Browser shows "Not Secure" despite HTTPS.
  • Cause: Missing intermediate certificate, expired cert, or self-signed.
  • Fix: Use fullchain.pem (includes intermediates), check expiration.
# Check certificate chain
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

# Check with SSL Labs
# Visit: https://www.ssllabs.com/ssltest/

C. Redirect Loops

  • Symptom: "Too many redirects" error.
  • Cause: Multiple redirect rules conflicting, or proxy issues.
  • Fix: Check for duplicate redirects in server config and .htaccess.

D. Port 443 Already in Use

# Find what's using port 443
sudo lsof -i :443

# Or
sudo netstat -tlpn | grep 443

# Stop conflicting service if needed

VIII. Security Best Practices

  • Use TLS 1.2+: Disable TLS 1.0 and 1.1—they have known vulnerabilities.
  • Enable HSTS: Tells browsers to always use HTTPS.
  • OCSP Stapling: Improves performance and privacy of certificate validation.
  • Regular testing: Scan with SSL Labs quarterly to catch configuration drift.
  • Monitor expiration: Set calendar reminders even with auto-renewal.

IX. Wildcard Certificates

Secure all subdomains with a single certificate.

A. Obtaining Wildcard Cert

# Wildcard requires DNS validation
sudo certbot certonly --manual --preferred-challenges=dns \
    -d example.com -d *.example.com

# You'll need to add a TXT record to your DNS:
# _acme-challenge.example.com

# After adding DNS record, press Enter to continue

B. Automated DNS Validation

# With Cloudflare DNS plugin
sudo apt install python3-certbot-dns-cloudflare

# Create credentials file
# /etc/letsencrypt/cloudflare.ini
# dns_cloudflare_api_token = YOUR_API_TOKEN

sudo certbot certonly --dns-cloudflare \
    --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
    -d example.com -d *.example.com

X. Conclusion

SSL/TLS certificates are essential for any website. Let's Encrypt and Certbot make obtaining and renewing certificates straightforward, while proper Nginx configuration ensures optimal security and performance. After migration, test thoroughly for mixed content issues and monitor your certificate status regularly. With automatic renewal configured, your HTTPS setup will run maintenance-free for years.

What SSL challenges have you encountered? Share your experience in the comments!