LibraHostDocumentation

Documentation

Complete guides for all our hosting services

🔒 Install SSL Let's Encrypt with Certbot + Nginx#

Secure your websites with free SSL certificates from Let's Encrypt using Certbot. This guide walks you through setting up HTTPS and configuring automatic renewal.

🎯 Objectives#

  • 🔐 Install free Let's Encrypt SSL certificates
  • ⚡ Configure Certbot for Nginx
  • 🔄 Set up automatic renewal
  • 🛡️ Optimize SSL configuration for security
  • ✅ Test and validate HTTPS installation

🧰 Prerequisites#

  • Nginx + PHP-FPM installed (see Nginx + PHP-FPM guide)
  • Valid domain name pointing to your VPS
  • Ports 80 and 443 open on your server
  • Root or sudo access

💡 Important: This guide builds on the Nginx installation from the previous tutorial. Make sure you have Nginx properly configured first.


1️⃣ Preparation and verification#

🌐 Domain verification#

Before starting, verify that your domain points to your server:

# DNS verification nslookup your-domain.com dig your-domain.com # HTTP access test (must work) curl -I http://your-domain.com

🔧 Nginx verification#

# Nginx configuration verification sudo nginx -t # Service status sudo systemctl status nginx # Port testing sudo netstat -tlnp | grep -E ':80|:443'

2️⃣ Certbot installation#

📦 Installation via APT (Ubuntu/Debian)#

# Installation of Certbot and the Nginx plugin sudo apt update sudo apt install certbot python3-certbot-nginx -y

✅ Installation verification#

# Certbot test certbot --version # Available help and options certbot --help

3️⃣ SSL certificate obtaining#

🎫 First installation with automatic configuration#

Certbot can automatically modify your Nginx configuration:

# Automatic installation for a domain sudo certbot --nginx -d your-domain.com -d www.your-domain.com # Installation for multiple domains sudo certbot --nginx -d site1.com -d www.site1.com -d site2.com -d www.site2.com

During installation:

  1. Enter your email (expiration notifications)
  2. Accept the terms of use
  3. Choose whether you want to receive newsletters (optional)
  4. Certbot will automatically configure Nginx and create the HTTPS redirect

🔧 Manual installation (full control)#

If you prefer to control the configuration:

# Certificate acquisition only (no auto modification) sudo certbot certonly --nginx -d your-domain.com -d www.your-domain.com

4️⃣ Manual Nginx configuration (if manual installation)#

If you chose manual installation, modify your Nginx configuration:

📝 Complete SSL configuration#

# Modify your site sudo nano /etc/nginx/sites-available/mysite

Complete configuration with SSL:

# HTTP to HTTPS redirect server { listen 80; listen [::]:80; server_name your-domain.com www.your-domain.com; # Permanent redirect to HTTPS return 301 https://$server_name$request_uri; } # HTTPS configuration server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name your-domain.com www.your-domain.com; # SSL certificates ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; # Secure SSL configuration ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # HTTPS security 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; # Site configuration (identical to HTTP version) root /var/www/html/mysite; index index.php index.html index.htm; # Logs access_log /var/log/nginx/mysite_ssl_access.log; error_log /var/log/nginx/mysite_ssl_error.log; # PHP configuration location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # Security location ~ /\.ht { deny all; } # Cache optimization location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|zip)$ { expires 1y; add_header Cache-Control "public, immutable"; } # URL management location / { try_files $uri $uri/ /index.php?$query_string; } }

✅ Configuration application#

# Configuration test sudo nginx -t # Nginx reload sudo systemctl reload nginx

5️⃣ Optimized SSL configuration#

🔐 Creating a reusable SSL configuration file#

# Create an SSL configuration file sudo nano /etc/nginx/snippets/ssl-params.conf

Optimized SSL configuration:

# SSL protocols ssl_protocols TLSv1.2 TLSv1.3; # Secure ciphers ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA; ssl_prefer_server_ciphers off; # SSL session cache ssl_session_cache shared:SSL:50m; ssl_session_timeout 1d; ssl_session_tickets off; # OCSP Stapling ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # Security headers add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" 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; add_header Referrer-Policy "no-referrer-when-downgrade" always;

🔄 Using the SSL file in your sites#

Modify your site configurations to use this file:

server { listen 443 ssl http2; server_name your-domain.com; # Certificates ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; # Include SSL configuration include /etc/nginx/snippets/ssl-params.conf; # ... rest of configuration }

6️⃣ Automatic renewal#

🔄 Renewal configuration#

Let's Encrypt generates certificates valid for 90 days. Automatic renewal is essential:

# Renewal test (dry-run) sudo certbot renew --dry-run # Verify installed certificates sudo certbot certificates

⏰ Cron configuration for renewal#

# Edit root crontab sudo crontab -e

Add the following line (official recommendation):

# Let's Encrypt automatic renewal (twice daily) 0 */12 * * * root certbot -q renew --nginx

7️⃣ Tests and validation#

🧪 Basic tests#

# Local HTTPS test curl -I https://your-domain.com # Certificate verification openssl s_client -connect your-domain.com:443 -servername your-domain.com

🌐 Online tests#

  1. SSL Labs: https://www.ssllabs.com/ssltest/
  2. Security Headers: https://securityheaders.com/
  3. Certificate Transparency: https://crt.sh/

📊 Score verification#

A good setup should achieve:

  • Grade A or A+ on SSL Labs
  • Grade A on Security Headers
  • Green on all compatibility tests

8️⃣ Multiple domain management#

🌍 Adding a new domain#

# Add a certificate for a new site sudo certbot --nginx -d new-site.com -d www.new-site.com # Or extend an existing certificate sudo certbot --nginx --expand -d old-site.com -d www.old-site.com -d new-site.com

🔧 Subdomain management#

# Wildcard certificate (requires DNS validation) sudo certbot certonly --manual --preferred-challenges dns -d "*.your-domain.com" -d your-domain.com

9️⃣ Troubleshooting#

🔍 Common problems#

Error: "Challenge failed"

# Verify domain accessibility curl -I http://your-domain.com/.well-known/acme-challenge/test # Verify Nginx configuration sudo nginx -t

Error: "Certificate already exists"

# Force renewal sudo certbot renew --force-renewal # Or delete and reinstall sudo certbot delete --cert-name your-domain.com sudo certbot --nginx -d your-domain.com

Error: "Port 80 not accessible"

# Firewall verification sudo ufw status sudo iptables -L # Port verification sudo netstat -tlnp | grep :80

📋 Useful logs#

# Certbot logs sudo tail -f /var/log/letsencrypt/letsencrypt.log # Nginx logs sudo tail -f /var/log/nginx/error.log # Detailed configuration test sudo certbot renew --dry-run --verbose

✅ Installation summary#

Your Let's Encrypt SSL installation is now complete with:

  • 🔒 SSL certificates free and valid
  • HTTPS configuration optimized
  • 🔄 Automatic renewal configured
  • 🛡️ Enhanced security with appropriate headers