547 lines
11 KiB
Markdown
547 lines
11 KiB
Markdown
# 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_
|