14 KiB
Despliegue en Windows
La aplicación se ejecuta como un solo servicio de Windows: la API (NestJS) sirve también la web compilada (Angular), por HTTPS y en un único puerto. El servicio lo administra NSSM.
Navegador ──HTTPS :443──▶ servicio "DevolucionProveedores" (node dist\main.js)
├─ sirve la web (Angular compilado)
├─ /api ──▶ Service Layer de SAP B1 (:50000)
└─ /api/…/pdf ──▶ web service de BES (HTTPS)
No hay base de datos propia ni otros servicios: todo se guarda en SAP. Como las sesiones viven en la memoria de la API, reiniciar el servicio cierra la sesión de todos los usuarios.
Estado de esta guía. La carpeta publicada, la API con HTTPS, la web servida por la API, la redirección HTTP→HTTPS y los logs sin colores se probaron en un Mac. Los scripts de PowerShell y NSSM no se han ejecutado todavía en Windows (se comprobó su sintaxis y los comandos de NSSM que generan, con
-SoloMostrar). Tampoco se ha probado contra HANA. Haga la primera instalación en un servidor de pruebas.
1. Requisitos del servidor
| Qué | Detalle |
|---|---|
| Windows | Windows Server 2016 o superior. |
| Node.js | 22 LTS o superior, instalado para todos los usuarios (node -v en una consola nueva). |
| Red | Acceso al Service Layer de SAP (puerto 50000) y al web service de BES (HTTPS de salida). |
| NSSM | nssm.exe de 64 bits (carpeta win64 del .zip de https://nssm.cc/download). Ver la nota de abajo sobre la versión. |
| Certificado | Un .pfx (o .key + .crt) para el nombre con que los usuarios abrirán la página. |
| Permisos | Una consola de PowerShell como administrador. |
Versión de NSSM. Descargue la compilación 2.24-101 (pre-release,
nssm-2.24-101-g897c7ad.zip, carpetawin64), no la estable. La estable (2.24, de 2014) puede fallar al iniciar servicios en Windows 10 y 11 y en Windows Server 2019 o 2022 (mensajes comoUnexpected status SERVICE_PAUSED); solo debería servir en Windows Server 2016. Compruebe connssm version(debe decir2.24-101-g897c7ad). La página de descargas no publica sumas de verificación: revise el.zipsegún la política de su empresa.
2. Publicar (en su equipo de desarrollo o en el servidor)
Desde la raíz del proyecto, con Node 22:
npm install
npm run publicar
Genera release\devolucion-proveedores\ con la API y la web compiladas y solo las dependencias de
producción (unos 55 MB). Si ya compiló (npm run build), use npm run publicar -- --sin-build.
Las dependencias de la API son JavaScript puro, así que se puede publicar desde un Mac o Linux y ejecutar en Windows.
3. Copiar al servidor
Copie solo la carpeta release\devolucion-proveedores (no el resto del proyecto) a, por ejemplo,
C:\apps\devolucion-proveedores. No contiene enlaces simbólicos, así que se puede copiar por red, USB o
comprimida en un .zip (más rápido: son miles de archivos pequeños; en el servidor, Expand-Archive).
nssm.exe no viene en la carpeta: se descarga aparte y se indica con -Nssm.
C:\apps\devolucion-proveedores\
├── app\ la aplicación (no se edita, salvo el .env)
│ └── apps\api\.env ← se crea en el paso 4
├── certificados\ ← el certificado HTTPS (paso 5)
├── logs\ ← los logs del servicio
├── servicio\ ← lo crea el instalador (copia de nssm.exe)
├── instalar-servicio.ps1
├── desinstalar-servicio.ps1
└── DEPLOY.md
4. Configurar el .env
cd C:\apps\devolucion-proveedores\app\apps\api
Copy-Item .env.example .env
notepad .env
Ejemplo para producción (HANA, HTTPS en el puerto 443 y redirección desde el 80):
PORT=443
SL_URL=https://servidor-hana:50000/b1s/v1
SL_COMPANY_DB=NombreDeLaSociedad
SL_REJECT_UNAUTHORIZED=false
DB_TYPE=HANA
COOKIE_SECURE=true
HTTPS_PFX_PATH=C:\apps\devolucion-proveedores\certificados\sitio.pfx
HTTPS_PFX_PASSPHRASE=la-clave-del-pfx
HTTP_REDIRECT_PORT=80
- El puerto es el que ponga en
PORT: 443 es solo el ejemplo (con él la URL no lleva:puerto). Puede usar cualquiera que esté libre, por ejemploPORT=8443; entonces la URL eshttps://servidor:8443. NSSM no influye: solo arranca el servicio. HTTP_REDIRECT_PORTes opcional. Solo es útil con el 80 (la gente escribehttp://servidorsin puerto); con otro puerto solo redirige a quien escribahttp://servidor:<ese puerto>. Déjelo vacío si no lo necesita.- No se configura el usuario ni la contraseña de SAP: cada persona los escribe en el login.
WEB_ORIGINno hace falta: la web y la API comparten origen.- Con
.key/.crten vez de.pfx:HTTPS_KEY_PATHyHTTPS_CERT_PATH(no mezcle ambas formas). - Si deja el
.envcon la clave del.pfx, restrinja quién puede leerlo:
icacls C:\apps\devolucion-proveedores\app\apps\api\.env /inheritance:r /grant:r "Administrators:F" "SYSTEM:F"
(Si el servicio correrá con una cuenta propia, agréguela con /grant:r "EMPRESA\svc-devolucion:R".)
5. Certificado HTTPS
Lo normal es un certificado de la CA de la empresa, exportado como .pfx a certificados\. Para
una prueba puede crear uno autofirmado (los navegadores mostrarán una advertencia):
$c = New-SelfSignedCertificate -DnsName 'devolucion.empresa.local' -CertStoreLocation Cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(2)
Export-PfxCertificate -Cert $c -FilePath C:\apps\devolucion-proveedores\certificados\sitio.pfx -Password (Read-Host -AsSecureString 'Clave del pfx')
HTTPS es obligatorio: el botón Pegar desde el portapapeles solo funciona con localhost o HTTPS, y
la cookie de sesión se marca Secure.
6. Abrir el firewall
Abra el puerto que puso en PORT (y el de HTTP_REDIRECT_PORT, si lo usa). Con los valores del
ejemplo (443 y 80):
New-NetFirewallRule -DisplayName 'Devolucion Proveedores HTTPS' -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
New-NetFirewallRule -DisplayName 'Devolucion Proveedores HTTP (redireccion)' -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
Desde el propio servidor (localhost) la aplicación funciona sin reglas; los demás equipos solo llegan si
el puerto está abierto.
Ver las reglas que hay y su puerto:
Get-NetFirewallRule -DisplayName 'Devolucion Proveedores*' |
Select-Object DisplayName, Enabled, @{ n = 'Puerto'; e = { ($_ | Get-NetFirewallPortFilter).LocalPort } }
Si más adelante cambia PORT, cambie el puerto de la regla existente en vez de crear otra, o borre la
anterior para no dejar abierto un puerto que ya no se usa (por ejemplo, para pasar al 8443):
Set-NetFirewallRule -DisplayName 'Devolucion Proveedores HTTPS' -LocalPort 8443
# o bien
Remove-NetFirewallRule -DisplayName 'Devolucion Proveedores HTTPS'
Comprobar desde otro equipo que el puerto responde:
Test-NetConnection servidor -Port 443 # TcpTestSucceeded : True
Si da False con el servicio en Running, el bloqueo está en el firewall (de Windows o de la red).
7. Instalar el servicio
cd C:\apps\devolucion-proveedores
.\instalar-servicio.ps1 -Nssm C:\descargas\nssm-2.24-101-g897c7ad\win64\nssm.exe
Opciones:
| Parámetro | Para qué |
|---|---|
-Cuenta 'EMPRESA\svc-devolucion' |
Ejecutar con una cuenta propia en vez de LocalSystem. Pide la contraseña y no la guarda en ningún archivo. Esa cuenta necesita el derecho Iniciar sesión como servicio y lectura sobre la carpeta. |
-UsarCertificadosDelSistema |
Agrega NODE_OPTIONS=--use-system-ca. Úselo si Fortinet (u otro firewall) inspecciona el HTTPS de salida con un certificado propio y la descarga de PDF falla por certificado. |
-NombreServicio |
Cambia el nombre del servicio (por defecto DevolucionProveedores). |
-SoloMostrar |
Imprime los comandos de NSSM que ejecutaría y termina, sin instalar nada ni exigir administrador. Úselo para revisarlos antes. |
El script verifica Node 22, los archivos y el .env; copia nssm.exe a servicio\; instala el servicio
(arranque automático, reinicio a los 10 s si Node se cae, logs a logs\) y lo inicia. Si algún ajuste
falla, quita el servicio a medio configurar.
8. Verificar
Get-Service DevolucionProveedores
Invoke-WebRequest https://devolucion.empresa.local/api/health -UseBasicParsing
Get-Content C:\apps\devolucion-proveedores\logs\*.out.log -Tail 30
Debe verse {"status":"ok"} y, en el log, la línea Escuchando en https://0.0.0.0:443. Después abra la
dirección en un navegador, inicie sesión con un usuario de SAP y revise Configuración → Metadatos.
En una base nueva pulse Reconstruir para crear las tablas, campos y el objeto de usuario.
9. Logs
NSSM guarda lo que la API escribe por consola en logs\devolucion-api.out.log y devolucion-api.err.log,
y los rota al llegar a 10 MB (los rotados llevan la fecha y la hora en el nombre). La aplicación no escribe
logs por su cuenta.
NSSM no limita cuántos archivos rotados conserva: se acumulan. Programe una limpieza periódica, por ejemplo una tarea que borre los de más de 30 días:
Get-ChildItem C:\apps\devolucion-proveedores\logs -Filter 'devolucion-api.*-*.log' |
Where-Object LastWriteTime -lt (Get-Date).AddDays(-30) | Remove-Item
- Los errores 4xx/5xx de la API, los fallos y las peticiones lentas al Service Layer, y los eventos de negocio (planificación creada, PDF descargado) quedan registrados. Las peticiones correctas no.
- Para seguirlo en vivo:
Get-Content C:\apps\devolucion-proveedores\logs\*.out.log -Wait -Tail 50. - La contraseña del web service DTE (
@DTE_CONFC) y las de los usuarios nunca se registran.
10. Administrar el servicio
Con servicio\nssm.exe (la copia que dejó el instalador):
cd C:\apps\devolucion-proveedores\servicio
.\nssm.exe status DevolucionProveedores
.\nssm.exe restart DevolucionProveedores
.\nssm.exe edit DevolucionProveedores # ventana gráfica con todos los ajustes
.\nssm.exe get DevolucionProveedores AppEnvironmentExtra
Para cambiar una variable de entorno del servicio con nssm set ... AppEnvironmentExtra, indique todas las
variables juntas (reemplaza la lista completa): NODE_ENV=production NO_COLOR=1 [NODE_OPTIONS=--use-system-ca].
Los valores de la aplicación (puerto, SAP, HTTPS) no van aquí: se cambian en el .env y se reinicia el servicio:
Stop-Service DevolucionProveedores
notepad C:\apps\devolucion-proveedores\app\apps\api\.env
Start-Service DevolucionProveedores
- Al cambiar
SL_COMPANY_DB, revise queDB_TYPE(HANA/MSSQL) corresponda a esa base y, tras entrar, pase por Configuración → Metadatos. El login muestra la sociedad conectada. - Al cambiar
PORT, ajuste el firewall (paso 6). La web y la API usan el mismo puerto. - La versión instalada se ve en el login, en la barra superior, en
VERSION.txty en el log al arrancar.
11. Actualizar a una versión nueva
- Publique la versión nueva (paso 2) y copie la carpeta al servidor, por ejemplo a
C:\nueva\. - Elija una hora en que haya pocos usuarios: se perderán las sesiones.
- Ejecute:
Stop-Service DevolucionProveedores
# Respaldo opcional de la versión actual
Copy-Item C:\apps\devolucion-proveedores\app C:\apps\respaldo-app -Recurse
# Copia la nueva sin tocar el .env
robocopy C:\nueva\devolucion-proveedores\app C:\apps\devolucion-proveedores\app /MIR /XF .env
Start-Service DevolucionProveedores
/MIR borra de app\ lo que ya no exista en la versión nueva; /XF .env conserva su configuración.
Los certificados, los logs y el servicio no cambian.
12. Desinstalar
cd C:\apps\devolucion-proveedores
.\desinstalar-servicio.ps1
Detiene y elimina el servicio. No borra archivos ni logs.
13. Seguridad
- No publique la aplicación en Internet. El login es el de SAP B1; manténgala en la red interna o detrás de una VPN.
- Use un certificado válido de la CA de la empresa; el servicio envía
Strict-Transport-Security. - Dele al servicio la cuenta con menos permisos posible: solo lectura sobre su carpeta y escritura en
logs\. - Restrinja la lectura del
.envsi contiene la clave del.pfx(paso 4).
14. Problemas frecuentes
| Síntoma | Causa probable |
|---|---|
El servicio no inicia (SERVICE_PAUSED, Unexpected status) |
Problema conocido de NSSM 2.24 estable en Windows recientes: use la compilación 2.24-101 (ver el paso 1) y reinstale el servicio. |
| El servicio se inicia y se detiene | Mire logs\*.err.log. Suele ser una ruta mal escrita en el .env (No se pudo leer HTTPS_PFX_PATH (…)) o el puerto ocupado (EADDRINUSE). |
WEB_DIST_DIR no contiene un index.html |
Se copió la carpeta app incompleta: falta app\apps\web\dist\web\browser. |
| Puerto 443 o 80 ocupado | IIS u otro programa lo usa. Cambie PORT / HTTP_REDIRECT_PORT en el .env y las reglas del firewall. |
| El navegador avisa que el sitio no es seguro | Certificado autofirmado, o el nombre de la URL no coincide con el del certificado. |
| Entra al login pero vuelve a pedirlo | Con COOKIE_SECURE=true la cookie solo se guarda por HTTPS: abra la página por https://. |
EHOSTUNREACH o no conecta con SAP |
Red o firewall hacia el Service Layer; reinicie el servicio tras un cambio de red. |
| La descarga de PDF falla por certificado | Fortinet inspecciona el HTTPS de salida: reinstale con -UsarCertificadosDelSistema, o importe el certificado raíz de Fortinet en Windows. |
| Cada acción tarda decenas de segundos | Mire el log: los avisos Petición lenta al Service Layer indican qué llamada y cuánto tardó. |
.\instalar-servicio.ps1 dice que no se puede ejecutar scripts |
Set-ExecutionPolicy -Scope Process Bypass en esa consola y vuelva a intentarlo. |
Antes de pasar a producción (HANA)
El sistema se probó contra SQL Server (SBOLibros). Con HANA:
- Pruebe primero con una copia de la sociedad:
DB_TYPE=HANA, Reconstruir y una ejecución completa. - Compare los resultados del FIFO con los del addon .NET para el mismo listado.
- Confirme que el Service Layer de HANA expone
/b1s/v1(el paginado usa$inlinecount).