Installing Let's Encrypt SSL Certificates with Nginx on Debian

How to issue SSL certificates with Let's Encrypt and configure them on Nginx servers to provide secure connections between client and server.

Requirements

  • Debian 9 (Stretch)
  • Nginx installed
  • A domain pointing to the server's IP address

1. Install Certbot

Edit the sources.list file.

sudo nano /etc/apt/sources.list

Add the following lines to the end of the file.

deb http://deb.debian.org/debian stretch-backports main contrib non-free
deb-src http://deb.debian.org/debian stretch-backports main contrib non-free

Example:

sources.list

deb http://cdn-aws.deb.debian.org/debian stretch main
deb http://security.debian.org/debian-security stretch/updates main
deb http://cdn-aws.deb.debian.org/debian stretch-updates main

deb http://deb.debian.org/debian stretch-backports main contrib non-free
deb-src http://deb.debian.org/debian stretch-backports main contrib non-free

Update the package index.

sudo apt update

Install Certbot from stretch-backports.

sudo apt install python-certbot-nginx -t stretch-backports

Check the installed version.

certbot --version
certbot 0.28.0

2. Create a New Domain

Follow the guide Create and Configure a New Domain with Nginx. Once the site is available—e.g. http://your_domain.com—continue with Certbot.

3. Issue the SSL Certificate

List existing certificates.

sudo ls -l /etc/letsencrypt/live

Create a new certificate.

sudo certbot --nginx -d your_domain.com -d www.your_domain.com
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

Choose option 2 so Certbot configures the redirects automatically, then press Enter.

Restart Nginx.

sudo service nginx restart

Verify the site at https://your_domain.com or run:

curl https://your_domain.com
<html>
  <head>
    <title>Welcome to your_domain.com!</title>
  </head>
  <body>
    <h1>Success! The your_domain.com server block is working!</h1>
  </body>
</html>

4. Add a Domain to an Existing Certificate

Include the subdomain blog.your_domain.com in an existing certificate.

sudo certbot -d blog.your_domain.com --expand

Restart Nginx.

sudo service nginx restart

5. Remove a Domain from a Certificate

Delete the domain blog.your_domain.com from an existing certificate.

sudo certbot delete --cert-name blog.your_domain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Deleted all files relating to certificate blog.your_domain.com.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Reconfigure the redirects in the Nginx config files manually.

sudo nano /etc/nginx/sites-available/blog.your_domain.com

For instance, comment or remove the lines marked # managed by Certbot. If needed, recreate the file with the default HTTP configuration.

blog.your_domain.com

server {
    root /var/www/blog.your_domain.com/html;
    index index.html index.htm index.nginx-debian.html;
    server_name blog.your_domain.com www.blog.your_domain.com;
    location / {
        try_files $uri $uri/ =404;
    }
    #listen [::]:443 ssl; # managed by Certbot
    #listen 443 ssl; # managed by Certbot
    #ssl_certificate /etc/letsencrypt/live/blog.your_domain.com/fullchain.pem; # managed by Certbot
    #ssl_certificate_key /etc/letsencrypt/live/blog.your_domain.com/privkey.pem; # managed by Certbot
    #include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    #ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    #if ($host = blog.your_domain.com) {
    #    return 301 https://$host$request_uri;
    #} # managed by Certbot
    listen 80;
    listen [::]:80;
    server_name blog.your_domain.com www.blog.your_domain.com;
    #return 404; # managed by Certbot
}

Restart Nginx.

sudo service nginx restart

6. Configure Automatic Renewal

Let's Encrypt certificates are valid for 90 days, so schedule renewals frequently.

Renew certificates manually.

sudo certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/your_domain.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/your_domain.com/fullchain.pem expires on 2020-09-04 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Simulate the renewal process.

sudo certbot renew --dry-run
...
Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/yourdomain.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Schedule the renewal with cron or a systemd timer.

sudo certbot renew --quiet --no-self-upgrade

References

Published: June 6, 2020