docs: documentar el instalador de Windows y corregir lo que contradecía al código
README afirmaba que la app no puede correr como servicio de Windows y sugería NSSM, contradiciendo a install.ps1 desde que existe. LEEME.txt solo documentaba el camino manual para Windows, mientras que para Linux ya traía el instalador. BUILD.md gana -UpdateInPlace, las tres garantías al reemplazar el binario y el remedio del token filtrado por UAC. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
25
BUILD.md
25
BUILD.md
@@ -196,6 +196,7 @@ cd CloudRestoreAS
|
|||||||
|
|
||||||
.\install.ps1 -Service # tarea programada ONSTART como SYSTEM (24/7 headless)
|
.\install.ps1 -Service # tarea programada ONSTART como SYSTEM (24/7 headless)
|
||||||
.\install.ps1 -Desktop # arranque al iniciar sesión (tarea ONLOGON de la app)
|
.\install.ps1 -Desktop # arranque al iniciar sesión (tarea ONLOGON de la app)
|
||||||
|
.\install.ps1 -UpdateInPlace # actualiza una instalación existente, conservando su tarea
|
||||||
.\install.ps1 # solo instala + bootstrap
|
.\install.ps1 # solo instala + bootstrap
|
||||||
Get-Help .\install.ps1 -Detailed
|
Get-Help .\install.ps1 -Detailed
|
||||||
```
|
```
|
||||||
@@ -205,6 +206,30 @@ Parámetros: `-Prefix` (default `C:\Aduanasoft\CloudRestoreAS`), `-PanelEnvFile`
|
|||||||
arranque 24/7 se resuelve con una tarea programada, no con NSSM: descargarlo violaría la
|
arranque 24/7 se resuelve con una tarea programada, no con NSSM: descargarlo violaría la
|
||||||
regla de que en el servidor destino no se instala ni se baja nada.
|
regla de que en el servidor destino no se instala ni se baja nada.
|
||||||
|
|
||||||
|
Si la cuenta pertenece a Administradores y aun así se rechaza, el mensaje lo dice explícitamente:
|
||||||
|
es el **token filtrado por UAC**, que es lo que recibe una sesión de OpenSSH. No se arregla
|
||||||
|
cambiando de cuenta sino con `LocalAccountTokenFilterPolicy=1` (DWORD) en
|
||||||
|
`HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System`.
|
||||||
|
|
||||||
|
### Garantías al reemplazar el binario (las mismas en los dos instaladores)
|
||||||
|
|
||||||
|
Reemplazar el binario de un servidor en producción no puede dejarlo sin restaurador:
|
||||||
|
|
||||||
|
1. **No se actúa si hay una restauración en curso** (`Temp\` no vacío): se sale con **75**
|
||||||
|
(`EX_TEMPFAIL`), que el PANEL traduce a "reintenta luego" y no a "falló la instalación".
|
||||||
|
Interrumpirla dejaría ese respaldo vetado en cada escaneo posterior y la base en `SINGLE_USER`.
|
||||||
|
2. **Se respalda el binario anterior** antes de pisarlo (`.CloudRestoreAS.exe.prev`).
|
||||||
|
3. **Se confirma que el agente volvió a arrancar** y, si no, se **revierte** al binario anterior.
|
||||||
|
El respaldo solo se descarta tras esa confirmación.
|
||||||
|
|
||||||
|
`-UpdateInPlace` además no vuelve a registrar la tarea (así no pisa ajustes hechos sobre ella) y
|
||||||
|
se salta el bootstrap: una segunda instancia purgaría el `Temp\` de la que está viva. Es el modo
|
||||||
|
que usa el PANEL para actualizar.
|
||||||
|
|
||||||
|
El arranque headless no depende del entorno de la tarea: `--headless` hace que el binario elija
|
||||||
|
el plugin Qt `offscreen` en cualquier plataforma, que es lo que le permite correr como SYSTEM en
|
||||||
|
la sesión 0, donde no hay escritorio interactivo.
|
||||||
|
|
||||||
> `scripts/dev-setup.ps1` es otra cosa: prepara el entorno de **desarrollo** (Python, venv,
|
> `scripts/dev-setup.ps1` es otra cosa: prepara el entorno de **desarrollo** (Python, venv,
|
||||||
> `requirements.txt`) para correr `python runner.py`. No sirve para desplegar el binario.
|
> `requirements.txt`) para correr `python runner.py`. No sirve para desplegar el binario.
|
||||||
|
|
||||||
|
|||||||
41
CHANGELOG.md
41
CHANGELOG.md
@@ -1,5 +1,46 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [Sin publicar]
|
||||||
|
|
||||||
|
### Instalación y actualización desatendidas en Windows
|
||||||
|
|
||||||
|
El instalador de Windows nunca recibió la maquinaria de actualización segura que sí tiene
|
||||||
|
`install.sh`, y la asimetría se notaba en producción: actualizar desde el PANEL dejaba el
|
||||||
|
servidor sin agente, o fallaba con un error que no correspondía.
|
||||||
|
|
||||||
|
- **`install.ps1 -UpdateInPlace`**: actualiza una instalación existente conservando su tarea
|
||||||
|
programada y su configuración, y sin correr el bootstrap (una segunda instancia purgaría el
|
||||||
|
`Temp\` de la que está viva). Es el modo que usa el PANEL para actualizar.
|
||||||
|
- **No se interrumpe una restauración en curso** (`Temp\` no vacío): sale con **75**
|
||||||
|
(`EX_TEMPFAIL`), que el PANEL traduce a "reintenta luego". Windows no tenía esta guarda y una
|
||||||
|
reinstalación a destiempo se llevaba por delante el respaldo que se estuviera restaurando,
|
||||||
|
dejándolo vetado y la base en `SINGLE_USER`.
|
||||||
|
- **Respaldo y reversión automática**: si el binario nuevo no arranca, se vuelve al anterior.
|
||||||
|
El respaldo solo se descarta tras confirmar que la versión nueva corre.
|
||||||
|
- **Rearranque garantizado en todos los modos.** La detención corría siempre, pero solo
|
||||||
|
`-Service` volvía a arrancar algo: actualizar con `desktop` o `none` mataba el agente y se iba
|
||||||
|
sin dejar señal.
|
||||||
|
- La espera a que el SO libere el `.exe` pasa de 5 s a 30 s con reintentos de la copia: con un
|
||||||
|
antivirus escaneando un onefile de ~270 MB, 5 s se quedaban cortos y la copia abortaba.
|
||||||
|
- Se distingue **"no es administrador"** de **"es administrador con el token filtrado por UAC"**,
|
||||||
|
que es lo que recibe una sesión de OpenSSH. Se veían idénticos y el remedio es el opuesto: el
|
||||||
|
segundo no se arregla cambiando de cuenta sino con `LocalAccountTokenFilterPolicy`.
|
||||||
|
|
||||||
|
### `--headless` ahora funciona en Windows
|
||||||
|
|
||||||
|
`_ensure_qt_platform()` salía de inmediato en `win32`, así que la bandera no hacía nada ahí. La
|
||||||
|
tarea ONSTART corre como SYSTEM en la sesión 0, sin escritorio interactivo, y arrancaba con el
|
||||||
|
plugin Qt `windows` intentando crear una ventana real. En Linux el mismo modo funcionaba porque
|
||||||
|
el unit de systemd fija `QT_QPA_PLATFORM=offscreen` por fuera, y esa asimetría escondió el
|
||||||
|
defecto. Ahora `--headless` fuerza `offscreen` en todas las plataformas y no se muestra ventana.
|
||||||
|
|
||||||
|
### Documentación
|
||||||
|
|
||||||
|
- `README.md` afirmaba que la app no puede correr como servicio de Windows y sugería NSSM, lo
|
||||||
|
que contradecía a `install.ps1` desde que existe. Corregido.
|
||||||
|
- `packaging/LEEME.txt` solo documentaba el camino manual para Windows; ahora incluye el
|
||||||
|
instalador, igual que ya hacía para Linux.
|
||||||
|
|
||||||
## [1.1.0] - 2026-07-29
|
## [1.1.0] - 2026-07-29
|
||||||
|
|
||||||
### Distribución e instalación automatizada vía Gitea + PANEL
|
### Distribución e instalación automatizada vía Gitea + PANEL
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ R: Sí, especifica el nombre o IP del servidor remoto en Configuración → SQL
|
|||||||
R: Sí, la aplicación usa RESTORE FILELISTONLY para detectar todos los archivos lógicos (MDF, LDF, y archivos adicionales). Solo mantiene el archivo principal de datos (.mdf) y de log (.ldf).
|
R: Sí, la aplicación usa RESTORE FILELISTONLY para detectar todos los archivos lógicos (MDF, LDF, y archivos adicionales). Solo mantiene el archivo principal de datos (.mdf) y de log (.ldf).
|
||||||
|
|
||||||
**P: ¿Puedo ejecutar esto como Windows Service?**
|
**P: ¿Puedo ejecutar esto como Windows Service?**
|
||||||
R: No, la aplicación está diseñada como "daemon de usuario" con interfaz gráfica. Para ejecutar como servicio, considera usar NSSM (Non-Sucking Service Manager) para envolver el ejecutable, pero perderás la UI.
|
R: Sí, con `install.ps1 -Service`: registra una tarea programada ONSTART que corre como SYSTEM, sin sesión iniciada y sin UI. **No** se usa NSSM ni ningún envoltorio descargado — el servidor destino no instala ni baja nada, y una tarea programada ya viene en el SO. Requiere PowerShell como Administrador. Ver [BUILD.md](BUILD.md) §6.
|
||||||
|
|
||||||
## 📄 Licencia
|
## 📄 Licencia
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,29 @@ Cerrar la ventana (X) minimiza a la bandeja; la app sigue en ejecucion.
|
|||||||
Para salir por completo: clic derecho en el icono de bandeja -> Salir,
|
Para salir por completo: clic derecho en el icono de bandeja -> Salir,
|
||||||
o menu Archivo -> Salir.
|
o menu Archivo -> Salir.
|
||||||
|
|
||||||
|
-------------------------------------
|
||||||
|
Windows en SERVIDOR (24/7, sin sesion iniciada)
|
||||||
|
-------------------------------------
|
||||||
|
Lo normal es que el PANEL instale y actualice solo, desde Versiones CRAS. Esto es
|
||||||
|
el camino manual, y es lo mismo que el PANEL ejecuta por dentro.
|
||||||
|
|
||||||
|
Opcion A - servicio 24/7 (recomendado en servidor SQL):
|
||||||
|
.\install.ps1 -Service
|
||||||
|
(registra una tarea programada ONSTART que corre como SYSTEM, sin sesion
|
||||||
|
iniciada y sin ventana; ver estado: Get-ScheduledTask -TaskName CloudRestoreAS)
|
||||||
|
Requiere PowerShell como Administrador.
|
||||||
|
|
||||||
|
Opcion B - actualizar una instalacion que ya existe:
|
||||||
|
.\install.ps1 -UpdateInPlace
|
||||||
|
(reemplaza el binario conservando la tarea y la configuracion; no actua si hay
|
||||||
|
una restauracion en curso, y revierte solo si la version nueva no arranca)
|
||||||
|
|
||||||
|
Opcion C - escritorio Windows (con sesion):
|
||||||
|
.\install.ps1 -Desktop
|
||||||
|
|
||||||
|
No se usa NSSM ni ningun envoltorio de servicio: la tarea programada ya viene en el
|
||||||
|
SO, y en el servidor destino no se instala ni se descarga nada.
|
||||||
|
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
Linux en SERVIDOR SIN ESCRITORIO (headless)
|
Linux en SERVIDOR SIN ESCRITORIO (headless)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user