Skip to content

SIVA — Guía de Despliegue en Servidor

Documentación técnica interna. Los scripts y la configuración viven en deploy/docker/ del repositorio. Índice general: docs/README.md.

Arquitectura de despliegue

┌──────────────────────────────────────────────────────────────┐
│  Servidor Debian 12 (192.168.1.80)                           │
│                                                              │
│  /home/siva/siva-app/                                        │
│  ├── backend/                  (Dockerfile → prod)           │
│  ├── frontend/                 (Dockerfile → nginx)          │
│  └── deploy/docker/                                │
│      ├── docker-compose.yml    (orquestacion)                │
│      ├── .env.prod             (variables de entorno)        │
│      ├── data/                 (SQLite, persistente)         │
│      ├── storage/              (uploads, persistente)        │
│      └── public/               (assets estaticos)            │
│                                                              │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐                    │
│  │ Frontend │ │ Backend  │ │ Mailpit  │                    │
│  │  :80     │→│  :3000   │ │  :1025   │                    │
│  │ (nginx)  │ │ (Node)   │ │  :8025   │                    │
│  └──────────┘ └──────────┘ └──────────┘                    │
│  ┌───────────────┐ ┌──────────────────┐                    │
│  │ Doc usuario   │ │ Doc sistema      │                    │
│  │  :8080 (nginx)│ │  :8081 (nginx)   │                    │
│  └───────────────┘ └──────────────────┘                    │
│       ↑            ↑             ↑                          │
│     :80          :3000      :1025, :8025                    │
│   :8080        :8081 (documentación)                        │
└───────┼────────────┼─────────────┼──────────────────────────┘
        │            │             │
   Usuario      Swagger/API    Mailpit UI
   (web)        (docs)        (debug email)

La aplicación corre en 5 contenedores Docker interconectados por una red bridge interna (siva-network):

ContenedorImagenPuerto hostDescripción
siva-frontendinap/siva-frontend:latest80Vue 3 compilado servido por Nginx
siva-backendinap/siva-backend:latest3000API REST Node.js + Express
siva-mailpitaxllent/mailpit:latest1025, 8025Captura de emails para desarrollo
siva-doc-userinap/siva-doc-user:latest8080Manual de usuario (VitePress + Nginx)
siva-doc-systeminap/siva-doc-system:latest8081Documentación de sistema (VitePress + Nginx)

Todos los contenedores usan restart: unless-stopped, lo que significa que:

  • Se inician automáticamente al arrancar el servidor (tras un reboot)
  • Se reinician automáticamente si crashean
  • Solo se detienen si ejecutas manualmente docker compose down

Los datos (base de datos SQLite y archivos subidos) se almacenan en volúmenes montados en el host (deploy/docker/data/, storage/, public/), por lo que sobreviven a reconstrucciones y reinicios de los contenedores.


Prerrequisitos

En el servidor (Debian 12)

  1. Docker Engine instalado. Si no lo tienes:

    bash
    # Instalar Docker en Debian 12
    sudo apt update
    sudo apt install -y ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    sudo apt update
    sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
  2. Tu usuario (siva) debe pertenecer al grupo docker:

    bash
    sudo usermod -aG docker siva
    # Cierra sesión SSH y vuelve a entrar para que el cambio surta efecto
  3. Puertos abiertos en el firewall (si usas ufw o iptables):

    bash
    sudo ufw allow 80/tcp    # Frontend
    sudo ufw allow 3000/tcp  # API / Swagger
    sudo ufw allow 8025/tcp  # Mailpit (opcional)

En tu máquina local

  • Acceso SSH a siva@192.168.1.80 (sin contraseña o con clave SSH configurada)
  • rsync instalado

Despliegue inicial

1. Primer despliegue

Desde la carpeta deploy/docker/ del proyecto:

bash
cd deploy/docker
chmod +x desplegar_en_servidor.sh
./desplegar_en_servidor.sh

ℹ️ Antes del primer despliegue crea el .env.prod local a partir de la plantilla: cp .env.prod.example .env.prod (ajusta secretos y CORS_ORIGIN).

El script hará automáticamente:

  1. Verificar conexión SSH y Docker en el servidor
  2. Sincronizar el código fuente a /home/siva/siva-app/
  3. Crear directorios de datos (deploy/docker/data/, storage/, public/)
  4. Generar .env.prod con un JWT_SECRET aleatorio (solo la primera vez)
  5. Construir las imágenes Docker y levantar los contenedores
  6. Verificar que la API responde correctamente

2. Personalizar la configuración

Si necesitas cambiar la IP del servidor o el directorio de despliegue, usa variables de entorno al ejecutar el script:

bash
SERVER_IP="10.0.0.50" ./desplegar_en_servidor.sh
CORS_ORIGIN="http://midominio.com" ./desplegar_en_servidor.sh

3. Verificar el despliegue

Abre en tu navegador:

  • Frontend: http://192.168.1.80
  • Swagger API docs: http://192.168.1.80:3000/api/docs
  • Mailpit (emails): http://192.168.1.80:8025
  • Documentación de usuario: http://192.168.1.80:8080
  • Documentación de sistema: http://192.168.1.80:8081

Login por defecto: superadmin@inap.es / superadmin1234

Cambia la contraseña del superadmin inmediatamente tras el primer acceso.


Actualizar un despliegue existente

Cada vez que hagas cambios en el código y quieras redesplegar:

bash
cd deploy/docker
./desplegar_en_servidor.sh

El script:

  • Sincroniza los archivos modificados al servidor
  • Preserva .env.prod, data/, storage/ y public/ existentes
  • Reconstruye las imágenes Docker
  • Reinicia los contenedores con el nuevo código
  • Los datos (SQLite, archivos subidos) se mantienen intactos

Comandos útiles

Ejecuta estos comandos desde tu máquina local:

bash
# Ver logs de todos los contenedores
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose logs -f'

# Ver logs solo del backend
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose logs -f backend'

# Reiniciar todos los servicios
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose restart'

# Detener los servicios (los contenedores se quedarán abajo)
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose down'

# Levantar servicios previamente detenidos
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose up -d'

# Ver estado de los contenedores
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose ps'

# Health check manual
curl http://192.168.1.80:3000/api/health

Estructura en el servidor

/home/siva/siva-app/
├── backend/                        # Código fuente del backend
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── frontend/                       # Código fuente del frontend
│   ├── Dockerfile
│   ├── nginx.conf
│   ├── package.json
│   └── src/
├── documentation/                  # Documentación VitePress (user/ y system/)
│   ├── Dockerfile                  # Imagen de producción (ARG SITE)
│   ├── nginx.conf
│   ├── scripts/                    # Generación de "última actualización"
│   ├── user/                       # Manual de usuario
│   └── system/                     # Documentación de sistema
├── docs/                           # Documentación técnica interna (esta guía)
├── deploy/podman/                         # Configuración Podman (original)
├── deploy/docker/        # ★ Configuración de despliegue Docker
│   ├── docker-compose.yml          # Orquestación Docker
│   ├── .env.prod                   # Variables de entorno de producción
│   ├── desplegar_en_servidor.sh    # Script de despliegue
│   ├── README.md                   # Aviso: guía en docs/operacion/
│   ├── data/                       # Persistente — base de datos SQLite
│   │   └── siva.db
│   ├── storage/                    # Persistente — archivos subidos (avatars, etc.)
│   └── public/                     # Assets estáticos del backend
│       └── images/
└── ...

Backup y restauración

Hacer backup

bash
# Desde tu máquina local
ssh siva@192.168.1.80 'tar czf /tmp/siva-backup-$(date +%Y%m%d).tar.gz -C /home/siva/siva-app/deploy/docker data storage .env.prod'
scp siva@192.168.1.80:/tmp/siva-backup-*.tar.gz .

Restaurar backup

bash
# Detener servicios primero
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose down'

# Restaurar datos
scp siva-backup-YYYYMMDD.tar.gz siva@192.168.1.80:/tmp/
ssh siva@192.168.1.80 'tar xzf /tmp/siva-backup-YYYYMMDD.tar.gz -C /home/siva/siva-app/deploy/docker/'

# Volver a levantar
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose up -d'

Variables de entorno (.env.prod)

VariableDescripciónValor por defecto
PORTPuerto del backend dentro del contenedor3000
NODE_ENVEntorno de ejecuciónproduction
API_PREFIXPrefijo de las rutas API/api
DB_PATHRuta del archivo SQLite./data/siva.db
JWT_SECRETClave secreta para tokens JWTGenerado aleatoriamente
JWT_ACCESS_EXPIRATIONDuración del token de acceso1h
JWT_REFRESH_EXPIRATIONDuración del token de refresco7d
SUPERADMIN_EMAILEmail del superadmin por defectosuperadmin@inap.es
SUPERADMIN_PASSWORDContraseña inicial del superadminsuperadmin1234
SMTP_HOSTServidor SMTPmailpit
SMTP_PORTPuerto SMTP1025
SMTP_FROMRemitente de los emailsnoreply@siva.local
CORS_ORIGINOrigen CORS permitidohttp://192.168.1.80
RATE_LIMIT_WINDOW_MSVentana de rate limiting900000 (15 min)
RATE_LIMIT_MAXPeticiones máximas por ventana3000

Solución de problemas

Error: "Permission denied" al ejecutar Docker

El usuario siva no está en el grupo docker. Solución:

bash
ssh siva@192.168.1.80 'sudo usermod -aG docker siva'
# Cerrar sesión SSH y volver a entrar

Error: "port is already allocated" (puerto 80 ocupado)

Otro servicio (Apache, otro Nginx) está usando el puerto 80. Opciones:

  • Detener el otro servicio: sudo systemctl stop apache2 o nginx
  • Cambiar el puerto: edita docker-compose.yml en el servidor (/home/siva/siva-app/deploy/docker/docker-compose.yml) y cambia "80:80" por "8080:80". Luego ejecuta docker compose up -d.

La API no arranca

Revisa los logs del backend:

bash
ssh siva@192.168.1.80 'cd /home/siva/siva-app/deploy/docker && docker compose logs backend'

Causas comunes:

  • DB_PATH incorrecto (debe ser ./data/siva.db)
  • JWT_SECRET vacío o muy corto
  • Puerto 3000 ya en uso

No puedo iniciar sesión

El token JWT se genera con el secreto de .env.prod. Si cambiaste JWT_SECRET después de haber creado usuarios, los tokens existentes quedarán invalidados. Vuelve a iniciar sesión con el superadmin por defecto.

Mailpit no recibe correos en producción

Por ahora Mailpit captura todos los correos. Para usar un SMTP real en producción, edita .env.prod en el servidor:

bash
ssh siva@192.168.1.80
vi /home/siva/siva-app/deploy/docker/.env.prod
# Cambiar SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS
# Luego:
cd /home/siva/siva-app/deploy/docker && docker compose up -d

SIVA — Sistema Integral de Vigilantes de Aulas