Security
Free SSL Certificate with Let's Encrypt - Complete Guide
Install and configure free SSL certificates using Let's Encrypt with automatic renewal and security headers.
What you'll learn
- Install and configure Certbot for Let's Encrypt
- Obtain SSL certificates for single and multiple domains
- Set up automatic certificate renewal
- Configure security headers and HSTS
- Implement SSL best practices (TLS 1.3, OCSP stapling)
- Troubleshoot common SSL issues
Install Certbot
Bash
1# Ubuntu 24.04 — install via snap (recommended)
2sudo snap install --classic certbot
3sudo ln -s /snap/bin/certbot /usr/bin/certbot
4
5# Verify
6certbot --versionObtain Certificate
Bash
1# Nginx — auto-configures the web server
2sudo certbot --nginx -d example.com -d www.example.com
3
4# Apache
5sudo certbot --apache -d example.com -d www.example.com
6
7# Standalone (no web server running)
8sudo certbot certonly --standalone -d example.com
9
10# Wildcard (requires DNS challenge)
11sudo certbot certonly --manual --preferred-challenges dns -d example.com -d "*.example.com"
12# Add the TXT record shown, then press Enter
13
14# Certificates stored in:
15# /etc/letsencrypt/live/example.com/fullchain.pem
16# /etc/letsencrypt/live/example.com/privkey.pemNginx Configuration
NGINX
1# /etc/nginx/sites-available/example.com
2server {
3 listen 80;
4 server_name example.com www.example.com;
5 return 301 https://$host$request_uri;
6}
7
8server {
9 listen 443 ssl;
10 http2 on;
11 server_name example.com www.example.com;
12
13 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
14 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
15 include /etc/letsencrypt/options-ssl-nginx.conf;
16 ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
17
18 # TLS 1.3 only
19 ssl_protocols TLSv1.3;
20 ssl_prefer_server_ciphers off;
21
22 # OCSP Stapling
23 ssl_stapling on;
24 ssl_stapling_verify on;
25 resolver 8.8.8.8 8.8.4.4 valid=300s;
26
27 root /var/www/example.com;
28 index index.html;
29 location / { try_files $uri $uri/ /index.html; }
30}
31
32sudo nginx -t && sudo systemctl reload nginxAutomatic Renewal
Bash
1# Certbot installs a systemd timer automatically
2sudo systemctl status certbot.timer
3
4# Test renewal (dry run)
5sudo certbot renew --dry-run
6
7# Manual renewal if needed
8sudo certbot renew
9
10# After renewal, reload Nginx
11# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
12#!/bin/bash
13systemctl reload nginxSecurity Headers
NGINX
1# Add to Nginx server block (HTTPS only)
2add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
3add_header X-Frame-Options "DENY" always;
4add_header X-Content-Type-Options "nosniff" always;
5add_header Referrer-Policy "strict-origin-when-cross-origin" always;
6add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
7
8# Test your SSL configuration:
9# https://www.ssllabs.com/ssltest/
10# Target: A+ ratingTroubleshooting
- Port 80 blocked: Check firewall —
sudo ufw allow 80/tcpandsudo ufw allow 443/tcp. - Rate limit hit: Let's Encrypt limits 5 certificate failures per hostname per hour. Wait before retrying.
- Certificate not trusted: Use
fullchain.pem(includes intermediates), not justcert.pem. - Mixed content warnings: Update all HTTP asset URLs to HTTPS in your application.