SSL/TLS certificates encrypt traffic between your server and visitors, protecting sensitive data and improving search engine rankings. This comprehensive guide shows you how to obtain free SSL certificates from Let's Encrypt and configure them for Nginx or Apache with automatic renewal.
SSL (Secure Sockets Layer) and its successor TLS (Transport Layer Security) encrypt data transmitted between web servers and browsers.
Encrypts sensitive data like passwords, credit cards, and personal information
Browsers display "Not Secure" warnings for HTTP sites, damaging credibility
Google prioritizes HTTPS sites in search results
Required for PCI DSS, HIPAA, and other regulations
Let's Encrypt is a free, automated Certificate Authority that provides SSL/TLS certificates trusted by all major browsers.
No cost, forever. No hidden fees.
Auto-renews every 90 days
Recognized by all browsers
Certbot places a file on your web server that Let's Encrypt verifies
Let's Encrypt issues a certificate valid for 90 days
Certbot automatically updates Nginx/Apache configuration
Certbot runs twice daily to check and renew if needed
Certbot is the official Let's Encrypt client that automates certificate installation and renewal.
# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
# CentOS/RHEL 8/9
sudo dnf install certbot python3-certbot-nginx -y
# Verify installation
certbot --version
Ensure your Nginx server block is properly configured:
# Example: /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ =404;
}
}
# Enable the site (Ubuntu/Debian)
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
# Automatic installation (recommended)
sudo certbot --nginx -d example.com -d www.example.com
# You'll be prompted to:
# 1. Enter email address (for renewal notifications)
# 2. Agree to Terms of Service
# 3. Choose whether to redirect HTTP to HTTPS (choose option 2)
# Check certificate details
sudo certbot certificates
# Test your site
curl -I https://example.com
# Check SSL rating (should be A+ after optimization)
# Visit: https://www.ssllabs.com/ssltest/analyze.html?d=example.com
If you prefer to configure Nginx manually:
# Get certificate without modifying Nginx config
sudo certbot certonly --nginx -d example.com -d www.example.com
# Certificate files will be saved to:
# /etc/letsencrypt/live/example.com/fullchain.pem
# /etc/letsencrypt/live/example.com/privkey.pem
# Then manually configure Nginx:
sudo nano /etc/nginx/sites-available/example.com
Example Nginx SSL configuration:
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Security headers
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-apache -y
# CentOS/RHEL 8/9
sudo dnf install certbot python3-certbot-apache mod_ssl -y
# Example: /etc/apache2/sites-available/example.com.conf (Ubuntu/Debian)
# or /etc/httpd/conf.d/example.com.conf (CentOS/RHEL)
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/html
AllowOverride All
Require all granted
ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
# Enable the site (Ubuntu/Debian)
sudo a2ensite example.com.conf
# Test configuration
sudo apachectl configtest
# Reload Apache
sudo systemctl reload apache2 # Ubuntu/Debian
# sudo systemctl reload httpd # CentOS/RHEL
# Automatic installation
sudo certbot --apache -d example.com -d www.example.com
# Certbot will:
# - Obtain the certificate
# - Create a new VirtualHost on port 443
# - Configure SSL settings
# - Set up HTTP to HTTPS redirect
# Check Apache SSL configuration
sudo apachectl -S
# Verify certificate
sudo certbot certificates
# Test HTTPS
curl -I https://example.com
sudo a2enmod ssl rewrite headers
Wildcard certificates cover all subdomains (*.example.com) with a single certificate.
Wildcard certificates require DNS validation (not HTTP validation):
# Request wildcard certificate
sudo certbot certonly \
--manual \
--preferred-challenges dns \
-d example.com \
-d *.example.com
# Certbot will instruct you to:
# 1. Create a TXT record in your DNS
# 2. Wait for DNS propagation
# 3. Press Enter to continue
# Example TXT record:
# _acme-challenge.example.com TXT "abc123..."
For automatic renewal, use DNS API plugins:
# Install Cloudflare plugin (if using Cloudflare)
sudo apt install python3-certbot-dns-cloudflare -y
# Create credentials file
sudo mkdir -p /etc/letsencrypt
sudo nano /etc/letsencrypt/cloudflare.ini
# Add your Cloudflare API token:
dns_cloudflare_api_token = YOUR_API_TOKEN
# Secure the credentials file
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
# Request wildcard certificate with auto-renewal
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d example.com \
-d *.example.com
Let's Encrypt certificates expire after 90 days. Certbot automatically sets up renewal.
# Test renewal process (dry run - doesn't actually renew)
sudo certbot renew --dry-run
# Check renewal timer (systemd)
sudo systemctl status certbot.timer
# View renewal configuration
sudo cat /etc/cron.d/certbot
# Renew all certificates that are due for renewal
sudo certbot renew
# Force renew specific certificate
sudo certbot renew --cert-name example.com --force-renewal
# Renew and reload web server
sudo certbot renew --post-hook "systemctl reload nginx"
Run commands before/after renewal:
# Create renewal hook script
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
# Add content:
#!/bin/bash
systemctl reload nginx
systemctl reload php8.1-fpm
# Make executable
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
# This script runs automatically after successful renewal
# Check certificate expiration dates
sudo certbot certificates
# Output shows:
# Certificate Name: example.com
# Domains: example.com www.example.com
# Expiry Date: 2026-03-05 12:34:56+00:00 (VALID: 89 days)
# Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
# Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
Certbot can't connect to your web server on port 80.
Solutions:
# Check if web server is running
sudo systemctl status nginx # or apache2/httpd
# Check if port 80 is open
sudo netstat -tlnp | grep :80
# Check firewall
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Test local access
curl -I http://localhost
Hit Let's Encrypt rate limits (5 failures per hour).
Solutions:
--dry-run for testing--test-certLet's Encrypt can't verify domain ownership.
Solutions:
# Check DNS propagation
dig example.com
nslookup example.com
# Verify domain points to your server
curl -I http://example.com
# Check web server configuration
sudo nginx -t
sudo apachectl configtest
# Check server_name/ServerName directive matches your domain
Browser shows security warning.
Solutions:
# Check certificate chain
openssl s_client -connect example.com:443 -showcerts
# Verify you're using fullchain.pem (not cert.pem)
# Nginx: ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem
# Apache: SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
# Clear browser cache and test in incognito mode
Certificates not renewing automatically.
Solutions:
# Test renewal
sudo certbot renew --dry-run
# Check renewal timer
sudo systemctl status certbot.timer
# Check logs
sudo tail -f /var/log/letsencrypt/letsencrypt.log
# Manually renew to see errors
sudo certbot renew --force-renewal
# Ensure web server config hasn't changed
# Renewal uses same method as initial issuance
Disable weak ciphers. Use only TLS 1.2 and 1.3.
Force HTTPS for all future visits with HTTP Strict Transport Security.
Improve performance with HTTP/2 protocol.
Speed up SSL handshake and improve privacy.
# /etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# HSTS (force HTTPS for 1 year)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# 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 X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Then in your server block:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/nginx/snippets/ssl-params.conf;
# ... rest of configuration
}
# Online tools (aim for A+ rating):
# https://www.ssllabs.com/ssltest/
# https://securityheaders.com/
# Command line testing
openssl s_client -connect example.com:443 -tls1_2
curl -I https://example.com
Our team can help you install and configure SSL certificates for your websites.