Based on Debian 11 "Bullseye" environment.

Let's Encrypt

Let's Encrypt provides free HTTPS certificates. It's the first choice when opening the website because HTTPS is almost mandatory. Let's Encrypt also provides the official client to create, renew, and revoke certificates - Certbot.

There are several plugins to work with major DNS services, such as Amazon Route 53, Cloudflare, or Google. If you're one of those services users, probably following the official explanation with snap packages will help you.
If your service provider is not listed in the official plugin but exists as a third-party one, this article may help. I'm one of the Gandi LiveDNS users, so I used Gandi plugin.

Install

To get and renew (or revoke) the certificate, Let's Encrypt provides the official client "Certbot". It's available through the Debian package. Though the packaged version is a bit older than the latest from the official, it works fine at least for now. The plugin for Gandi is also ported to a Debian package, but it's too old and doesn't work.
So I used the Debian package Certbot with the latest Gandi plugin from PyPI.

First, install Certbot.

# apt install certbot

Then prepare pip command and install certbot-plugin-gandi.

# apt install python3-pip
# pip install certbot-plugin-gandi
  • certbot-plugin-gandi has to be installed by root

plugin config

How to use this plugin is written in the README.

Before starting, get the API key from Gandi website. (Gandi's API)

Create /etc/letsencrypt/gandi/gandi.ini. You have to make /etc/letsencrypt/gandi directory manually.

# live dns v5 api key
dns_gandi_api_key=APIKEY
  • Organization id is optional

Don't forget to restrict the permission. API key information must be protected.

# chmod 600 /etc/letsencrypt/gandi/gandi.ini

Get the certificate

Request the wildcard certificate.

# certbot certonly --authenticator dns-gandi\
 --dns-gandi-credentials /etc/letsencrypt/gandi/gandi.ini\
 -d example.jp -d \*.example.jp
  • "\*.example.jp" will match any subdomains, but won't match "example.jp" (without subdomain). So you need to specify two types of domains.
  • "--server https://acme-v02.api.letsencrypt.org/directory" is not required because this is same as the default.

After this command, Certbot will ask your email address and agreement confirmation. After that, it will try to obtain new certificate.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-gandi, Installer None
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): info@example.jp

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n
Account registered.
Requesting a certificate for example.jp and *.example.jp
Performing the following challenges:
dns-01 challenge for example.jp
dns-01 challenge for example.jp
Waiting 10 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.jp/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.jp/privkey.pem
   Your certificate will expire on 2021-12-01. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Done. The certificate is stored under /etc/letsencrypt/live/example.jp.
Certificate renewal will be done automatically. (It's set up in the systemd.timer.)


Set up nginx

See nginx official site for more information about HTTPS configurations.

Prepare snippets

To use certificates, prepare the /etc/nginx/snippets/example.jp-ssl.conf

ssl_certificate /etc/letsencrypt/live/example.jp/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.jp/privkey.pem;

Security Enhancement

When using the Certbot with the installer option, it will automatically add some security enhancement. This is not available for the wildcard certificate so we have to make the equivalent configurations manually.

For nginx case, add /etc/letsencrypt/options-ssl-nginx.conf

ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";

Generate /etc/letsencrypt/ssl-dhparams.pem

To generate the dhparams above, use openssl.

# openssl dhparam -out /etc/letsencrypt/ssl-dhparams.pem 2048
  • You may find the command with the 2048 just after the 'dhparam' but that will not save the file as you expect. The numbits (number) MUST BE the last option.
    See the official document for more details.

The file should look like this.

-----BEGIN DH PARAMETERS-----
MIIBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* snip *
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBag==
-----END DH PARAMETERS-----

Add snippets to the server section

Add three snippets to enable them.

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        include snippets/example.jp-ssl.conf;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        server_name example.jp;

        (snip)
}

Stop using certificate

Once the certificate is obtained, Certbot will continue renewing it. If you want to stop using the certificate, the certbot has an option to revoke the related files.
The revoke command will ask you to clean up the configuration files.

# certbot revoke --cert-name example.jp

Supplemental: Certbot packages

The Certbot official recommends using the latest snap package. Debian provides the Debian package, but it's already a bit older than the official package.
(As of 2021 September, Debian package is 1.12.0 while Snap package is 1.18.0)
Using Snap package is not a big issue, but things will get complicated when considering the plugins.

The official plugins are released as snap packages same as Certbot itself, so it should work as instructed on the official website document. When it comes to the third-party plugins, especially Gnadi plugin in my case, they may not be released as snap packages.
Gandi plugin is officially released only through PyPI module, so I tried some combinations.

(1) Snap Certbot and PyPI plugin - Didn't work
It works fine when getting the certificate, but fails when Certbot automatically tries to renew the certificate. There may be a way to solve the issue, but I couldn't find it.
Maybe I could solve this by building the plugin snap by myself, but I gave up and tried other choices.

(2) Debian package Certbot and Debian package Gandi plugin (python3-certbot-dns-gandi) - Didn't work
To follow the Debian way, I tried to install both from Debian packages. Unfortunately, Gandi plugin is too old (current 1.3.2 is required) and didn't work. Gandi plugin doesn't have any updates even for Sid, so impossible to install the latest version with apt.

(3) Debian package Certbot and PyPI Gandi plugin (certbot-plugin-gandi) - Worked!
As explained on this page, this combination worked even though Debian packaged Certbot is a bit old.
There may be a risk that the Debian packaged version (1.12.0) will stop working due to Let"s Encrypt API change, Bookworm or Sid has the latest version of Certbot. Backport from them can be expected.


Update History

2020-05-26

  • Changed "./rfc2136.example.jp.ini" to the absolute path.
    This command will store the path as typed into the renewal config file. Even if the relative path is ok when obtaining the certificate for the first time, the path stored from the config file may not match the actual file path. This will cause the certificate renewal failure.

2021-09-03

  • Update the article to Bullseye version
  • Use Gandi Live DNS (used to explain the case with rfc2136 plugin to update DNS records on the self-managed servers)
  • Add an additional section for the snap package and Debian package.