Uno de los principales problemas al que nos enfrentamos con nuestro Home Lab son los avisos de «sitio web inseguro» al acceder por HTTPS a servicios que utilizan certificados autofirmados.
Sí, ya sé que hay formas de saltarse el aviso y añadir excepciones en el navegador, pero esa es la clave: en el navegador, en ese navegador y en ese dispositivo… Salvo que tengamos un controlador de dominio, una infraestructura PKI y consigamos que los dispositivos confíen en esos certificados. Ciertamente, no es el caso. Esto es para nuestro Home Lab.
Así que me encontré con un vídeo de Wolfgang’s Channel (canal que os recomiendo fuertemente) en el que daba con la clave de todo: usar certificados de Let’s Encrypt. Pero, ¿cómo vamos a usar esos certificados si es nuestra red interna? Los obtendremos con DNS-01, es decir, solo necesitamos verificar que el dominio es nuestro y no es necesario haya un servicio web ahí corriendo.
Requisitos:
- Un dominio (el coste suele rondar los 10 euros/año; merece la pena)
- Cloudflare
- Nginx Proxy Manager
Lo «malo» es que necesitamos un dominio, pero el coste es ridículo si lo comparamos con, por ejemplo, el plan 4K de Netflix. Creo que merece la pena.
Otra desventaja es que tenemos que utilizar Cloudflare para modificar los registros DNS, así que si teníamos montado un DNS interno, tendremos que buscar la forma de mantenerlos sincronizados o utilizar uno de ellos (no lo recomiendo, porque Cloudflare siempre requiere de conexión a Internet).
La verdad es que nunca se me habría ocurrido usar un dominio y Cloudflare para resolver mis direcciones IP privadas.
Cómo instalar Nginx Proxy Manager en Docker
Vamos a Portainer y creamos dos volúmenes: npm-data-volume y npm-letsencrypt-volume.
Para aquellos que se están iniciando con Portainer, tenéis que ir a Volumes y pulsar en Add volume.
Después, lo único que tenemos que hacer es dar un nombre al volumen y pulsar en Create volume.
Ahora, vamos a crear el contenedor. Para ello vamos a Containers y pulsamos en Add container.
Los datos que vamos a utilizar y que debéis rellenar en Portainer para crear el contenedor son los siguientes:
Nombre | nginx-proxy-manager |
Imagen | jc21/nginx-proxy-manager:latest |
Puertos | 80 > 80 81 > 81 443 > 443 |
Volúmenes | /data > npm-data-volume /etc/letsencrypt > npm-letsencrypt-volum |
Acción de reinicio | Unless stopped |
En mi caso, voy a usar el puerto del host 8181 en lugar del 81, ya que utilicé este puerto para la interfaz web de OpenMediaVault. Este es el único puerto que podéis modificar de Nginx Proxy Manager, ya que es el que vamos a utilizar para la interfaz de gestión web. Los puertos 80 y 443 se utilizarán para acceder a las web del proxy inverso.
Así es como se vería la configuración completa en Portainer:
Cuando hayamos terminado de configurar el contenedor, pulsamos en Deploy the container.
Accedemos a la interfaz web de Nginx Proxy Manager usando un navegador en la dirección http://<IP del servidor>:81
. Por defecto, el email es [email protected] y la contraseña es changeme. No os preocupéis, que estos datos los cambiaremos nada más entrar.
¿Y en Cloudflare?
Llega el momento de trabajar con Cloudflare. Vamos a crear dos registros para el dominio que teníamos o habremos adquirido previamente.
Tipo | Nombre | Contenido | Proxy |
A | homelab1 | <IP privada del servidor> | No |
CNAME | *.homelab1 | homelab1.<dominio> | No |
En este caso, mi subdominio se llama «homelab1», pero podéis darle el nombre que más os guste. El subdominio completo sería homelab1.javituinformatico.com.
No pasa nada porque ponga aquí el subdominio porque solo va a ser accesible desde la red interna. De lo contrario, hubiese filtrado algo más la información 😉
El registro A tiene la clara misión de llevarnos al servidor donde hemos instalado Nginx Proxy Manager; mientras que el registro CNAME lo utilizaremos para obtener un certificado wildcard que cubra a homelab1.javituinformatico.com y todos los subdominios que vamos a crear.
Ahora, necesitamos la API token que después utilizaremos en Nginx Proxy Manager. Para ello, vamos a Overview y, en la parte inferior-derecha, encontramos el botón Get your API token.
Pulsamos en Create Token y elegimos Edit zone DNS.
Lo único que tendremos que hacer después es, en la sección Zone Resources, abrir el desplegable que se encuentra junto a Specific zone y elegir el dominio que nos interesa.
Una vez pulsemos en Continuar, aparecerá la API Token y copiaremos el código en un lugar seguro.
Volvemos a Nginx Proxy Manager…
En la UI de Nginx Proxy Manager, vamos a SSL Certificates y hacemos clic en Add SSL Certificate.
Escribimos nuestro dominio (o subdominio, realmente) y el wildcard para todos los subdominios (o sub-subdominios). Como proveedor de DNS, elegimos Cloudflare y cambiamos la API Token por la que hemos obtenido anteriormente.
Si el proceso os da un error, cambiad el tiempo de propagación a 120 segundos.
Llega el momento de crear las entradas para el proxy inverso
En Nginx Proxy Manager, vamos a Hosts > Proxy Hosts, y pulsamos en Add Proxy Host.
Por ejemplo, voy a crear la entrada para el UniFi Controller, que utiliza un certificado autofirmado y siempre suele dar la típica advertencia.
Vamos a darle un nombre de subdominio, por ejemplo, unifi.homelab1.javituinformatico.com. En esquema, elegimos HTTPS. Escribimos la IP del contenedor Docker (en este caso) o del servidor donde esté instalado y el puerto en el que está expuesto el servicio.
Si utilizáis Docker para vuestros servicios, debéis tener en cuenta que el contenedor de Nginx Proxy Manager deberá tener acceso a las subredes de vuestros servicios.
En la pestaña SSL, elegimos el certificado SSL que acabamos de generar y marcamos las casillas Force SSL y HTTP/2 Support.
Pulsamos en Save y probamos que funcione nuestro nuevo subdominio.
Y ahí lo tenemos, nuestro subdominio funcionando con el certificado de Let’s Encrypt sin tener que publicarlo hacia Internet.
Es una buena práctica utilizar un proxy inverso para acceder a nuestros servicios por varios motivos: nos olvidamos de recordar direcciones IP, forzamos una conexión cifrada con el servidor y podemos dejar de exponer los puertos de nuestros contenedores Docker, ya que la conexión se hace utilizando la interfaz interna.