# Con Nginx Proxy Manager delante [Nginx Proxy Manager](https://nginxproxymanager.com/) es un Nginx con panel web: en vez de escribir archivos de configuración a mano, se dan de alta los dominios desde un formulario y él pide los certificados de Let's Encrypt y los renueva solo. Se suele montar como contenedor y hace de puerta única para todo lo que se publica desde una red. > **Ojo con la abreviatura.** En este proyecto `npm` es el gestor de paquetes de > Node, el de `npm run dev`. No tienen nada que ver, así que aquí el proxy se > escribe siempre con el nombre entero. Este es el montaje cuando quien recibe del exterior no es el Nginx de la propia máquina, sino un **Nginx Proxy Manager** en otro sitio de la red: ``` internet → router (80, 443) → Nginx Proxy Manager → 192.168.18.171:3000 → Node ``` Con Proxy Manager delante, **el Nginx de la máquina de la web sobra**. Se puede dejar instalado sin más, pero no tiene que estar en medio: `adapter-node` ya sirve los estáticos con sus cabeceras de caché correctas, y meter un segundo proxy solo añade un salto y complica el recuento de direcciones IP, que sí importa (ver más abajo). ## 1. DNS, en Hostinger Hoy el dominio apunta al alojamiento del registrador. Hay que cambiar **dos registros** y **no tocar los demás**: | Acción | Tipo | Nombre | Contenido | | ---------- | ------- | ------ | --------------------------------- | | **Borrar** | `ALIAS` | `@` | `senzapaura.es.cdn.hstgr.net` | | **Crear** | `A` | `@` | `89.46.247.16` | | **Borrar** | `CNAME` | `www` | `www.senzapaura.es.cdn.hstgr.net` | | **Crear** | `A` | `www` | `89.46.247.16` | **Lo que NO se toca, bajo ningún concepto:** - Los dos `MX` a `mx1/mx2.titan.email` — son el correo del dominio. - El `TXT` de `@` con `v=spf1 include:spf.titan.email ~all` — sin él, el correo que se envía desde el dominio acaba en spam. - El `TXT` de `titan1._domainkey` — la firma DKIM de ese mismo correo. Borrar cualquiera de esos tres deja el correo del dominio inservible, y el síntoma aparece días después, cuando alguien no recibe algo. El registro `A` de `ftp` (`89.116.53.14`) es del alojamiento antiguo. No estorba; se puede borrar cuando se abandone del todo. Con TTL de 300 segundos el cambio se ve en cinco minutos. Comprobación: ```sh dig +short senzapaura.es @1.1.1.1 # tiene que decir 89.46.247.16 dig +short www.senzapaura.es @1.1.1.1 ``` ## 2. Router Redirigir al equipo donde corre Proxy Manager: ``` 80 TCP → :80 443 TCP → :443 ``` El 80 hace falta aunque todo vaya por HTTPS: es por donde Let's Encrypt hace su comprobación. ## 3. El proxy, en Proxy Manager **Hosts → Proxy Hosts → Add Proxy Host** | Campo | Valor | | --------------------- | ------------------------------------ | | Domain Names | `senzapaura.es`, `www.senzapaura.es` | | Scheme | `http` | | Forward Hostname / IP | `192.168.18.171` | | Forward Port | `3000` | | Cache Assets | apagado | | Block Common Exploits | encendido | | Websockets Support | apagado | **«Cache Assets» apagado** a propósito: SvelteKit ya manda `Cache-Control` bien puesto —eterno para lo que lleva huella en el nombre, corto para lo demás—, y una caché por encima que no distinga las dos cosas acaba sirviendo una versión vieja de la web después de un despliegue. En la pestaña **SSL**: «Request a new SSL Certificate», con **Force SSL** y **HTTP/2** encendidos. En **Advanced**, nada. En particular, no hace falta tocar las cabeceras: Proxy Manager ya manda `X-Forwarded-For`, `X-Forwarded-Proto` y `X-Forwarded-Host`. ## 4. El `.env` del servidor Dos variables, y las dos importan: ```sh ORIGIN=https://senzapaura.es ADDRESS_HEADER=X-Forwarded-For XFF_DEPTH=1 ``` **`ORIGIN`** es el error más fácil de cometer y el más desconcertante: sin él, SvelteKit rechaza todos los formularios con un 403 por comprobación de origen. La web se ve perfectamente y nada funciona. **`ADDRESS_HEADER` y `XFF_DEPTH`** son menos evidentes y hacen falta igual. Sin ellos, `getClientAddress()` devuelve la IP del proxy, no la de quien pide. Y esa función es la que usa el limitador del formulario de acceso: con todas las peticiones pareciendo venir de la misma dirección, **el límite salta con una sola persona insistiendo** y nadie más puede pedir su código. `XFF_DEPTH=1` porque hay **un** proxy entre internet y Node. Si algún día se mete otro delante —un Cloudflare, por ejemplo—, hay que subirlo a 2: la cuenta es desde el final de la cadena hacia atrás, y equivocarla deja la IP a merced de quien mande su propia cabecera. Después de tocar el `.env`: ```sh sudo systemctl restart senzapaura ``` ## 5. Y antes que todo lo anterior Que el servicio exista y esté arrancado, que es lo que hoy falta: ```sh sudo bash /var/www/senzapaura/despliegue/instalar.sh ``` Comprobación desde cualquier máquina de la red, sin pasar por el proxy: ```sh curl -I http://192.168.18.171:3000/ ``` Si eso no contesta 200, el problema está en el servidor y no en el DNS ni en Proxy Manager, y es ahí donde hay que mirar: ```sh journalctl -u senzapaura -n 50 --no-pager ``` ## El portón de «muy pronto» Mientras la web no esté abierta al público, en el `.env` del servidor: ```sh PROXIMAMENTE=1 PROXIMAMENTE_PERMITIDAS=89.46.247.16 ``` Esa dirección es la IP pública fija de la línea —contratada como fija, no depende de renovaciones—, así que la lista no hay que revisarla. Y ahí está lo que despista: **hace falta ponerla aunque estés en casa.** La regla «la red local entra siempre» no sirve para esto. Cuando desde la propia red se pide `senzapaura.es`, el nombre resuelve a la IP pública, la petición sale al router y vuelve, y el router la reescribe: al proxy le llega como `89.46.247.16`, no como `192.168.18.x`. Es NAT de retorno, y lo hacen casi todos los routers domésticos. Sin la IP pública en la lista, verías tu propia página de espera en tu propio ordenador y no habría forma de entender por qué. Se comprueba en el registro del proxy: ```sh tail -3 /data/logs/proxy-host-5_access.log # [Client 89.46.247.16] ``` De paso, algo que conviene saber que funciona: mandar a mano un `X-Forwarded-For: 8.8.8.8` **no abre el portón**. El proxy añade la dirección real al final de la cabecera y `XFF_DEPTH=1` es la que se lee. Por eso el número tiene que ser exacto: si algún día se mete otro proxy delante y no se sube a 2, la dirección pasa a ser la que mande quien pide. ## Si el operador bloquea el 80 y el 443 No es el caso aquí: la línea tiene IP pública fija contratada y los puertos 80 y 443 llegan. Queda escrito por si algún día se mueve el montaje a otra conexión, porque el síntoma es de los que se confunden con un fallo de configuración: el DNS resuelve bien, desde dentro de casa se ve, y desde fuera —desde los datos del móvil, por ejemplo— no responde nada. Si eso pasara, hay dos salidas: pedir al operador la IP pública sin filtrar, o montar un túnel —Cloudflare Tunnel es lo más directo— que sale desde la red hacia fuera y no necesita ningún puerto abierto.