How to install SSL Let’s Encrypt using Lego?

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.

Lego: Let’s Encrypt client and ACME library written in Go.


  • ACME v2 RFC 8555
  • Register with CA
  • Obtain certificates, both from scratch or with an existing CSR
  • Renew certificates
  • Revoke certificates
  • SAN certificate support

You can view full features at:


Related content:

Note: the following procedure has been executed on Alpine Linux.

1 – Download

Ir a Releases seleccione el binario de acuerdo a su arquitectura, en el momento de escribir este post la última versión es la 4.10.2.

$ curl -LO -#

2 – Unpack

$ tar xzvf lego_v4.10.2_linux_amd64.tar.gz

3 – Install

$ sudo install lego /usr/local/bin/

4 – Show version

$ lego -v
lego version 4.10.2 linux/amd64

5 – Getting help

   lego - Let's Encrypt client written in Go

   lego [global options] command [command options] [arguments...]


   run      Register an account, then create and install a certificate
   revoke   Revoke a certificate
   renew    Renew a certificate
   dnshelp  Shows additional help for the '--dns' global option
   list     Display certificates and accounts information.
   help, h  Shows a list of commands or help for one command

   --accept-tos, -a                                             By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service. (default: false)
   --cert.timeout value                                         Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30)
   --csr value, -c value                                        Certificate signing request filename, if an external CSR is to be used.
   --dns value                                                  Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.
   --dns-timeout value                                          Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries. (default: 10)
   --dns.disable-cp                                             By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers. (default: false)
   --dns.resolvers value [ --dns.resolvers value ]              Set the resolvers to use for performing (recursive) CNAME resolving and apex domain determination. For DNS challenge verification, the authoritative DNS server is queried directly. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.
   --domains value, -d value [ --domains value, -d value ]      Add a domain to the process. Can be specified multiple times.
   --eab                                                        Use External Account Binding for account registration. Requires --kid and --hmac. (default: false)
   --email value, -m value                                      Email used for registration and recovery contact.
   --filename value                                             (deprecated) Filename of the generated certificate.
   --help, -h                                                   show help (default: false)
   --hmac value                                                 MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.
   --http                                                       Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges. (default: false)
   --http-timeout value                                         Set the HTTP timeout value to a specific value in seconds. (default: 0)
   --http.memcached-host value [ --http.memcached-host value ]  Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.
   --http.port value                                            Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port. (default: ":80")
   --http.proxy-header value                                    Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy. (default: "Host")
   --http.webroot value                                         Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge
   --key-type value, -k value                                   Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384. (default: "ec256")
   --kid value                                                  Key identifier from External CA. Used for External Account Binding.
   --path value                                                 Directory to use for storing the data. (default: "/home/vagrant/.lego") [$LEGO_PATH]
   --pem                                                        Generate a .pem file by concatenating the .key and .crt files together. (default: false)
   --pfx                                                        Generate a .pfx (PKCS#12) file by with the .key and .crt and issuer .crt files together. (default: false)
   --pfx.pass value                                             The password used to encrypt the .pfx (PCKS#12) file. (default: "changeit")
   --server value, -s value                                     CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "")
   --tls                                                        Use the TLS challenge to solve challenges. Can be mixed with other types of challenges. (default: false)
   --tls.port value                                             Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port. (default: ":443")
   --user-agent value                                           Add to the user-agent sent to the CA to identify an application embedding lego-cli
   --version, -v                                                print the version (default: false)

6 – Get the certificate

6.1 –Create DIR /var/www/letsencrypt

In /var/www/letsencrypt/.well-known/acme-challenge DIR lego stores the file that will help us to validate our domain, that is, we will use the challenge/response http-01 to verify that the domain is ours, therefore we must create the DIR with the following command.

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

6.2 – Create a virtual host for the NGINX with the following configuration

server {
    listen 80;

    location / {
        return 301 https://$host$request_uri;

    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt/;

Create a txt file under /var/www/letsencrypt/.well-known/acme-challenge/ to test the NGINX configuration

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

Reloag NGINX configuration

$ sudo service nginx reload

Now try to access the ok.txt file from the browser with if you accessed successfully then we can go to the next step which is obtain a test certificate.

6.3 – Get a test certificate using Let’s encrypt staging environment

$ sudo lego --server= --accept-tos -m -d -d www.mydomain.comm --http --http.webroot /var/www/letsencrypt --pem --path /etc/lego/ run
  • –accept-tos: aceptar los términos del servicio de forma automática.
  • -m: correo electrónico donde se reciben notificaciones Let’s Encrypt por ejemplo: fecha de expiración del certificado.
  • -d: El dominio al cual se se le desea obtener un certificado SSL/TLS (Se puede especificar varias veces para un obtener un certificado SAN: varios dominios en un mismo certificado)
  • –http: Usar el método HTTP para validar el dominio.
  • http.webroot: DIR donde se guarda los ficheros a usar en el desafío/respuesta, se necesita un servidor web que permita acceder a estos ficheros (Ver 6.2)
  • –pem: Concatena el fichero .key y .crt en un solo fichero.
  • –server: point to staging server, production by default.

6.5 – Get a test certificate using Let’s encrypt production environment

After step 6.3 has been successfully completed, we proceed to obtain a valid and real certificate using the production environment. Keep in mind that production environment has a validation limit of 5 failures per account, per host name and per hour.

$ sudo lego --accept-tos -m -d -d www.mydomain.comm --http --http.webroot /var/www/letsencrypt --pem --path /etc/lego/ run

Note that we removed the server option. It is also possible to execute certain actions through hooks.

6.6 – List certificates

$ sudo lego --path /etc/lego/ list

6.7 – Renew certificates automatically

To automatically renew the certificates, create a cron task or we can create a script in / etc/periodic/daily/

lego --accept-tos -m -d -d www.midominio.comm --http --http.webroot /var/www/letsencrypt --pem --path /etc/lego/ renew --renew-hook="rc-service nginx reload"

Put the previous content in a file, for example /etc/periodic/daily/lego and give it execution permissions, now every day it will check if the security certificate should be renewed, if so, it will proceed to the renewal and if the renewal was successful the NGINX configuration is reloaded. If you want to force the renewal, run the above command passing the –days N option where N must be greater than the number of days the certificate expires.

7 – NGINX configuration

7.1 – Replace or modify these directives

Open the main NGINX configuration file, /etc/nginx/nginx.conf, and set the following directives to the corresponding values.

ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;


# 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;

Generate Diffie Hellman (DH)

$ openssl dhparam -out dhparam.pem 4096

If you run the above operation on a device with few resources, it will most likely take a long time, so it is recommended that you do it on a latest generation CPU for example on my desktop: Intel(R) Core(TM) i7- 9700 CPU @ 3.00GHz with 32 GB RAM took about 1m to complete the process.

Copy the generated key to /etc/nginx/ and add to NGINX:

ssl_dhparam dhparam.pem;

7.2 – Create the configuration file for para

Create the /etc/nginx/mydomain.conf file and add:

server {
    listen 443 ssl http2;

    # SSL configuration
    ssl_certificate  /etc/lego/certificates/; 
    ssl_certificate_key /etc/lego/certificates/; 

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /etc/letsencrypt/live/; 

    # Put here you domain
    root /var/www/miproyecto;
    index index.php;

    # Max file size useful for file uploading 
    client_max_body_size 8M;

     location / {
        # This is cool because no php is touched for static content.
        # include the "?$args" part so non-default permalinks doesn't break when
        # using query string
        try_files $uri $uri/ /index.php?$args;

    location ~ \.php$ {
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        /etc/nginx/fastcgi_params;

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;

7.3 – Reload NGINX configuration

$ sudo service nginx reload


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.