5.4 KiB
Con Nginx Proxy Manager delante
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 NPM 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
MXamx1/mx2.titan.email— son el correo del dominio. - El
TXTde@conv=spf1 include:spf.titan.email ~all— sin él, el correo que se envía desde el dominio acaba en spam. - El
TXTdetitan1._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:
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 NPM:
80 TCP → <IP de NPM>:80
443 TCP → <IP de NPM>:443
El 80 hace falta aunque todo vaya por HTTPS: es por donde Let's Encrypt hace su comprobación.
3. El proxy, en NPM
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: NPM ya
manda X-Forwarded-For, X-Forwarded-Proto y X-Forwarded-Host.
4. El .env del servidor
Dos variables, y las dos importan:
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:
sudo systemctl restart senzapaura
5. Y antes que todo lo anterior
Que el servicio exista y esté arrancado, que es lo que hoy falta:
sudo bash /var/www/senzapaura/despliegue/instalar.sh
Comprobación desde cualquier máquina de la red, sin pasar por el proxy:
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 NPM, y es ahí donde hay que mirar:
journalctl -u senzapaura -n 50 --no-pager
Si el operador bloquea el 80 y el 443
Avatel es fibra residencial, y ahí es habitual encontrarse los puertos de entrada cerrados o direcciones compartidas entre varios clientes (CGNAT). El síntoma es claro: el DNS resuelve bien, desde dentro de casa se ve, y desde fuera —desde datos del móvil, por ejemplo— no responde nada.
Si pasa, hay dos salidas: pedirles 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. Con túnel, el paso 2 sobra y el certificado lo pone Cloudflare.