Estaba mal hecho y el síntoma era el `if` sobre `/admin` que acabó metido en el
layout de la web pública: la web sabiendo que existe el panel, al revés de como
debe ser.
Ahora son dos aplicaciones del mismo repositorio. Lo que las separa son tres
líneas de `vite.config.ts`: con `APP=panel`, las rutas salen de
`src/panel/rutas`, los hooks de `src/panel/hooks.server.ts` y el resultado va a
`build-panel/`. El servidor público se compila sin las rutas del panel, así que
en `senzapaura.es` no es que `/admin` esté protegido: no existe, y hay una
prueba que lo comprueba pidiéndolo.
Comparten `src/lib` —esquema, consultas, acceso—, que es lo que evita mantener
las migraciones por duplicado. Para que eso funcione, dos cosas que resolvían
rutas del sitio salen de en medio: la navegación, a `$lib/navegacion`, y los
tipos ambientales, que ahora son dos porque el `PageData` del sitio lleva
carrito y favoritos y el del panel no.
El precio de otro dominio es que el panel necesita su propia página de entrar:
la cookie se emite para el host y no para el dominio padre, que es justo lo que
hace que la sesión del panel no viaje en las peticiones de la web. Usa el mismo
código de `$lib/server/auth`, con una diferencia: solo manda código a una cuenta
que ya administre, y contesta lo mismo exista o no. Si dijera «esa cuenta no
administra», el formulario sería una forma cómoda de averiguar cuál sí.
Y con dominio propio, el 404 de ayer pasa a ser un 403 con el motivo escrito:
esconder el panel de quien ya está en `admin.senzapaura.es` no engaña a nadie, y
a esa rama solo llega alguien que administraba y ha dejado de administrar.
Dos servidores en las pruebas, uno por proyecto, con su `baseURL`: una prueba
del panel no puede pedir por accidente una página del sitio.
Aparte, la prueba de contacto otra vez. El arreglo de ayer no valía —comprobar
que el texto está escrito no impide que lo borren un instante después—, así que
el layout marca con `data-hidratado` el momento en que Svelte toma el control y
la prueba espera a eso. Quince pasadas con cuatro trabajadores, sin un fallo.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La regla de que la red local entra siempre no sirve para el porton, y es
lo que mas despista: una peticion al dominio desde la propia red sale al
router y vuelve reescrita, asi que al proxy le llega con la IP publica.
Sin esa direccion en la lista, uno ve su propia pagina de espera en su
propio ordenador y no hay forma de entender por que.
La IP es fija y contratada, asi que la lista no hay que revisarla.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
En este repositorio npm es el gestor de paquetes de Node, el de npm run
dev. Abreviar Nginx Proxy Manager igual en un documento de despliegue
confunde justo a quien lo lee para montar el servidor.
De paso, el documento explica que es antes de decir donde tocarlo.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El proxy no lo hace el Nginx de la maquina de la web, sino un Nginx
Proxy Manager en otro sitio de la red. Con eso delante, el Nginx local
sobra: adapter-node ya sirve los estaticos con sus cabeceras de cache, y
un segundo salto solo complica el recuento de IPs.
Y ese recuento importa mas de lo que parece. Sin ADDRESS_HEADER y
XFF_DEPTH, getClientAddress() devuelve la IP del proxy: el limitador del
formulario de acceso cuenta por direccion, asi que con todas las
peticiones pareciendo venir del mismo sitio salta con una sola persona
insistiendo y nadie mas puede pedir su codigo.
El documento incluye que registros de DNS cambiar y, sobre todo, cuales
no tocar: los MX, el SPF y el DKIM son el correo del dominio, y borrar
cualquiera de ellos da un sintoma que aparece dias despues.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El servicio de systemd nunca llegó a instalarse y el sitio de fábrica de
Nginx seguía puesto: es él quien contesta a quien entra por la IP, así
que se veía su bienvenida aunque nuestro sitio estuviera bien
configurado.
`instalar.sh` hace las tres cosas que el despliegue normal no puede hacer
por sí solo —poner el unit, poner el sitio, quitar el de fábrica—, es
idempotente, y comprueba al final que Node y Nginx contestan de verdad en
vez de dar por hecho que sí.
El script va dentro de `despliegue/`, que ahora se sube con el resto: la
vez anterior remití a copiar de una ruta del servidor donde ese archivo
no estaba.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cambia las referencias al dominio de trabajo: la URL canónica, los correos
de los textos legales, las direcciones de retorno de Google y Facebook, y
lo que espera la suite.
El `robots.txt` pasa de archivo estático a ruta generada. Llevaba el
dominio escrito a mano y se quedó anunciando el anterior: un mapa del
sitio mal anunciado no da ningún error, simplemente no lo encuentra
nadie. Ahora sale de `site.url`, igual que el mapa y las etiquetas de
cada página. De paso deja fuera del rastreo lo que depende de quién mira
—cuenta, carrito, favoritos, entrar, descargas—, que no es contenido.
Y el Nginx queda listo para el dominio, con los tres pasos que hay que
dar fuera del servidor: los registros A a 89.46.247.16, la redirección de
los puertos 80 y 443 a 192.168.18.171, y Certbot.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Los botones dejan de ser cápsulas y las tarjetas pierden la mitad del canto. De
paso se ordena el sistema: había tres radios sueltos y una píldora de 999px
repetida en quince archivos, y quedan dos —uno para lo que se pulsa, otro para
las superficies—. Los botones de icono suelto siguen redondos, que ahí sí tiene
sentido.
Las fichas del taller no usaban la tarjeta compartida: tenían su propio borde,
su propio canto y su propio hover, así que se veían de otra familia que las de
música. Ahora usan `.tarjeta`, con el mismo reflejo bajo el puntero y el mismo
subrayado.
Y la portada arranca en el borde de la ventana, con la cabecera flotando encima.
Para eso la cabecera pasa a medir su propio alto y publicarlo: estaba escrito a
mano en 4,75rem cuando mide 68px, y todo lo que dependía de ese número —el salto
a un ancla, las barras laterales pegajosas— quedaba desplazado.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Lo escribí suponiendo, lo probé a mano contra la máquina y las suposiciones
fallaron en dos sitios:
- `rsync` no está en la máquina de desarrollo. Git Bash no lo trae. Se sube con
`tar` por SSH, que sí está en los dos lados.
- `npm ci` no funciona en el servidor. Tiene salida a internet, pero su DNS
resuelve unos dominios y otros no: `google.com` sí, `registry.npmjs.org` no.
Las dependencias se resuelven aquí y se suben instaladas. Los tres paquetes de
producción son JavaScript puro, así que viajan tal cual; el script comprueba
que sigan siéndolo y se para si aparece un binario de plataforma.
Comprobado en el servidor y no solo en el papel: la web arranca, las siete rutas
que probé devuelven 200, la muestra de audio sale entera y la ficha lee las
valoraciones de Postgres por el bucle local.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
El servidor del usuario lleva Nginx, así que el montaje es proxy inverso por
delante y Node por detrás. La web no son archivos estáticos —cada página se
genera sabiendo quién la pide—, de modo que hace falta un proceso vivo y un
servicio que lo mantenga.
Nginx sirve además los estáticos por su cuenta: lo de `_app/immutable` lleva el
hash del contenido en el nombre y se cachea para siempre, así que abrir la web
deja de despertar a Node para devolver un CSS. Lo que no puede tocar son las
descargas: comprueban la compra antes de entregar el archivo, y el audio
completo vive fuera de `build/` para que no haya forma de pedirlo por URL.
El script construye aquí y sube el resultado, en vez de compilar en el servidor:
allí no hacen falta ni Vite ni el compilador, solo Node y tres paquetes. Las
migraciones también se lanzan desde aquí, porque `drizzle-kit` es herramienta de
desarrollo y en producción se instala con `--omit=dev`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>