You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
9.9 KiB
252 lines
9.9 KiB
# 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 → <IP de Proxy Manager>:80
|
|
443 TCP → <IP de Proxy Manager>: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 panel, en `admin.senzapaura.es`
|
|
|
|
El panel de administración es **otra aplicación y otro proceso**, del mismo
|
|
repositorio. No cuelga de la web: el servidor público se compila sin sus rutas,
|
|
así que en `senzapaura.es` no existe ninguna dirección que lleve a él.
|
|
|
|
Se compila aparte y escribe en `build-panel/`:
|
|
|
|
```sh
|
|
npm run build # la web → build/
|
|
npm run build:panel # el panel → build-panel/
|
|
```
|
|
|
|
Lo que hay que añadir es lo mismo que para la web, una vez más:
|
|
|
|
1. **DNS**: un registro `A` para `admin`, apuntando a la misma IP.
|
|
2. **Servicio**: una unidad de systemd que arranque `build-panel/index.js` en
|
|
otro puerto —**3001**—, con su propio `.env`.
|
|
3. **Proxy Host**: `admin.senzapaura.es` → `192.168.18.171:3001`, con su
|
|
certificado, «Force SSL» y «HTTP/2», igual que el de la web.
|
|
|
|
El `.env` del panel lleva `ORIGIN=https://admin.senzapaura.es`. **No es un
|
|
detalle**: con el `ORIGIN` de la web, SvelteKit rechaza todos los formularios
|
|
del panel con un 403 y no se puede ni entrar. Para que el alta pueda recibir y
|
|
procesar un máster, ese entorno necesita además:
|
|
|
|
```sh
|
|
BODY_SIZE_LIMIT=260M
|
|
MEDIA_DIR=/var/www/senzapaura/media/audio
|
|
ESCUCHA_DIR=/var/www/senzapaura/media/escucha
|
|
ONDA_DIR=/var/www/senzapaura/static/ondas
|
|
```
|
|
|
|
El proceso del sitio usa las mismas tres rutas. En el Proxy Host de `admin`, el
|
|
campo **Advanced** debe admitir la petición y el tiempo de transcodificación:
|
|
|
|
```nginx
|
|
client_max_body_size 260m;
|
|
proxy_read_timeout 300s;
|
|
```
|
|
|
|
El servidor donde corre el panel necesita `ffmpeg` y `ffprobe`. Si falta alguno,
|
|
el alta se cancela antes de escribir la canción y el panel muestra el motivo.
|
|
|
|
`PROXIMAMENTE` **no se pone aquí**. El portón es de la web pública, y encendido
|
|
en el panel dejaría fuera al administrador justo mientras la web no está
|
|
abierta, que es cuando más falta hace entrar.
|
|
|
|
### Por qué otro dominio y no `/admin`
|
|
|
|
Porque así el servidor que da la cara a internet no lleva dentro el código del
|
|
panel. No es una puerta cerrada: es que ahí no hay puerta. Y de paso, la cookie
|
|
de sesión del panel es de `admin.senzapaura.es` y solo de ahí —no se emite para
|
|
el dominio padre—, así que no viaja en ninguna petición de la web pública.
|
|
|
|
El precio es que el panel tiene su propia página de entrar: una sesión de
|
|
`senzapaura.es` no vale aquí. Usa el mismo código de acceso por correo, con una
|
|
diferencia: **solo manda código a una cuenta que ya administre**, y contesta lo
|
|
mismo exista o no, para que el formulario no sirva para averiguar qué correo
|
|
tiene las llaves.
|
|
|
|
## 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.
|