How to install Let’s Encrypt SSL in Debian?

SSL / TLS (Secure Socket Layer / Transport Layer Security) are cryptographic protocols designed to provide communications security over a computer network: web, email, instant messengers.

CA (Certificate Authoritative): worldwide recognized entity in charge of generating security certificates for third parties.

CSR (Certificate Signing Request): signing request sended to a CA.

Let’s Encrypt: Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. It is a service provided by the Internet Security Research Group (ISRG).

It provides people with the digital certificates they need to enable HTTPS (SSL / TLS) on their websites, free of charge, in the most user-friendly way possible.

Another features are:

  • Free: Anyone who owns a domain name can use Let’s Encrypt to obtain a trusted certificate at zero cost.
  • Automatic: Software running on a web server can interact with Let’s Encrypt to painlessly obtain a certificate, securely configure it for use, and automatically take care of renewal.
  • Secure: Let’s Encrypt will serve as a platform for advancing TLS security best practices, both on the CA side and by helping site operators properly secure their servers.
  • Transparent: All certificates issued or revoked will be publicly recorded and available for anyone to inspect.
  • Open: The automatic issuance and renewal protocol is published as an open standard that others can adopt.
  • Cooperative: Much like the underlying Internet protocols themselves, Let’s Encrypt is a joint effort to benefit the community, beyond the control of any one organization.

Cerbot: Certbot is a free, open source software tool for automatically using Let’s Encrypt certificates on manually-administrated websites to enable HTTPS.

You may be interested in:

Install Cerbot

$ sudo apt install certbot
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  python-pyicu python3-acme python3-certbot python3-configargparse python3-configobj python3-distutils python3-future python3-josepy python3-lib2to3 python3-mock python3-openssl python3-parsedatetime python3-pbr
  python3-requests-toolbelt python3-rfc3339 python3-setuptools python3-tz python3-zope.component python3-zope.event python3-zope.hookable python3-zope.interface
Suggested packages:
  python3-certbot-apache python3-certbot-nginx python-certbot-doc python-acme-doc python-configobj-doc python-future-doc python-mock-doc python-openssl-doc python3-openssl-dbg python-setuptools-doc
The following NEW packages will be installed:
  certbot python-pyicu python3-acme python3-certbot python3-configargparse python3-configobj python3-distutils python3-future python3-josepy python3-lib2to3 python3-mock python3-openssl python3-parsedatetime
  python3-pbr python3-requests-toolbelt python3-rfc3339 python3-setuptools python3-tz python3-zope.component python3-zope.event python3-zope.hookable python3-zope.interface
0 upgraded, 22 newly installed, 0 to remove and 105 not upgraded.
Need to get 1,937 kB of archives.
After this operation, 9,700 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

Get help

$ certbot -h

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

  certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...

Certbot can obtain and install HTTPS/TLS/SSL certificates.  By default,
it will attempt to use a webserver both for obtaining and installing the
certificate. The most common SUBCOMMANDS and flags are:

obtain, install, and renew certificates:
    (default) run   Obtain & install a certificate in your current webserver
    certonly        Obtain or renew a certificate, but do not install it
    renew           Renew all previously obtained certificates that are near
expiry
    enhance         Add security enhancements to your existing configuration
   -d DOMAINS       Comma-separated list of domains to obtain a certificate for

  (the certbot apache plugin is not installed)
  --standalone      Run a standalone webserver for authentication
  (the certbot nginx plugin is not installed)
  --webroot         Place files in a server's webroot folder for authentication
  --manual          Obtain certificates interactively, or using shell script
hooks

   -n               Run non-interactively
  --test-cert       Obtain a test certificate from a staging server
  --dry-run         Test "renew" or "certonly" without saving any certificates
to disk

manage certificates:
    certificates    Display information about certificates you have from Certbot
    revoke          Revoke a certificate (supply --cert-path or --cert-name)
    delete          Delete a certificate

manage your account with Let's Encrypt:
    register        Create a Let's Encrypt ACME account
    update_account  Update a Let's Encrypt ACME account
  --agree-tos       Agree to the ACME server's Subscriber Agreement
   -m EMAIL         Email address for important account notifications

More detailed help:

  -h, --help [TOPIC]    print this message, or detailed help on a topic;
                        the available TOPICS are:

   all, automation, commands, paths, security, testing, or any of the
   subcommands or plugins (certonly, renew, install, register, nginx,
   apache, standalone, webroot, etc.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Certbot configuration

Certbot uses the following directory structure to store and manage certificates:

In acme-staging you will find the test environment configuration (–test-cert option), use the test environment until you are sure that you can obtain your certificates successfully, once the certbot indicates that the certificates have been generated correctly use the acme production environment.

archive is the history of all certificates obtained and renewed.

Under live there are symlinks to archive, they point to the latest versions of the obtained/renewed certificates.

Under renewal we find the setting that will be used in the auto-renew process.

Put in renewal-hooks actions that you want to run before, after or during the renewal process.

/etc/letsencrypt/
├── accounts
│   ├── acme-staging-v02.api.letsencrypt.org
│   │   └── directory
│   └── acme-v02.api.letsencrypt.org
│       └── directory
├── archive
├── csr
├── keys
├── live
├── renewal
└── renewal-hooks
    ├── deploy
    ├── post
    └── pre

Get

In order to avoid repeating the common options every time we obtain a certificate we must have a configuration similar to the following in the /etc/letsencrypt/cli.ini file.

# Because we are using logrotate for greater flexibility, disable the
# internal certbot logrotation.
max-log-backups = 0
# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Certbot with
# "--help" to learn more about the available options.
#
# Note that these options apply automatically to all use of Certbot for
# obtaining or renewing certificates, so options specific to a single
# certificate on a system with several certificates should not be placed
# here.

# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Uncomment and update to register with the specified e-mail address
# email = foo@example.com

# Uncomment to use the standalone authenticator on port 443
# authenticator = standalone

# Uncomment to use the webroot authenticator. Replace webroot-path with the
# path to the public_html / webroot folder being served by your web server.
authenticator = webroot
webroot-path = /var/www/letsencrypt

We need to create /var/www/letsencrypt/.well-known/acme-challenge/ DIR with

$ sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge/

Create a virtual host with a configuration like this:

server {
    listen 80;
    server_name mydomain.com; 
    
    location / {
        return 301 https://$host$request_uri;
    }
    
    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt/;
    }
}

Modify server_name directive accordingly.

Now we create a txt file under /var/www/letsencrypt/.well-known/acme-challenge/.

$ sudo echo OK > /var/www/letsencrypt/.well-known/acme-challenge/ok.txt

Reload NGINX configuraiton with:

$ sudo service nginx reload

Open your browser (or use curl) and try to access to http://mydomain.com/.well-known/acme-challenge/ok.txt if you get and OK your are ready to obtain a certificate, first we’ll try to get a test certificate.

$ sudo certbot certonly --test-cert --cert-name midominio.com -d midominio.com,www.midominio.com,subdominio1.midominio.com

the –cert-name option is to identify the domain within the /etc/letsencrypt DIR once you have successfully obtained the certificates remove the –test-cert option and run the command again:

$ sudo certbot certonly --cert-name mydomain.com -d mydomain.com,www.mydomain.com,subdoamain.mydomain.com

Set up NGINX

Now we are ready to configure NGINX, check SSL Configuration Generator to start from a template.

server {
    listen 443 ssl http2;
    
    # SSL configuration
    ssl_certificate  /etc/letsencrypt/live/mydomain.com/fullchain.pem; 
    ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; 
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
    # Absolute path of snippets DIR: /etc/nginx/snippets
    ssl_dhparam snippets/dhparam;

    # modern configuration
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;	

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /etc/letsencrypt/live/midominio.com/fullchain.pem; 
    
    # Put here you domain
    #
    server_name mydomain.com;
    
    # Max file size useful for file uploading 
    # 
    client_max_body_size 8M;
    
    location / {
        # NGINX acting as reverse proxy
        #
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        #
        # Set the backend url and port, port is optional for standard services
        # when there is a variable as a part of proxy_pass URL a resolver is needed.
        #
        proxy_pass http://myurl.internal:port;
    }
}

Reload the NGINX configuration:

$ sudo service nginx reload

List the certificates

$ sudo certbot certificates

Renew automatically

Now that we have configured our certificate correctly, we must create the necessary configurations so that the renewal process is automatic. In the case of Debian, a systemd timer is created as part of the certbot package installation process. You can inspect this file with:

$ cat /lib/systemd/system/certbot.timer
[Unit]
Description=Run certbot twice daily

[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true

[Install]
WantedBy=timers.target

If your distro doesn’t use systemd then create a bash script in /etc/cron.daily (on Alpine Linux put the script in /etc/periodic/daily)

#!/bin/sh
certbot renew

The created file must have execute permissions.

Further readings

YouTube video

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.