Instalar en el servidor del cliente¶
Esta guía instala el Sistema de Premios como servicio de Windows en el servidor de destino: build del jar único, carpeta de deploy fuera del repo, config/application.yml con los valores reales del cliente, arranque a mano para verificar, y el servicio con NSSM para que quede corriendo solo y se levante con el sistema operativo.
No hace falta Docker: es un jar Java corriendo nativo en Windows, con SQL Server ya instalado en el mismo servidor o accesible por red.
Esta página deja la app corriendo en 127.0.0.1:28880, sin TLS
A propósito: acá dejamos la aplicación escuchando solo localhost. El paso de exponerla al público por HTTPS real es aparte — seguí con Publicar con HTTPS (Caddy + NSSM) inmediatamente después de terminar esta guía.
Prerrequisitos del servidor¶
- JDK 21 instalado (el jar es bytecode Java 17, corre en cualquier JDK ≥17 — usamos 21 para estar alineados con el build).
- SQL Server 2022 con la base de datos
SistemaPremiosya creada (vacía; Flyway arma el esquema al primer arranque). - NSSM descargado en el servidor (para correr la app como servicio Windows).
- Acceso de red del servidor a la instancia de SQL Server (local o remota).
1. Buildear el jar completo¶
El build se hace en tu máquina de build (o en el mismo servidor, si tiene Maven/Node). El perfil full empaqueta la landing y el gestor dentro del jar del backend — no hay que copiar nada de esos dos proyectos por separado.
Esto genera:
con la landing (/) y el gestor (/gestor/) ya adentro.
2. Crear la carpeta de deploy (fuera del repo)¶
La carpeta de deploy es donde vive todo lo operativo del servidor — el jar, la config real con secretos, las bases legales, el branding y los logs. No es un checkout de git: nunca se versiona.
mkdir C:\work\sistemapremios
mkdir C:\work\sistemapremios\config
mkdir C:\work\sistemapremios\bases
mkdir C:\work\sistemapremios\branding
mkdir C:\work\sistemapremios\logs
Copiá el jar recién buildeado y el logo del cliente:
3. Escribir config\application.yml¶
Este es el archivo que reemplaza al que viaja en el repo como referencia (ver ADR-029 y el detalle de cada clave en Configuración). Va junto al jar, en C:\work\sistemapremios\config\application.yml, y acá sí lleva los valores reales.
Creá el archivo con este contenido, reemplazando cada CAMBIAR:
# config externa (ADR-029). Va junto al jar. NO en git (valores reales).
sp.config.externa: true # centinela ADR-029 — NO borrar
# ── valores del cliente (resuelven los ${SP_*} de abajo) ──
SP_DB_PASSWORD: "CAMBIAR" # sa de SQL Server (SistemaPremios)
SP_MASTER_KEY: "CAMBIAR" # base64 32 bytes — EL MISMO usado al seed
SP_GESTOR_USER: "admin" # login del gestor
SP_GESTOR_PASSWORD: "CAMBIAR" # login del gestor (obligatorio: sin esto NO arranca)
SP_CLIENTE_NOMBRE: "Supermercados Caracol"
SP_CLIENTE_COLOR: "#e30613"
SP_BRANDING_DIR: "C:/work/sistemapremios/branding" # con logo.png adentro
SP_MODO_PRUEBA: "true" # generador de QR de prueba (NO usar perfil prod)
SP_BASE_URL: "https://sistemapremios.tipre.com" # URL pública que va DENTRO del QR (¡no localhost!)
management:
endpoints:
web:
exposure:
include: health
endpoint:
health:
show-details: when-authorized
server:
address: 127.0.0.1 # solo localhost — solo el reverse proxy entra
port: 28880
forward-headers-strategy: framework # detrás de Caddy ya reescribe la IP real (X-Forwarded-For) — NO cambiar
tomcat:
allow-trace: false
compression:
enabled: true
mime-types: text/html,text/css,application/javascript,text/javascript,application/json
min-response-size: 1024
spring:
application:
name: sistemapremios-backend
datasource:
url: ${SP_DB_URL:jdbc:sqlserver://localhost;databaseName=SistemaPremios;encrypt=false}
username: ${SP_DB_USER:sa}
password: ${SP_DB_PASSWORD:${SP_DB_PASS:}}
jpa:
hibernate:
ddl-auto: validate
open-in-view: false
properties:
hibernate:
jdbc:
time_zone: America/Argentina/Buenos_Aires
query:
in_clause_parameter_padding: true
flyway:
enabled: true
jackson:
property-naming-strategy: SNAKE_CASE
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
sp:
cliente:
nombre: ${SP_CLIENTE_NOMBRE:Cliente}
color-primario: ${SP_CLIENTE_COLOR:#E01020}
branding:
dir: ${SP_BRANDING_DIR:./branding}
modo-prueba:
enabled: ${SP_MODO_PRUEBA:false}
base-url: ${SP_BASE_URL:http://localhost:8080}
reconocimiento:
habilitado: true
Tres variables que muerden si las salteás
SP_GESTOR_PASSWORD— sin ella el backend no arranca. No hay fallback silencioso.SP_BASE_URL— si queda enlocalhost, los QR que genera el sistema apuntan alocalhosty ningún cliente fuera de esa máquina puede escanearlos.SP_MASTER_KEY— tiene que ser la misma que se usó al sembrar los datos (seed), o los QR emitidos antes no vuelven a validar.
Fallback LAN sin reverse proxy (self-signed, no recomendado para producción pública)
Si por algún motivo no vas a poner Caddy delante (por ejemplo, una prueba interna en la LAN del cliente sin dominio público), podés reemplazar el bloque server de arriba por:
server:
port: 8443
ssl:
enabled: true
key-store: "file:C:/work/sistemapremios/sp-dev.p12"
key-store-password: changeit
key-store-type: PKCS12
key-alias: sp
Con Caddy delante (el camino recomendado, ver el paso siguiente) esto no hace falta.
4. Probar el arranque a mano¶
Antes de instalarlo como servicio, corré el jar directamente para confirmar que todo está en orden. Parado en la carpeta de deploy:
Flyway migra la base al arrancar. Si falta la carpeta config\, o si le falta alguna clave de contrato, el fail-fast de ADR-029 corta el arranque y te dice exactamente qué archivo esperaba y en qué working directory buscó — nunca arranca en silencio con defaults.
En otra terminal, verificá el health check:
Debería responder {"estado":"ok","base_datos":"ok"}. Si respondió bien, cortá el proceso (Ctrl+C) y pasá al servicio.
5. Instalar el servicio con NSSM¶
nssm install SistemaPremios "C:\Program Files\Java\jdk-21\bin\java.exe" "-jar C:\work\sistemapremios\sistemapremios-backend-0.0.1-SNAPSHOT.jar"
AppDirectory es CRÍTICO — no es un detalle cosmético
Spring Boot busca ./config/ relativo al working directory del proceso, no a la ubicación del jar. Si AppDirectory no apunta a C:\work\sistemapremios (la carpeta que contiene config\), el servicio arranca con el proceso corriendo en otro directorio y el chequeo de config externa falla — aunque el jar esté en la ruta correcta. Es el error más común al migrar de "corrí bien a mano" a "no arranca como servicio".
Confirmá que el servicio está arriba:
6. Backup diario¶
La carpeta de deploy y la base de datos son lo único que no se recupera con un simple re-deploy del jar (el jar se regenera desde el repo; los datos, no). Como mínimo, programá dos backups diarios fuera de horario pico:
Backup de la base de datos (ejemplo con sqlcmd, ajustá credenciales y ruta):
sqlcmd -S localhost -U sa -P "CAMBIAR" -Q "BACKUP DATABASE SistemaPremios TO DISK = 'C:\backups\SistemaPremios_$(Get-Date -Format yyyyMMdd).bak'"
Backup de la carpeta de deploy (config, branding y logs — no hace falta backupear el jar, ese sale del repo):
Programalo con el Programador de tareas de Windows
Envolvé estos comandos en un .ps1 y agendalo con schtasks o el Programador de tareas de Windows, corriendo una vez por día fuera del horario de mayor tráfico de la campaña. C:\backups\ es un ejemplo — usá la ruta de backup que ya tenga definida la infraestructura del cliente (idealmente en otro disco o servidor).
Siguiente paso¶
La app ya corre como servicio, pero solo responde en 127.0.0.1:28880 — todavía no es accesible desde afuera. Para publicarla con HTTPS real (necesario para que el escáner de DNI de la landing funcione en cualquier celular), seguí con Publicar con HTTPS (Caddy + NSSM).