fix(versiones-cras): permitir fijar la ruta de instalación y blindar la config de Gitea

Un agente anterior a 1.1.0 no reporta su install_path, así que el panel caía al
default de plataforma y ACTUALIZAR abortaba cuando la instalación vivía en otra
carpeta (p. ej. C:\Aduanasoft\CloudRestoreAS-win). Era un huevo-y-gallina: la
ruta se empieza a reportar en 1.1.x, que es justo lo que no se podía instalar.

Se agrega la captura manual de la ruta por servidor. No hace falta esquema nuevo
ni lógica de resolución nueva: el upsert del estado ya usa
install_path = COALESCE(EXCLUDED.install_path, actual), así que el valor
capturado sobrevive los reportes sin ruta del agente viejo, y resolveInstallPath
y cras-verify ya leen esa misma columna. Cuando el servidor quede en 1.1.x su
propio reporte lo sustituye por la ruta real.

De paso, dos fallos de configuración que costaron el diagnóstico:

- GITEA_TOKEN con los `<>` de la plantilla se veía como un 401 opaco de Gitea,
  idéntico al de un token revocado. Se valida la forma antes de llamar, el
  aviso sale al cargar la pantalla y 401 y 403 dejan de colapsar al mismo
  texto. Un rechazo ahora deja línea en los logs: no dejaba ninguna.
- PANEL_PUBLIC_URL sin el puerto apuntaba a otro servicio. Esa URL se siembra
  en el config/.env del destino también al ACTUALIZAR, así que rompería un
  agente que ya reportaba: se avisa y se aborta antes de tocar el servidor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-30 12:16:06 -06:00
parent 14b611c581
commit d570c7dac2
8 changed files with 541 additions and 18 deletions

View File

@@ -80,6 +80,11 @@ CRAS_PACKAGE_NAME=cloudrestoreas
# PAT de Gitea. El panel solo LEE el registro, así que basta el scope `read:package`.
# (El token con `write:package` vive en la máquina de build, no aquí.)
# Sin este token /versiones-cras carga pero avisa que no puede sincronizar.
#
# El valor va DESNUDO: sin los `<>` de una plantilla, sin comillas y sin espacios. Compose los
# pasa literales y Gitea responde 401, indistinguible de un token revocado.
# Y tras cambiarlo hay que RECREAR el contenedor (`docker compose up -d`), no reiniciarlo:
# `environment:` con `${VAR:-}` congela el valor al crearlo y `restart` no relee este archivo.
GITEA_TOKEN=
# Caché local de artefactos. Cada uno pesa ~270 MB y se publican dos por versión, así que la
@@ -88,7 +93,19 @@ GITEA_TOKEN=
CRAS_RELEASES_DIR=./local-cras-releases
CRAS_CACHE_KEEP_VERSIONS=3
# Origen del bind-mount de esa caché en el HOST (docker-compose.prod.yml). Es una ruta del host,
# no del contenedor, así que debe existir EN EL SISTEMA DEL HOST: en un host Windows
# `C:/Aduanasoft/cras-releases`, en uno Linux `/srv/panel/cras-releases`. Una ruta estilo POSIX
# en un host Windows no falla: Docker la crea dentro de su propia VM, donde nadie la ve ni la
# respalda y consume el disco virtual.
CRAS_RELEASES_HOST_PATH=
# URL con la que el agente instalado reportará al panel. El instalador remoto la siembra en el
# config/.env del servidor destino, así que TIENE que ser alcanzable desde esos servidores (no
# localhost). Si se omite se usa ORIGIN.
#
# DEBE incluir el puerto si el panel no está detrás de un proxy en 443. El panel escucha en 3000,
# y en cpanel-a24 el 443 lo sirve el PHP legado: sin el `:3000` el agente le pediría todo a otro
# servicio y recibiría 404. Se siembra también al ACTUALIZAR, así que una URL mal puesta rompe
# un agente que ya funcionaba. Lo más seguro es dejarla vacía y que tome ORIGIN.
PANEL_PUBLIC_URL=