Let's Encrypt is a free Certificate Authority that issues SSL certificates via the Certbot client tool, handling automatic renewal. This guide covers installation on Ubuntu VPS for both Nginx and Apache.
Prerequisites
- Ubuntu 20.04/22.04/24.04 VPS with root access
- Domain DNS A Record pointing to your VPS IP
- Nginx or Apache installed and running
- Ports 80 and 443 open in your firewall
Install Certbot
sudo apt update sudo apt install snapd -y sudo snap install --classic certbot sudo ln -s /snap/bin/certbot /usr/bin/certbot
Get Certificate for Nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot automatically edits your Nginx config and adds HTTP → HTTPS redirect.
For manual control, use certonly mode:
sudo certbot certonly --nginx -d yourdomain.com
Get Certificate for Apache
sudo apt install python3-certbot-apache -y sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
Let's Encrypt vs Paid SSL: When to Choose Which
Let's Encrypt works well for most websites needing basic HTTPS. However, paid SSL certificates offer additional value in certain scenarios. Use this comparison to make the right choice for your situation.
| Feature | Let's Encrypt | Paid SSL (OV/EV) |
|---|---|---|
| Cost | Free | From 1,000+ THB/year |
| Certificate type | DV only | DV / OV / EV / Wildcard |
| Validity | 90 days (auto-renewed) | 1 or 3 years |
| Identity validation | Domain only | OV: Organization / EV: Strict |
| Wildcard | Supported via DNS challenge | Full support, no DNS challenge needed |
| Warranty | None | Included (varies by issuer) |
| Best for | Personal sites, blogs, dev servers, startups | E-commerce, banking, enterprises, multi-subdomain |
In summary: if your site is a WordPress blog, portfolio, or web app that doesn't handle payments directly, Let's Encrypt is perfectly adequate. For e-commerce or sites requiring Wildcard coverage across many subdomains, a paid SSL certificate is worth considering.
Verify Installation
sudo certbot certificates
Test renewal:
sudo certbot renew --dry-run
Automatic Renewal
Certbot installs a systemd timer automatically to renew certificates daily. Check it:
sudo systemctl status certbot.timer
Add a post-renewal hook to reload Nginx:
sudo nano /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
#!/bin/bash systemctl reload nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
Configuring HTTPS Redirect and HSTS for Maximum Security
After installing SSL, the next critical step is forcing all traffic to HTTPS and adding the HTTP Strict Transport Security (HSTS) header to tell browsers they must connect via HTTPS only. This prevents downgrade attacks and mixed-content issues.
Nginx: HTTPS Redirect and HSTS
# /etc/nginx/sites-available/yourdomain.com
# HTTP to HTTPS redirect
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
# HTTPS server block
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# HSTS (1 year)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
}
Apache: HTTPS Redirect and HSTS
# /etc/apache2/sites-available/yourdomain.com.conf
<VirtualHost *:80>
ServerName yourdomain.com
Redirect permanent / https://yourdomain.com/
</VirtualHost>
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/yourdomain.com/chain.pem
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</VirtualHost>
Restart your web server after editing config:
# Nginx sudo nginx -t && sudo systemctl reload nginx # Apache sudo apachectl configtest && sudo systemctl reload apache2
Test your SSL configuration at SSL Labs (ssllabs.com/ssltest/) to see your grade and further improvement suggestions. Aim for grade A or higher.
Monitoring Certificate Expiry Automatically
Even with Certbot's automatic renewal, set up additional monitoring so you receive alerts before a certificate expires — especially in cases where Certbot encounters errors or DNS issues.
Check expiry date using openssl:
echo | openssl s_client -servername yourdomain.com \ -connect yourdomain.com:443 2>/dev/null \ | openssl x509 -noout -dates
Create a warning script that triggers when fewer than 30 days remain:
#!/bin/bash # /usr/local/bin/check-cert-expiry.sh DOMAIN="yourdomain.com" DAYS_WARN=30 EXPIRY=$(echo | openssl s_client -servername $DOMAIN \ -connect $DOMAIN:443 2>/dev/null \ | openssl x509 -noout -enddate \ | cut -d= -f2) EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s) NOW_EPOCH=$(date +%s) DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 )) if [ $DAYS_LEFT -le $DAYS_WARN ]; then echo "WARNING: Certificate for $DOMAIN expires in $DAYS_LEFT days!" # Add email notification command here fi
Add this script to cron to run daily:
# Run check every day at 09:00 0 9 * * * /usr/local/bin/check-cert-expiry.sh
Alternatively, use a monitoring tool such as Uptime Kuma which includes built-in SSL certificate monitoring with configurable alert thresholds, or any external monitoring service that can send email or webhook notifications when a certificate is close to expiry.
Common Troubleshooting
Port 80 Blocked
sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
DNS Not Propagated
Check: dig +short yourdomain.com — must return your VPS IP.
Certificate Expired and Won't Renew
sudo certbot renew --force-renewal -d yourdomain.com
SSL Best Practices and Pre-Deployment Checklist
Before pushing your website to production, verify that your SSL configuration is complete and secure. Use this checklist to avoid common pitfalls.
SSL Installation Checklist
- Certificate installed successfully —
sudo certbot certificatesshows VALID - Renewal dry run passes:
sudo certbot renew --dry-run - HTTP redirects to HTTPS correctly (test in browser or with curl)
- HSTS header present in response:
curl -I https://yourdomain.com | grep Strict - No mixed content warnings — all page resources load over HTTPS
- SSL grade A or higher at SSL Labs
- systemd timer running:
sudo systemctl status certbot.timer
Verify TLS Protocol Versions
Disable old TLS versions (1.0 and 1.1) and enable only TLS 1.2 and 1.3. For Nginx, check /etc/letsencrypt/options-ssl-nginx.conf and confirm it contains:
ssl_protocols TLSv1.2 TLSv1.3;
For Apache, check ssl.conf:
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
Disabling old TLS versions prevents vulnerabilities like POODLE and BEAST and improves your SSL Labs grade.
Multi-Domain Certificate (SAN)
If you host multiple domains on a single VPS, you can request a certificate covering all of them in one command:
sudo certbot --nginx \ -d domain1.com -d www.domain1.com \ -d domain2.com -d www.domain2.com \ -d domain3.com
Let's Encrypt supports up to 100 domains per certificate (SAN). In practice, group certificates by application for easier management and renewal tracking.
Additional Tips for Let's Encrypt on VPS
- Rate limits: Let's Encrypt limits 5 certificates per domain per week. Use the
--stagingflag during testing to avoid hitting limits. - Use snap for Certbot: The snap version stays up to date automatically. The apt package may lag behind.
- Webroot plugin: If you don't want Certbot to modify your server config, use
--webroot -w /var/www/htmlfor manual control. - Standalone mode: If no web server is running yet, use
--standaloneto spin up a temporary server on port 80 for verification.
Summary: Let's Encrypt via Certbot is the easiest free SSL for VPS, auto-renewing every 90 days. For OV/EV or Wildcard SSL covering multiple subdomains, AsiaGB offers a range of commercial SSL certificates.
VPS for Your Web Server
AsiaGB VPS Ubuntu includes Full Root Access — install Nginx/Apache + SSL immediately. From 500 THB/month.
View VPS Plans