Files
quasar/docs/04-operaciones/deployment.md
Benito Rodríguez 0c9c408564
Some checks failed
CI / lint (push) Failing after 1m4s
CI / test-backend (push) Has been skipped
CI / test-frontend (push) Has been skipped
CI / test-e2e (push) Has been skipped
Refactor code structure for improved readability and maintainability
2026-02-22 18:18:46 +01:00

11 KiB

Guía de Despliegue y Operaciones 🚀

Esta guía cubre el despliegue, configuración y operación de Quasar en producción.


Tabla de Contenidos

  1. Requisitos del Sistema
  2. Configuración de Producción
  3. Despliegue
  4. Monitoreo y Mantenimiento
  5. Actualizaciones
  6. Backup y Recuperación
  7. Solución de Problemas

Requisitos del Sistema

Hardware Mínimo

  • CPU: 2 cores
  • RAM: 4GB
  • Almacenamiento: 20GB (para ROMs y metadata)
  • Red: Estable (para descargas de artwork)

Software

  • Node.js 18+
  • Yarn 4.x
  • SQLite (o PostgreSQL para producción)
  • Nginx (recomendado para reverse proxy)
  • Certificado SSL (HTTPS obligatorio)

Dependencias Externas

  • Claves API de IGDB, RAWG, TheGamesDB
  • Acceso a servicios de descarga de imágenes

Configuración de Producción

Variables de Entorno

Crear .env.production con:

# Database
DATABASE_URL="file:./production.db"
# Para PostgreSQL: postgresql://user:password@localhost:5432/quasar

# API Keys
IGDB_CLIENT_ID=your_production_client_id
IGDB_CLIENT_SECRET=your_production_client_secret
RAWG_API_KEY=your_production_api_key
THEGAMESDB_API_KEY=your_production_api_key
SCREENSCRAPER_USERNAME=your_screenscraper_username
SCREENSCRAPER_PASSWORD=your_screenscraper_password

# App Config
NODE_ENV=production
PORT=3000
HOST=0.0.0.0
LOG_LEVEL=info

# Security
CORS_ORIGIN=https://yourdomain.com
JWT_SECRET=your_secure_jwt_secret_here
API_RATE_LIMIT=100

# Performance
CACHE_TTL=86400
MAX_CONCURRENT_API_REQUESTS=5

Configuración de Nginx

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    # SSL Configuration
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    # Security headers
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Frontend
    location / {
        root /var/www/quasar/frontend/dist;
        try_files $uri $uri/ /index.html;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Backend API
    location /api/ {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 864s;
    }

    # Static files
    location /static/ {
        root /var/www/quasar;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Despliegue

Opción 1: Docker (Recomendado)

# Dockerfile
FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* ./
RUN yarn install --frozen-lockfile

# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Build the application
RUN yarn build

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV PORT=3000

# Copy built application
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

USER nextjs

EXPOSE 3000

CMD ["node", "dist/server.js"]
# docker-compose.yml
version: '3.8'

services:
  quasar-backend:
    build: ./backend
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
      - DATABASE_URL=file:./production.db
      - IGDB_CLIENT_ID=${IGDB_CLIENT_ID}
      - IGDB_CLIENT_SECRET=${IGDB_CLIENT_SECRET}
      - RAWG_API_KEY=${RAWG_API_KEY}
      - THEGAMESDB_API_KEY=${THEGAMESDB_API_KEY}
    volumes:
      - ./data:/app/data
      - ./backend/prisma:/app/prisma
    restart: unless-stopped

  quasar-frontend:
    build: ./frontend
    ports:
      - '5173:5173'
    depends_on:
      - quasar-backend
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - '443:443'
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - quasar-backend
      - quasar-frontend
    restart: unless-stopped

Opción 2: VPS Manual

# 1. Setup server
sudo apt update
sudo apt install -y nodejs yarn nginx sqlite3

# 2. Clone repository
git clone https://your-repo/quasar.git
cd quasar

# 3. Install dependencies
yarn install --production

# 4. Setup environment
cp .env.example .env.production
# Edit .env.production with real values

# 5. Build frontend
cd frontend
yarn build
cd ..

# 6. Setup database
cd backend
npx prisma migrate deploy
cd ..

# 7. Configure nginx
sudo cp nginx.conf /etc/nginx/sites-available/quasar
sudo ln -s /etc/nginx/sites-available/quasar /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

# 8. Start services
cd backend
nohup yarn start > /var/log/quasar-backend.log 2>&1 &
cd ../frontend
nohup yarn start > /var/log/quasar-frontend.log 2>&1 &

Monitoreo y Mantenimiento

Health Checks

# Backend health
curl http://localhost:3000/health

# Database connection
curl http://localhost:3000/api/health/database

# API rate limits status
curl http://localhost:3000/api/health/rate-limits

Logging

Configurar logrotate:

# /etc/logrotate.d/quasar
/var/log/quasar/*.log {
    daily
    missingok
    rotate 7
    compress
    delaycompress
    notifempty
    copytruncate
}

Monitoreo de API Keys

Crear script para verificar límites:

#!/bin/bash
# check-api-limits.sh

# Check IGDB rate limits
curl -s -I "https://api.igdb.com/v4/games" | grep -i "x-ratelimit"

# Check RAWG usage
curl -s "https://api.rawg.io/api/games?key=$RAWG_API_KEY&search=test" | jq '.count'

# Log warnings
echo "$(date): API rate limits checked" >> /var/log/quasar/api-monitor.log

Actualizaciones

Proceso de Actualización

# 1. Backup
./backup.sh

# 2. Stop services
sudo systemctl stop quasar-backend
sudo systemctl stop quasar-frontend

# 3. Pull latest code
git pull origin main

# 4. Update dependencies
yarn install --frozen-lockfile

# 5. Build frontend
cd frontend && yarn build && cd ..

# 6. Run migrations
cd backend && npx prisma migrate deploy && cd ..

# 7. Start services
sudo systemctl start quasar-backend
sudo systemctl start quasar-frontend

Actualizaciones de API Keys

  1. Generar nuevas claves en cada servicio
  2. Actualizar variables de entorno
  3. Reiniciar servicios
  4. Monitorear errores durante 24h

Backup y Recuperación

Script de Backup

#!/bin/bash
# backup.sh

BACKUP_DIR="/backups/quasar"
DATE=$(date +%Y%m%d_%H%M%S)
DB_FILE="quasar_$DATE.db"
ROMS_DIR="roms_$DATE"

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Backup database
cp backend/prisma/production.db "$BACKUP_DIR/$DB_FILE"

# Backup ROM metadata (not actual ROMs)
cp -r data/roms_metadata "$BACKUP_DIR/$ROMS_DIR"

# Backup configuration
cp .env.production "$BACKUP_DIR/env_$DATE"

# Compress backup
tar -czf "$BACKUP_DIR/backup_$DATE.tar.gz" -C "$BACKUP_DIR" "$DB_FILE" "$ROMS_DIR" "env_$DATE"

# Clean up old backups (keep last 7 days)
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete

echo "Backup completed: $BACKUP_DIR/backup_$DATE.tar.gz"

Recuperación

#!/bin/bash
# restore.sh

BACKUP_FILE=$1
BACKUP_DIR="/backups/quasar"

if [ ! -f "$BACKUP_DIR/$BACKUP_FILE" ]; then
    echo "Backup file not found: $BACKUP_DIR/$BACKUP_FILE"
    exit 1
fi

# Stop services
sudo systemctl stop quasar-backend
sudo systemctl stop quasar-frontend

# Extract backup
cd "$BACKUP_DIR"
tar -xzf "$BACKUP_FILE"

# Restore database
cp "$DB_FILE" backend/prisma/production.db

# Restore ROM metadata
cp -r "$ROMS_DIR"/* data/

# Restore configuration (optional)
# cp "env_$DATE" .env.production

# Start services
sudo systemctl start quasar-backend
sudo systemctl start quasar-frontend

echo "Restore completed from: $BACKUP_FILE"

Solución de Problemas

Problemas Comunes

1. "Database connection failed"

# Check database file
ls -la backend/prisma/production.db

# Check permissions
sudo chown -R nodejs:nodejs backend/prisma/

# Check database integrity
sqlite3 backend/prisma/production.db "PRAGMA integrity_check;"

2. "API rate limit exceeded"

# Check current rate limits
curl -I "https://api.igdb.com/v4/games" | grep -i "x-ratelimit"

# Implement backoff strategy
# Check logs for specific API errors
tail -f /var/log/quasar/backend.log | grep "429"

3. "Frontend cannot connect to backend"

# Check backend is running
curl http://localhost:3000/health

# Check CORS configuration
curl -H "Origin: https://yourdomain.com" -v http://localhost:3000/health

# Check nginx configuration
sudo nginx -t

4. "ROM scanning fails"

# Check directory permissions
ls -la /path/to/roms/

# Check file formats
find /path/to/roms/ -name "*.zip" -o -name "*.7z" -o -name "*.rar"

# Check disk space
df -h

Diagnóstico Remoto

# Create diagnostic script
#!/bin/bash
# diagnostic.sh

echo "=== Quasar Diagnostic Report ==="
echo "Date: $(date)"
echo "Node.js version: $(node --version)"
echo "Yarn version: $(yarn --version)"
echo ""

echo "=== System Resources ==="
free -h
df -h
echo ""

echo "=== Services Status ==="
systemctl status quasar-backend
systemctl status quasar-frontend
echo ""

echo "=== Database Status ==="
sqlite3 backend/prisma/production.db "SELECT COUNT(*) FROM games;"
sqlite3 backend/prisma/production.db "SELECT COUNT(*) FROM rom_files;"
echo ""

echo "=== API Keys Status ==="
echo "IGDB: ${IGDB_CLIENT_ID:0:10}..."
echo "RAWG: ${RAWG_API_KEY:0:10}..."
echo "TheGamesDB: ${THEGAMESDB_API_KEY:0:10}..."
echo ""

echo "=== Recent Errors ==="
tail -20 /var/log/quasar/backend.log | grep -i "error"
tail -20 /var/log/quasar/frontend.log | grep -i "error"

Soporte

Logs de Depuración

# Backend logs
tail -f /var/log/quasar/backend.log

# Frontend logs
tail -f /var/log/quasar/frontend.log

# Nginx logs
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

Contacto


Última actualización: 2026-02-22