SSLLet's EncryptCertbot5 min read

Install SSL certificates with Let's Encrypt

Obtain and install free SSL certificates with Certbot for your domain on a VPS.


Overview

Let's Encrypt provides free, automated SSL/TLS certificates. Certbot is the official client that handles certificate issuance and renewal.

Prerequisites

  • VPS with a domain pointing to it (A record configured)
  • Nginx or Apache installed
  • Ports 80 and 443 open in your firewall

Step 1: Install Certbot

For Nginx

bash
sudo apt update
sudo apt install -y certbot python3-certbot-nginx

For Apache

bash
sudo apt update
sudo apt install -y certbot python3-certbot-apache

Step 2: Obtain certificate

Nginx

bash
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Apache

bash
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com

Certbot will:

  1. Verify domain ownership via HTTP challenge
  2. Obtain the certificate
  3. Automatically configure your web server
  4. Set up HTTPS redirect (if you choose yes)

Step 3: Verify the installation

bash
# Check certificate details
sudo certbot certificates

# Test HTTPS
curl -I https://yourdomain.com

Visit your site in a browser and verify the padlock icon appears.

Step 4: Auto-renewal

Certbot installs a systemd timer for automatic renewal:

bash
# Check the timer is active
sudo systemctl status certbot.timer

# Test renewal (dry run)
sudo certbot renew --dry-run

Certificates are valid for 90 days. Certbot renews them automatically when they have less than 30 days remaining.

Nginx manual configuration

If Certbot doesn't auto-configure, here's a manual Nginx SSL setup:

nginx
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

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;

    # SSL security settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    root /var/www/yourdomain.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Test and reload:

bash
sudo nginx -t
sudo systemctl reload nginx

Wildcard certificates

For wildcard certificates (*.yourdomain.com), you need DNS validation:

bash
sudo certbot certonly --manual --preferred-challenges dns -d "*.yourdomain.com" -d yourdomain.com

Certbot will ask you to create a TXT record:

  1. Add the TXT record at your DNS provider
  2. Wait for propagation (verify with dig TXT _acme-challenge.yourdomain.com)
  3. Press Enter to continue

Automate wildcard renewal with DNS plugin

For Cloudflare:

bash
sudo apt install -y python3-certbot-dns-cloudflare

# Create credentials file
sudo nano /etc/letsencrypt/cloudflare.ini
ini
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
bash
sudo chmod 600 /etc/letsencrypt/cloudflare.ini

sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d "*.yourdomain.com" -d yourdomain.com

Troubleshooting

  • Challenge failed: Ensure port 80 is open and domain points to your server
  • Rate limited: Let's Encrypt has rate limits (50 certs/domain/week). Use staging for testing:

```bash

sudo certbot --staging --nginx -d yourdomain.com

```

  • Renewal failed: Check sudo certbot renew --dry-run for errors
  • Mixed content: Ensure all resources (images, scripts) use HTTPS URLs

Post-install security headers

Add these headers to your Nginx config for an A+ SSL rating:

nginx
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' https:" always;

Test your SSL configuration at ssllabs.com/ssltest.


Was this guide helpful?