LGM-OS documentación

Dominio propio, certificado y proxy inverso.

Publicar el NAS en internet (acceso externo)

Esta guía convierte tu NAS en tu nube: un nombre propio (micasa.duckdns.org), un certificado válido y acceso desde cualquier sitio sin avisos del navegador. Como efecto secundario, la interfaz se puede instalar como aplicación (PWA): con certificado autofirmado el navegador limita el service worker y con uno válido no.

El camino son cuatro pasos, en este orden:

  1. Abrir 80 y 443 en el router (y solo esos).
  2. Un nombre de dominio que siga a tu IP (DDNS).
  3. Emitir el certificado de Let's Encrypt.
  4. Publicar el panel y las apps con el proxy inverso.
Publicar el NAS es el cambio que más superficie de ataque añade en toda su vida útil. La sección Seguridad no es un apéndice: léela antes de abrir el primer puerto.

Cómo queda montado

Internet ──► router ──► NAS · Apache ──┬──► 127.0.0.1:5000   panel de LGM-OS
             80 y 443    :443 TLS      ├──► 127.0.0.1:8096   Jellyfin
                         :80 redirige  └──► 127.0.0.1:8080   Nextcloud

Apache es el único que escucha desde fuera: termina el TLS con el certificado de Let's Encrypt y reenvía a cada servicio por 127.0.0.1. Ni el puerto del panel (5000) ni los de las apps salen del NAS.

1. Antes de empezar

  • IP fija para el NAS en tu red: reserva DHCP en el router o IP estática en Panel de control → Red. Si el NAS cambia de IP, el reenvío de puertos deja de apuntar a él.
  • IP pública de verdad (sin CGNAT). Compruébalo así:
curl -s https://api.ipify.org; echo      # IP con la que te ve internet

Compara ese valor con la IP WAN que muestra tu router. Si no coinciden, o si la del router está en el rango 100.64.0.0100.127.255.255, estás detrás de CGNAT: el reenvío de puertos no funcionará hagas lo que hagas. Pide a tu operador una IP pública (suele ser gratis y basta con solicitarla) o usa una VPN/túnel.

  • Un nombre de dominio: uno propio, o uno gratuito con DDNS (paso 3).

2. Puertos del router: 80 y 443, nada más

Puerto externoProtocoloDestinoPara qué
80TCPIP-del-NAS:80Validación del certificado (HTTP-01) y redirección a https
443TCPIP-del-NAS:443Todo el tráfico real, ya cifrado

El 80 no es opcional aunque no quieras servir nada sin cifrar: Let's Encrypt comprueba que el dominio es tuyo pidiendo un fichero por el puerto 80, y sin esa comprobación no hay certificado. Lo que sí conviene es que el 80 solo redirija al 443.

Por qué NO se abre el 5000

El 5000 es el puerto del panel. Publicarlo es un error aunque parezca el camino corto:

  • Sirve el certificado autofirmado, así que el navegador avisará siempre y acabarás acostumbrándote a saltarte avisos de certificado — que es justo lo que hace viable un ataque de intermediario contra ti.
  • Expone la API de administración completa directamente, sin las cabeceras, la redirección ni el filtrado que aplica el proxy delante.
  • Con certificado no válido la PWA queda coja y algunas funciones del navegador se desactivan.

Con el proxy inverso entras al panel en https://micasa.duckdns.org (puerto 443, con certificado válido) y el 5000 sigue escuchando solo dentro del NAS, que es donde debe estar.

Tampoco abras 445 (SMB), 2049 (NFS), 3389 ni, salvo que sepas muy bien lo que haces, el 22 (SSH). Son protocolos pensados para la red local; SMB expuesto a internet es la puerta por la que entra la mayoría del ransomware doméstico.

El cortafuegos del NAS también cuenta

Si tienes el cortafuegos activado (Panel de Control → Seguridad → Firewall), por defecto solo deja pasar el panel y SSH: aunque el router reenvíe, Apache no recibirá nada. Añade dos reglas y no toques el origen (deben poder entrar desde cualquier IP):

AcciónProtocoloPuertoDescripción
Permitirtcp80Let's Encrypt y redirección
Permitirtcp443Acceso externo https

3. DDNS con DuckDNS, paso a paso

Casi ningún operador doméstico da IP fija: cambia cada pocos días o en cada reinicio del router. Un servicio de DNS dinámico mantiene el nombre apuntando a la IP actual. DuckDNS es gratuito, no pide tarjeta y funciona bien.

  1. Entra en https://www.duckdns.org y pulsa uno de los botones sign in with (Google, GitHub, Reddit…). No creas contraseña nueva: usa la cuenta que ya tienes.
  2. En el recuadro add domain escribe el nombre que quieras (por ejemplo micasa) y pulsa add domain. Tu dominio es micasa.duckdns.org.
  3. Arriba de la página verás token: xxxxxxxx-xxxx-…. Cópialo. Ese token es la contraseña de tu dominio: no lo compartas ni lo dejes visible en capturas de pantalla.
  4. En el NAS: Panel de Control → Acceso remoto → Acceso externo → *Dominio dinámico (DDNS)*. Elige el proveedor DuckDNS, escribe el dominio completo (micasa.duckdns.org), pega el token y deja la frecuencia por defecto (admite de 5 a 1440 minutos; por debajo de 5 los proveedores empiezan a rechazar peticiones). Activa el interruptor y guarda; con «Actualizar ahora» compruebas al momento que el token vale. El panel muestra la última IP publicada y el error de la última actualización si lo hubo. Los otros proveedores admitidos son Cloudflare (token de API con permiso Zone · DNS · Edit) y No-IP (clave de la sección Dynamic DNS).
  5. Comprueba que resuelve (desde el NAS, o nslookup desde Windows):
getent hosts micasa.duckdns.org      # debe devolver tu IP pública
curl -s https://api.ipify.org; echo  # ...la misma que esta

Si prefieres no depender del NAS para esto, mira si tu router trae cliente DDNS con DuckDNS: actualiza la IP aunque el NAS esté apagado, que es más robusto. La llamada, por si la necesitas en un script o para forzar una actualización manual, es:

curl -s "https://www.duckdns.org/update?domains=micasa&token=TU-TOKEN&ip="
# responde OK (actualizado) o KO (dominio o token incorrectos)

El parámetro ip vacío significa «usa la IP desde la que te estoy llamando».

Dos detalles útiles de DuckDNS: los cambios tardan un par de minutos en propagarse, y cualquier subdominio (pelis.micasa.duckdns.org) resuelve a la misma IP sin configurar nada — es lo que permite publicar varias apps por nombre (paso 5).

Con dominio propio el paso 3 es equivalente: apunta un registro A a tu IP pública (o usa el DDNS de tu proveedor de DNS) y sigue igual desde el paso 4.

4. Emitir el certificado

Requisitos, los tres a la vez: el dominio resuelve a tu IP pública, el puerto 80 llega al NAS y Apache está en marcha. Antes de emitir nada, comprueba desde fuera de tu red (datos móviles del teléfono, no wifi de casa) que http://micasa.duckdns.org responde algo —aunque sea la página por defecto de Apache—. Si eso no funciona, el certificado tampoco.

Desde la interfaz: Panel de Control → Acceso remoto → Acceso externoCertificado. Escribe el dominio, un correo de contacto (Let's Encrypt lo usa solo para avisarte si un certificado va a caducar sin renovarse), acepta las condiciones y pulsa Emitir certificado. Cuando esté emitido, Usar en el panel hace que la propia interfaz lo sirva: se reinicia unos segundos y vuelve por https con tu dominio, sin avisos.

El equivalente por consola, si prefieres verlo por dentro:

sudo certbot --apache -d micasa.duckdns.org -m tu@correo --agree-tos --no-eff-email

Si el proxy inverso ya lo gestionas desde el panel, usa certbot certonly --apache … en su lugar: --apache a secas reescribe los vhosts para añadir el TLS y pisaría los que genera el panel. Con certonly solo se emite el certificado y la configuración la sigue llevando el panel.

Qué debes saber después:

  • Los ficheros quedan en /etc/letsencrypt/live/micasa.duckdns.org/ (fullchain.pem y privkey.pem). No los muevas: certbot los sustituye al renovar.
  • Caducan a los 90 días y se renuevan solos. El paquete instala un temporizador; compruébalo con systemctl list-timers certbot.timer y ensáyalo con sudo certbot renew --dry-run.
  • Let's Encrypt limita los intentos fallidos (5 por hora y dominio). Si falla, arregla la causa antes de reintentar; insistir en bucle te dejará sin poder emitir durante un rato. Para pruebas usa --dry-run.

Si emitiste el certificado a mano con certbot, el panel no se entera: seguirá con el autofirmado en el 5000 y la copia que hagas se quedará vieja en cuanto certbot renueve. Este enganche de despliegue lo mantiene al día (certbot lo ejecuta en cada renovación efectiva):

sudo tee /etc/letsencrypt/renewal-hooks/deploy/10-lgm-os.sh >/dev/null <<'EOF'
#!/bin/sh
# certbot ejecuta este script en cada renovación efectiva.
D=micasa.duckdns.org
cp "/etc/letsencrypt/live/$D/fullchain.pem" /etc/nas/tls/cert.pem
cp "/etc/letsencrypt/live/$D/privkey.pem"  /etc/nas/tls/key.pem
chgrp nas /etc/nas/tls/key.pem && chmod 640 /etc/nas/tls/key.pem
systemctl restart nas-backend
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/10-lgm-os.sh

5. Publicar apps por subdominio (proxy inverso)

La idea: un nombre para cada servicio, todos entrando por el 443 y repartidos por Apache según el nombre que pida el navegador.

NombreVa aQué es
micasa.duckdns.org127.0.0.1:5000El panel de LGM-OS
pelis.micasa.duckdns.org127.0.0.1:8096Jellyfin
nube.micasa.duckdns.org127.0.0.1:8080Nextcloud

En Panel de Control → Acceso remoto → Acceso externoProxy inversoNueva regla, con un servicio por regla:

  1. Dominio público: el nombre completo (pelis.micasa.duckdns.org).
  2. Host y puerto de destino: normalmente 127.0.0.1 y el puerto de la app. El desplegable de contenedores en marcha los rellena por ti; si la app no publica puerto, escríbelos a mano.
  3. Redirigir HTTP a HTTPS: déjalo activado. Quien escriba el nombre sin https:// acabará igualmente en la conexión cifrada.
  4. Usar el certificado gestionado: activado si ese nombre está cubierto por el certificado emitido en el paso 4.
  5. Regla activa: puedes dejarla desactivada y publicarla más tarde sin borrarla.

Al guardar, el panel escribe el vhost y recarga Apache. Los WebSockets funcionan sin tocar nada (el instalador deja proxy_wstunnel habilitado); es lo que necesitan las terminales web, los logs en vivo, Home Assistant o code-server para no quedarse «conectando» eternamente. Dos condiciones por cada nombre:

  • Que resuelva: con DuckDNS los subdominios funcionan solos; con dominio propio crea un registro CNAME (o A) para cada uno.
  • Que tenga certificado: la validación HTTP-01 emite por nombre concreto, así que emite también el certificado del subdominio (o añádelo al existente con otro -d). Un certificado comodín *.midominio exige validación DNS-01, que esta guía no cubre.

Y una regla que conviene repetir: los puertos de las apps no se abren en el router. El proxy llega a ellos por 127.0.0.1. Publicar por proxy y además abrir el puerto directo es dejar la puerta de atrás abierta al lado de la buena.

6. Seguridad (léelo antes de tocar el router)

Mientras el NAS solo estaba en tu red, un fallo de configuración lo veía tu familia. Desde que lo publicas, lo ve un escáner automático en cuestión de horas: no es una exageración, los bots prueban /login de cualquier IP con el 443 abierto. Esto es lo mínimo:

  • Activa 2FA ya: Panel de Control → Seguridad → Cuenta y 2FA. Sin segundo factor, lo único entre internet y todos tus datos es una contraseña.
  • Pasa el Asesor de seguridad (Panel de Control → Seguridad) y resuelve sus avisos. Es el resumen honesto de cómo está el equipo; no publiques con avisos críticos abiertos.
  • Bloqueo de IPs activado (Seguridad → Bloqueo de IPs). El panel ya limita a 10 intentos por minuto y bloquea la cuenta tras 5 fallos, pero el bloqueo por IP es lo que corta el escaneo de raíz.
  • Cortafuegos activado con solo 80 y 443 abiertos hacia fuera.
  • Contraseñas largas y únicas, en especial la del administrador. Para quien solo consulte, crea usuarios con rol viewer.
  • Actualiza: Panel de control → Actualizar LGM-OS (apt) y la actualización del panel. Un NAS publicado y sin actualizar es cuestión de tiempo, no de suerte.
  • Copias de seguridad, y al menos una fuera de línea. Publicar multiplica el riesgo de ransomware, y una copia conectada se cifra con el resto. Ver disaster-recovery.md.
  • Mira la Auditoría y los Usuarios conectados de vez en cuando: ahí verás los intentos de acceso y desde qué IP.
  • Publica lo justo. Si lo que quieres es ver tus películas fuera de casa, publica Jellyfin y administra el panel desde casa. Cada nombre publicado es una puerta más.

Y la comparación honesta: lo más seguro sigue siendo no publicar nada. Una VPN (WireGuard) en el router te da acceso a todo el NAS sin exponer un solo servicio a internet, a cambio de tener que conectar la VPN en cada dispositivo. LGM-OS todavía no incluye servidor VPN propio; si tu router lo trae, para uso personal es la mejor opción. Publicar con proxy y certificado es la opción correcta cuando necesitas compartir con gente que no va a instalarse una VPN.

7. Si algo no funciona

SíntomaCausa habitualQué comprobar
El dominio no resuelveEl DDNS no ha actualizadogetent hosts micasa.duckdns.org; token correcto; espera unos minutos
Resuelve, pero desde fuera no conecta (desde casa sí)Puertos sin reenviar, o CGNATPrueba con datos móviles; revisa el reenvío 80/443; compara IP del router con api.ipify.org
certbot: Timeout during connect o challenge failedEl puerto 80 no llega al NASReenvío del 80, regla del cortafuegos, y si tu operador bloquea el 80 (algunos lo hacen)
502 / 503 al abrir un subdominioLa app no está levantada o el puerto destino es otrodocker ps, Centro de Paquetes, sudo tail -f /var/log/apache2/error.log
La app carga pero se queda «conectando»Faltan los WebSockets`apache2ctl -M \grep wstunnel; si no aparece: sudo a2enmod proxy_wstunnel && sudo systemctl reload apache2`
El navegador avisa del certificadoEstás entrando por el 5000, o ese nombre no tiene certificadoEntra por https://micasa.duckdns.org (443); sudo certbot certificates
Por VPN llegas a todo menos al panelEl tamaño de paquete del túnel (MTU) no cabe por la red móvilEn la app de WireGuard del cliente, en [Interface], pon MTU = 1280 (los clientes creados con LGM-OS ya lo traen)

Por la VPN se ve todo menos el panel

Desconcierta porque parece que el NAS se protege de ti: el móvil dice «conectado», el ping va, entras a los demás equipos de casa… y el panel da no se puede acceder a este sitio web.

No es el cortafuegos ni la licencia: es el MTU. Un túnel WireGuard sin MTU declarado usa 1420 bytes, que sobra por fibra pero no cabe por 4G/5G (la red móvil y el CGNAT se quedan con parte del paquete). Los paquetes pequeños pasan —de ahí que el ping y casi todo funcionen— y los llenos se pierden en silencio. El panel es justo lo que viaja en paquetes llenos: el saludo TLS con su certificado y luego la interfaz entera.

Los clientes que crea LGM-OS ya salen con MTU = 1280, el mínimo que internet garantiza. Si tu cliente es de antes de esa versión, no hace falta rehacerlo: edita la conexión en la app de WireGuard y añade esa línea en [Interface].

Comandos de diagnóstico:

sudo apachectl configtest              # ¿la configuración de Apache es válida?
sudo systemctl status apache2
sudo journalctl -u apache2 -n 50
sudo tail -f /var/log/apache2/error.log
sudo certbot certificates              # certificados emitidos y su caducidad

Los módulos de Apache que necesita el proxy (proxy, proxy_http, proxy_wstunnel, headers, ssl, rewrite) los habilitan deploy/install.sh y deploy/update.sh. Para verificarlos:

apache2ctl -M | grep -E 'proxy|headers|ssl|rewrite'