# 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](#requisitos-del-sistema)
2. [Configuración de Producción](#configuración-de-producción)
3. [Despliegue](#despliegue)
4. [Monitoreo y Mantenimiento](#monitoreo-y-mantenimiento)
5. [Actualizaciones](#actualizaciones)
6. [Backup y Recuperación](#backup-y-recuperación)
7. [Solución de Problemas](#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:

```env
# 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

```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
# 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"]
```

```yaml
# 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

```bash
# 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

```bash
# 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:

```bash
# /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:

```bash
#!/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

```bash
# 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

```bash
#!/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

```bash
#!/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"

```bash
# 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"

```bash
# 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"

```bash
# 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"

```bash
# 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

```bash
# 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

```bash
# 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

- **Issues:** Reportar en el repositorio de Gitea
- **Emergencias:** Email: support@yourdomain.com
- **Documentación:** Ver [docs/README.md](../../README.md)

---

_Última actualización: 2026-02-22_
