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.
Features
- 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:
- https://github.com/go-acme/lego
- https://go-acme.github.io/lego/
Related content:
- How to install Let’s Encrypt SSL in Debian?
- How to install and configure NGINX as reverse proxy
- How to install NGINX on NetBSD?
- How to install NGINX on Alpine Linux?
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 -# https://github.com/go-acme/lego/releases/download/v4.10.2/lego_v4.10.2_linux_amd64.tar.gz
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
NAME:
lego - Let's Encrypt client written in Go
USAGE:
lego [global options] command [command options] [arguments...]
VERSION:
4.10.2
COMMANDS:
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
GLOBAL OPTIONS:
--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: "https://acme-v02.api.letsencrypt.org/directory")
--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;
server_name midominio.com;
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 http://mydomain.com/.well-known/acme-challenge/ok.txt
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=https://acme-staging-v02.api.letsencrypt.org/directory --accept-tos -m myemail@mydomain.com -d mydomain.com -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 myemail@mydomain.com -d mydomain.com -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/
#!/bin/sh
lego --accept-tos -m micorreo@midomnio.com -d midominio.com -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;
Add
# 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 mydomain.com
Create the /etc/nginx/mydomain.conf
file and add:
server {
listen 443 ssl http2;
# SSL configuration
ssl_certificate /etc/lego/certificates/midominio.com.cert;
ssl_certificate_key /etc/lego/certificates/midominio.com.key;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/letsencrypt/live/midominio.com.pem;
# Put here you domain
#
server_name midominio.com www.midominio.com;
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_pass 127.0.0.1:9000;
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