Every website serving traffic over the internet should use HTTPS. Beyond encrypting data in transit between your visitors and your server, HTTPS is a ranking factor for search engines, a requirement for modern web APIs like HTTP/2 and service workers, and a trust signal that browsers display prominently. Let’s Encrypt has removed the cost barrier entirely by providing free, automated SSL/TLS certificates, and Certbot is the most widely used tool to obtain and manage them.
This guide covers everything you need to know to set up Certbot with Nginx or Apache, automate certificate renewal, obtain wildcard certificates, and harden your HTTPS configuration with security headers.
Prerequisites
Before you begin, make sure you have:
- An Ubuntu server (22.04 or 24.04) with a public IP address
- A registered domain name with DNS A records pointing to your server
- Nginx or Apache installed and serving your website
- Terminal access with sudo privileges
- Port 80 (HTTP) and port 443 (HTTPS) open in your firewall
Why HTTPS Matters
Here is why every system administrator should prioritize HTTPS:
- Encryption: HTTPS encrypts all traffic between the client and server, protecting login credentials, personal data, and session cookies from eavesdropping
- Authentication: SSL/TLS certificates verify that visitors are communicating with your actual server, not an impersonator
- Data integrity: HTTPS prevents man-in-the-middle attackers from modifying data in transit
- SEO ranking: Google uses HTTPS as a ranking signal. Sites without HTTPS are at a disadvantage in search results
- Browser trust: Modern browsers display “Not Secure” warnings on HTTP pages, especially those with forms
- Compliance: Many regulations (GDPR, PCI DSS, HIPAA) require encryption of data in transit
What Is Let’s Encrypt?
Let’s Encrypt is a free, automated, and open Certificate Authority (CA) operated by the Internet Security Research Group (ISRG). It issues Domain Validation (DV) certificates that are trusted by all major browsers and operating systems.
Key characteristics:
- Free: No cost for certificates
- Automated: Certificates can be obtained and renewed without manual intervention
- Short-lived: Certificates are valid for 90 days, encouraging automated renewal and reducing the impact of key compromise
- Rate limited: There are limits on how many certificates you can request per domain per week (50 certificates per registered domain per week)
Installing Certbot
Certbot is the official Let’s Encrypt client. The recommended installation method is via snap, which ensures you always have the latest version:
# Remove any OS-packaged certbot to avoid conflicts
sudo apt-get remove certbot
# Install Certbot via snap
sudo snap install --classic certbot
# Create a symbolic link so certbot is available in your PATH
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Verify the installation:
certbot --version
Obtaining Certificates for Nginx
Automatic Configuration (Recommended)
Certbot can automatically obtain the certificate and modify your Nginx configuration to enable HTTPS. This is the simplest approach:
sudo certbot --nginx -d knowledgexchange.xyz -d www.knowledgexchange.xyz
Certbot will:
- Verify you control the domain by placing a challenge file on your server
- Obtain the certificate from Let’s Encrypt
- Modify your Nginx server block to enable SSL/TLS
- Set up an HTTP-to-HTTPS redirect
You will be prompted to enter your email address (for renewal notifications) and agree to the terms of service.
After completion, your Nginx configuration will be updated automatically. You can verify the changes:
sudo nginx -t
sudo systemctl reload nginx
Tip: Always run
nginx -tto test configuration syntax before reloading. A syntax error can take your site offline.
What Certbot Adds to Your Nginx Configuration
Certbot adds lines similar to these to your server block:
server {
listen 443 ssl;
server_name knowledgexchange.xyz www.knowledgexchange.xyz;
ssl_certificate /etc/letsencrypt/live/knowledgexchange.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/knowledgexchange.xyz/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# ... your existing configuration
}
server {
listen 80;
server_name knowledgexchange.xyz www.knowledgexchange.xyz;
return 301 https://$host$request_uri;
}
For more details on Nginx configuration, see our articles on installing Nginx and improving SSL performance in Nginx.
Certonly Mode (Manual Configuration)
If you prefer to configure Nginx yourself, use the certonly subcommand to obtain the certificate without modifying any configuration:
sudo certbot certonly --nginx -d knowledgexchange.xyz -d www.knowledgexchange.xyz
The certificates will be saved to /etc/letsencrypt/live/knowledgexchange.xyz/ and you can reference them in your Nginx configuration manually.
Obtaining Certificates for Apache
The process for Apache is nearly identical. Install the Certbot Apache plugin if it is not already available:
sudo apt install -y python3-certbot-apache
Then run Certbot with the --apache flag:
sudo certbot --apache -d knowledgexchange.xyz -d www.knowledgexchange.xyz
Certbot will:
- Verify domain ownership
- Obtain the certificate
- Update your Apache virtual host configuration
- Enable the SSL module and create a redirect
Verify and reload Apache:
sudo apachectl configtest
sudo systemctl reload apache2
For certonly mode with Apache:
sudo certbot certonly --apache -d knowledgexchange.xyz -d www.knowledgexchange.xyz
Standalone Mode
If you are not running Nginx or Apache, or if you want to obtain certificates independently of any web server, use standalone mode. Certbot will temporarily start its own web server on port 80:
sudo certbot certonly --standalone -d knowledgexchange.xyz -d www.knowledgexchange.xyz
Important: Port 80 must be available. If Nginx or Apache is running, stop it first:
sudo systemctl stop nginx # or apache2 sudo certbot certonly --standalone -d knowledgexchange.xyz sudo systemctl start nginx # or apache2
Standalone mode is particularly useful for non-web services that need TLS certificates, such as mail servers or VPN endpoints.
Setting Up Auto-Renewal
Let’s Encrypt certificates expire after 90 days, so automated renewal is essential. The good news is that Certbot installs a systemd timer (or cron job) automatically that runs twice per day and renews any certificates that are within 30 days of expiration.
Verify the timer is active:
sudo systemctl status certbot.timer
You should see active (waiting) in the output. You can also list the scheduled timers:
sudo systemctl list-timers | grep certbot
Testing Auto-Renewal
Always test that renewal will work correctly before relying on it:
sudo certbot renew --dry-run
This simulates the renewal process without actually obtaining new certificates. If the dry run succeeds, your auto-renewal is properly configured.
Post-Renewal Hooks
After a certificate is renewed, your web server needs to reload the new certificate. Certbot handles this automatically for Nginx and Apache plugins, but if you used certonly mode, you need to add a renewal hook:
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << 'EOF'
#!/bin/bash
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
For Apache:
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh << 'EOF'
#!/bin/bash
systemctl reload apache2
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh
Wildcard Certificates with DNS Challenge
Wildcard certificates cover all subdomains of a domain (e.g., *.knowledgexchange.xyz). They can only be obtained using the DNS-01 challenge, which requires you to create a specific DNS TXT record.
Manual DNS Challenge
sudo certbot certonly --manual --preferred-challenges dns \
-d knowledgexchange.xyz -d "*.knowledgexchange.xyz"
Certbot will display a TXT record you need to add to your DNS configuration:
Please deploy a DNS TXT record under the name:
_acme-challenge.knowledgexchange.xyz
with the following value:
dGhpcyBpcyBhIHRlc3Qgc3RyaW5n
Before continuing, verify the record is deployed.
Add the TXT record through your DNS provider’s control panel, wait for propagation (usually 1-5 minutes), then press Enter to continue.
Note: Manual DNS challenges cannot be renewed automatically. For automated wildcard renewal, use a DNS plugin.
Automated DNS Challenge with Plugins
Certbot has plugins for many DNS providers that automate the TXT record creation. For example, with Cloudflare:
# Install the Cloudflare DNS plugin
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare
Create a credentials file:
sudo mkdir -p /etc/letsencrypt/cloudflare
sudo tee /etc/letsencrypt/cloudflare/credentials.ini << 'EOF'
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
EOF
sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini
Obtain the wildcard certificate:
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
-d knowledgexchange.xyz -d "*.knowledgexchange.xyz"
This method supports fully automated renewal since Certbot can create and clean up the DNS records programmatically.
Certificate Monitoring
It is important to monitor your certificates to catch renewal failures before they cause outages.
Check Certificate Expiration
# Check all managed certificates
sudo certbot certificates
# Check a specific domain's certificate from the outside
echo | openssl s_client -servername knowledgexchange.xyz -connect knowledgexchange.xyz:443 2>/dev/null | openssl x509 -noout -dates
Set Up Expiration Alerts
Create a simple monitoring script:
sudo tee /usr/local/bin/check-certs.sh << 'SCRIPT'
#!/bin/bash
THRESHOLD_DAYS=14
ALERT_EMAIL="admin@knowledgexchange.xyz"
for cert_dir in /etc/letsencrypt/live/*/; do
domain=$(basename "$cert_dir")
expiry_date=$(openssl x509 -enddate -noout -in "${cert_dir}fullchain.pem" | cut -d= -f2)
expiry_epoch=$(date -d "$expiry_date" +%s)
current_epoch=$(date +%s)
days_remaining=$(( (expiry_epoch - current_epoch) / 86400 ))
if [ "$days_remaining" -lt "$THRESHOLD_DAYS" ]; then
echo "WARNING: Certificate for $domain expires in $days_remaining days" | \
mail -s "SSL Certificate Expiration Warning: $domain" "$ALERT_EMAIL"
fi
done
SCRIPT
sudo chmod +x /usr/local/bin/check-certs.sh
Add it to cron to run daily:
echo "0 8 * * * root /usr/local/bin/check-certs.sh" | sudo tee /etc/cron.d/check-ssl-certs
Adding Security Headers
Having HTTPS is only part of the equation. You should also configure security headers to maximize protection. Add these to your Nginx server block:
# HTTP Strict Transport Security - tells browsers to always use HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Prevent MIME type sniffing
add_header X-Content-Type-Options "nosniff" always;
# Prevent clickjacking
add_header X-Frame-Options "SAMEORIGIN" always;
# Enable XSS filter in older browsers
add_header X-XSS-Protection "1; mode=block" always;
# Control referrer information
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Content Security Policy (customize for your site)
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" always;
# Permissions Policy
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
For Apache, add equivalent headers in your virtual host or .htaccess:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Important: Before enabling HSTS with
preload, make sure your entire domain works over HTTPS. Once preloaded, browsers will refuse to connect over HTTP, and removing your domain from the preload list takes months.
Troubleshooting Common Issues
Port 80 Is Blocked
Certbot’s HTTP-01 challenge requires port 80 to be accessible from the internet. If it is blocked:
# Check if port 80 is open in UFW
sudo ufw status | grep 80
# Allow port 80 if blocked
sudo ufw allow 80/tcp
# Check if something else is using port 80
sudo ss -tlnp | grep :80
If your hosting provider or ISP blocks port 80, use the DNS challenge method instead.
DNS Not Propagated
If Certbot fails with a DNS-related error, your domain’s A record may not be pointing to the server yet:
# Check DNS resolution
dig +short knowledgexchange.xyz
nslookup knowledgexchange.xyz
# The returned IP should match your server's public IP
curl -s https://ifconfig.me
DNS changes can take up to 48 hours to propagate globally, though most propagation happens within minutes. Wait and try again.
Rate Limit Exceeded
If you have exceeded Let’s Encrypt rate limits, you will receive an error. There is no way to reset the limit. You must wait until the limit window resets (typically one week). To avoid hitting rate limits:
- Use
--dry-runfor testing - Use the staging environment for development:
--staging - Consolidate multiple subdomains into a single certificate using
-dflags or a wildcard
Certificate Renewal Fails Silently
If auto-renewal is not working, check the Certbot logs:
sudo cat /var/log/letsencrypt/letsencrypt.log
Common causes:
- Port 80 is no longer accessible (firewall or web server configuration changed)
- DNS records were modified
- Certbot snap is outdated:
sudo snap refresh certbot
Testing Your SSL Configuration
After setting up HTTPS, test your configuration using external tools:
# Quick test from the command line
curl -vI https://knowledgexchange.xyz 2>&1 | grep -E "(SSL|subject|expire|issuer)"
For a comprehensive analysis, visit SSL Labs Server Test and enter your domain. Aim for an A+ rating by enabling HSTS and using strong cipher suites.
Conclusion
Let’s Encrypt and Certbot have made SSL/TLS certificates accessible to everyone. With automated issuance and renewal, there is no excuse for serving any website over plain HTTP. By following this guide, you have set up free, automatically renewing certificates and hardened your HTTPS configuration with security headers.
For related topics, check out our articles on moving an Nginx website to HTTPS/SSL, improving SSL performance in Nginx, and creating self-signed certificates on Ubuntu for development environments. If you need to understand which web server to choose, see our comparison of Apache vs. Nginx.