Vamos a configurar nginx para publicar contenido por “HTTP/HTTPS”, con un certificado SSL/TLS gratuito de la autoridad certificadora let’s encrypt. Para administrar y automatizar la renovación de los certificados, usaremos la herramienta certbot.

Antes de continuar es necesario tener un dominio propio, si vamos a utilizar un host en casa seguramente tengamos una IP dinámic, por lo que hay que asegurarse que nuestro proveedor DNS soporte DDNS. Por suerte hay muchos proveedores gratuitos que soportan clientes con IP dinámic, uno de mis preferidos es duckdns.

El último requisio si queremos ser nuestro propio proveedor, es abrir los puertos 80 (HTTP) y 443 (HTTPS) de nuestro router y redirigirlos a la máquina con nginx.

Instalación de nginx

  • Instalar nginx en distribuciones basadas en debian, es tan sencillo como ejecutar:
$ sudo apt install nginx
  • Una vez instalado, detenemos el servicio:
$ sudo systemctl stop nginx.service
  • Las configuraciones de los distintos sites que sirve nginx se encuentran en el directorio /etc/nginx/sites-available/.
$ ls /etc/nginx/sites-available/
default
  • Para que una configuración de site esté habilitada, hay que crear un enlace simbólico en el directorio **/etc/nginx/sites-enabled/.
$ ls -ls /etc/nginx/sites-enabled/
total 0
0 lrwxrwxrwx 1 root root 34 Mar 18 14:16 default -> /etc/nginx/sites-available/default
  • Deshabilitamos el site default y más adelante crearemos el nuestro.
$ sudo rm /etc/nginx/sites-enabled/default

Configurar nginx para publicar contenido por HTTP

Supongamos que tenemos nuestro contenido estático en el directorio /var/www/miblog, ahora configuramos nginx para servir este contenido por el puerto 80 protocolo HTTP.

  • Creamos el fichero de configuración /etc/nginx/sites-available/miblog.conf, con el siguiente contenido:
server {
    listen 80;
    server_name www.midominio.com midominio.com;
    root /var/www/miblog/;
    location \ {
               try_files $uri $uri/ =404;
    }
    access_log /var/log/nginx/miblog.access.log;
}

Con esta configuración, le estamos diciendo a nginx, que sirva todo el contenido dentro del directorio /var/www/miblog/, solo cuando la petición sea al puerto 80 con el nombre de dominio midominio.com. Cuando alguien pida un contenido que no exista devolverá un 404 y los logs de acceso irán a /var/log/nginx/miblog.access.log.

  • Habilitamos el site para que nginx lo cargue en cada inicio.
$ sudo ln -s /etc/nginx/sites-available/miblog.conf /etc/nginx/sites-enabled/miblog.conf
  • Iniciamos nginx con la nueva configuración del site:
$ sudo systemctl restart nginx.service
$ sudo systemctl enable nginx

Con esto ya tendríamos nginx sirviendo el contenido en http://midominio.com

Instalación de certbot

  • Instalar certbot en distribuciones basadas en debian, es tan sencillo como ejecutar:
$ sudo apt install certbot python-certbot-nginx

Configurar nginx para publicar contenido por HTTPS

  • Ahora empieza la mágia de certbot, el solo es capaz de obtener y configurar el certificado en nuestro site, además comprobará diariamente si va a expirar y lo renovará automáticamente. En el siguiente ejemplo, usaré el dominio lynks.duckdns.org.
$ sudo certbot
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: lynks.duckdns.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
Obtaining a new certificate
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/lynks.duckdns.org.conf

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): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/lynks.duckdns.org.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://lynks.duckdns.org

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=lynks.duckdns.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/lynks.duckdns.org/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/lynks.duckdns.org/privkey.pem
   Your cert will expire on 2021-06-23. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. 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
  • Si preferimos que certbot no se encargue de tocar la configuración del site en nginx, simplemente creamos los certificados así:
$ sudo certbot certonly --standalone -d lynks.duckdns.org -d www.lynks.duckdns.org
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for homeassistant.lynks.duckdns.org
http-01 challenge for lynks.duckdns.org
http-01 challenge for www.lynks.duckdns.org
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/lynks.duckdns.org/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/lynks.duckdns.org/privkey.pem
   Your cert will expire on 2021-06-30. 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
  • Activamos el timer que se encargará de mantener renovados los certificados:
$ sudo systemctl enable certbot.timer
$ sudo systemctl start certbot.timer
$ sudo systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
   Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
   Active: active (waiting) since Thu 2021-04-01 16:24:22 CEST; 27min ago
  Trigger: Fri 2021-04-02 09:30:32 CEST; 16h left
  • Así quedará la configuración de nuestro site:
$ sudo cat /etc/nginx/sites-available/lynks.duckdns.org.conf
server {
    server_name lynks.duckdns.org;
    root /var/www/miblog/;
    location \ {
               try_files $uri $uri/ =404;
    }
    access_log /var/log/nginx/lynks.duckdns.org.access.log;

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/lynks.duckdns.org/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/lynks.duckdns.org/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 = lynks.duckdns.org) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name lynks.duckdns.org;
    return 404; # managed by Certbot
}
  • Reiniciamos nginx para que use nuestra nueva configuración:
$ sudo systemctl restart nginx.service

Con esto ya tendremos un servidor HTTPS con certificado firmado por una autoridad oficial de manera totalmente gratuita, como apunte decir que la configuración que añade certbot, redirige todas las peticiones HTTP a HTTPS.

Administración de los certificados con certbot

  • Listar todos los certificados disponibles:
$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: lynks.duckdns.org
    Domains: lynks.duckdns.org
    Expiry Date: 2021-06-23 17:41:22+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/lynks.duckdns.org/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/lynks.duckdns.org/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  • Eliminar un certificado:
$ sudo certbot delete
Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which certificate(s) would you like to delete?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: lynks.duckdns.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Deleted all files relating to certificate lynks.duckdns.org.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -