Esta guía detalla la configuración completa del sistema SIGA, incluyendo requisitos, instalación, configuración de servicios y despliegue en diferentes ambientes.
CPU: 4 cores (2.4 GHz+)
RAM: 16 GB
Almacenamiento: 100 GB SSD
GPU: Opcional (para ML local)
# Servidores de Aplicación
CPU: 16 cores (3.0 GHz+)
RAM: 64 GB
Almacenamiento: 500 GB NVMe SSD
# Servidores de Base de Datos
CPU: 32 cores
RAM: 128 GB
Almacenamiento: 2 TB NVMe SSD (RAID 10)
# Servidores ML
CPU: 16 cores
RAM: 64 GB
GPU: NVIDIA Tesla T4 o superior
Almacenamiento: 1 TB NVMe SSD
# Sistema Operativo
Ubuntu 22.04 LTS o RHEL 8.x
# Runtime
Docker 24.0+
Docker Compose 2.20+
Kubernetes 1.28+ (producción)
# Lenguajes
Python 3.11+
Node.js 20 LTS
Go 1.21+ (para servicios auxiliares)
# Bases de Datos
PostgreSQL 15+
Redis 7.2+
TimescaleDB 2.13+
git clone https://github.com/empresa/siga-system.git
cd siga-system
# Copiar plantilla de configuración
cp .env.example .env
# Editar configuración
nano .env
# === GENERAL ===
ENVIRONMENT=development
APP_NAME=SIGA
APP_VERSION=1.0.0
DEBUG=true
LOG_LEVEL=info
# === API CONFIGURATION ===
API_HOST=0.0.0.0
API_PORT=8000
API_WORKERS=4
API_RELOAD=true
# === DATABASE ===
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=siga
POSTGRES_USER=siga_user
POSTGRES_PASSWORD=secure_password_here
POSTGRES_POOL_SIZE=20
POSTGRES_MAX_OVERFLOW=40
# === TIMESCALE ===
TIMESCALE_HOST=timescale
TIMESCALE_PORT=5433
TIMESCALE_DB=siga_metrics
TIMESCALE_USER=metrics_user
TIMESCALE_PASSWORD=secure_password_here
# === REDIS ===
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=redis_password_here
REDIS_DB=0
REDIS_CACHE_TTL=300
# === AUTHENTICATION ===
JWT_SECRET_KEY=your-super-secret-jwt-key-min-32-chars
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
# === EXTERNAL APIS ===
RTRACKTOR_API_URL=https://api.rtracktor.com/v1
RTRACKTOR_API_KEY=your_rtracktor_api_key
RTRACKTOR_TIMEOUT=30
MAPBOX_API_KEY=your_mapbox_api_key
OPENWEATHER_API_KEY=your_weather_api_key
# === ML SERVICES ===
ML_SERVICE_HOST=ml-service
ML_SERVICE_PORT=8001
ML_BATCH_SIZE=32
ML_MODEL_CACHE_SIZE=1000
# === MONITORING ===
PROMETHEUS_PORT=9090
GRAFANA_PORT=3000
GRAFANA_ADMIN_PASSWORD=admin_password_here
# === FEATURE FLAGS ===
ENABLE_ML_PREDICTIONS=true
ENABLE_REALTIME_TRACKING=true
ENABLE_AB_TESTING=false
ENABLE_DEBUG_ENDPOINTS=false
# Desarrollo
docker-compose -f docker-compose.dev.yml up -d
# Producción
docker-compose -f docker-compose.prod.yml up -d
version: '3.8'
services:
# === DATABASES ===
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init-scripts/postgres:/docker-entrypoint-initdb.d
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
timescale:
image: timescale/timescaledb:latest-pg15
environment:
POSTGRES_DB: ${TIMESCALE_DB}
POSTGRES_USER: ${TIMESCALE_USER}
POSTGRES_PASSWORD: ${TIMESCALE_PASSWORD}
volumes:
- timescale_data:/var/lib/postgresql/data
- ./init-scripts/timescale:/docker-entrypoint-initdb.d
ports:
- "5433:5432"
redis:
image: redis:7.2-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 10s
timeout: 5s
retries: 5
# === BACKEND SERVICES ===
api:
build:
context: ./backend
dockerfile: Dockerfile.dev
environment:
- ENVIRONMENT=${ENVIRONMENT}
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
volumes:
- ./backend:/app
- /app/__pycache__
ports:
- "8000:8000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
command: >
sh -c "
alembic upgrade head &&
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
"
ml-service:
build:
context: ./ml-service
dockerfile: Dockerfile
environment:
- MODEL_PATH=/models
- CACHE_URL=redis://default:${REDIS_PASSWORD}@redis:6379/1
volumes:
- ./ml-service:/app
- ml_models:/models
ports:
- "8001:8001"
depends_on:
- redis
# === FRONTEND ===
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
environment:
- REACT_APP_API_URL=http://localhost:8000
- REACT_APP_MAPBOX_TOKEN=${MAPBOX_API_KEY}
volumes:
- ./frontend:/app
- /app/node_modules
ports:
- "3000:3000"
command: npm start
# === MONITORING ===
prometheus:
image: prom/prometheus:latest
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
ports:
- "9090:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
grafana:
image: grafana/grafana:latest
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
volumes:
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning
- grafana_data:/var/lib/grafana
ports:
- "3001:3000"
depends_on:
- prometheus
# === DEVELOPMENT TOOLS ===
pgadmin:
image: dpage/pgadmin4:latest
environment:
PGADMIN_DEFAULT_EMAIL: admin@siga.local
PGADMIN_DEFAULT_PASSWORD: admin
ports:
- "5050:80"
depends_on:
- postgres
redisinsight:
image: redislabs/redisinsight:latest
ports:
- "8002:8001"
depends_on:
- redis
volumes:
postgres_data:
timescale_data:
redis_data:
ml_models:
prometheus_data:
grafana_data:
networks:
default:
name: siga_network
-- init-scripts/postgres/01-create-schema.sql
CREATE SCHEMA IF NOT EXISTS siga;
CREATE SCHEMA IF NOT EXISTS analytics;
-- Crear usuario para la aplicación
CREATE USER siga_app WITH PASSWORD 'app_password';
GRANT ALL PRIVILEGES ON SCHEMA siga TO siga_app;
GRANT CREATE ON DATABASE siga TO siga_app;
-- Extensiones necesarias
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "postgis";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
CREATE EXTENSION IF NOT EXISTS "btree_gist";
-- Configuración de rendimiento
ALTER SYSTEM SET shared_buffers = '4GB';
ALTER SYSTEM SET effective_cache_size = '12GB';
ALTER SYSTEM SET maintenance_work_mem = '1GB';
ALTER SYSTEM SET work_mem = '50MB';
ALTER SYSTEM SET max_connections = 200;
ALTER SYSTEM SET random_page_cost = 1.1;
# redis.conf
# Persistencia
save 900 1
save 300 10
save 60 10000
# Memoria
maxmemory 2gb
maxmemory-policy allkeys-lru
# Seguridad
requirepass your_redis_password
bind 0.0.0.0
protected-mode yes
# Performance
tcp-backlog 511
timeout 300
tcp-keepalive 300
# Logging
loglevel notice
logfile /var/log/redis/redis-server.log
# nginx/sites-available/siga
upstream api_backend {
least_conn;
server api1:8000 weight=5 max_fails=3 fail_timeout=30s;
server api2:8000 weight=5 max_fails=3 fail_timeout=30s;
server api3:8000 weight=5 max_fails=3 fail_timeout=30s;
keepalive 32;
}
upstream ml_backend {
server ml-service1:8001;
server ml-service2:8001;
keepalive 16;
}
server {
listen 80;
server_name siga.example.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name siga.example.com;
# SSL Configuration
ssl_certificate /etc/nginx/ssl/siga.crt;
ssl_certificate_key /etc/nginx/ssl/siga.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000" always;
# API Routes
location /api/ {
proxy_pass http://api_backend;
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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffer sizes
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
# Rate limiting
limit_req zone=api_limit burst=20 nodelay;
}
# ML Service Routes
location /ml/ {
proxy_pass http://ml_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Larger timeouts for ML predictions
proxy_connect_timeout 120s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
}
# Static Files
location / {
root /var/www/siga/build;
try_files $uri $uri/ /index.html;
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
# WebSocket for real-time tracking
location /ws/ {
proxy_pass http://api_backend;
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;
}
# Health checks
location /health {
access_log off;
return 200 "healthy\n";
}
}
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=ml_limit:10m rate=2r/s;
# k8s/00-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: siga
---
# k8s/01-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: siga-config
namespace: siga
data:
ENVIRONMENT: "production"
API_HOST: "0.0.0.0"
API_PORT: "8000"
LOG_LEVEL: "info"
# k8s/10-api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: siga-api
namespace: siga
spec:
replicas: 3
selector:
matchLabels:
app: siga-api
template:
metadata:
labels:
app: siga-api
spec:
containers:
- name: api
image: siga/api:latest
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: siga-secrets
key: database-url
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: siga-secrets
key: redis-url
envFrom:
- configMapRef:
name: siga-config
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8000
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: siga-api
namespace: siga
spec:
selector:
app: siga-api
ports:
- port: 80
targetPort: 8000
type: ClusterIP
# k8s/11-ml-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: siga-ml
namespace: siga
spec:
replicas: 2
selector:
matchLabels:
app: siga-ml
template:
metadata:
labels:
app: siga-ml
spec:
nodeSelector:
gpu: "true" # Asegurar nodos con GPU
containers:
- name: ml-service
image: siga/ml-service:latest
ports:
- containerPort: 8001
resources:
requests:
memory: "4Gi"
cpu: "2000m"
nvidia.com/gpu: 1
limits:
memory: "8Gi"
cpu: "4000m"
nvidia.com/gpu: 1
volumeMounts:
- name: model-storage
mountPath: /models
volumes:
- name: model-storage
persistentVolumeClaim:
claimName: ml-models-pvc
# Generar certificados con Let's Encrypt
sudo certbot certonly --standalone -d siga.example.com
# Auto-renovación
echo "0 0 * * * root certbot renew --quiet" >> /etc/crontab
# UFW Configuration
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Permitir SSH
sudo ufw allow 22/tcp
# Permitir HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Permitir puertos internos solo desde la red Docker
sudo ufw allow from 172.16.0.0/12 to any port 5432 # PostgreSQL
sudo ufw allow from 172.16.0.0/12 to any port 6379 # Redis
sudo ufw allow from 172.16.0.0/12 to any port 8000 # API
sudo ufw allow from 172.16.0.0/12 to any port 8001 # ML Service
# Activar firewall
sudo ufw enable
# k8s/02-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: siga-secrets
namespace: siga
type: Opaque
stringData:
database-url: "postgresql://user:pass@postgres:5432/siga"
redis-url: "redis://default:pass@redis:6379/0"
jwt-secret: "your-super-secret-jwt-key"
rtracktor-api-key: "your-api-key"
# monitoring/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'siga-api'
static_configs:
- targets: ['api:8000']
metrics_path: '/metrics'
- job_name: 'siga-ml'
static_configs:
- targets: ['ml-service:8001']
metrics_path: '/metrics'
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
- job_name: 'redis'
static_configs:
- targets: ['redis-exporter:9121']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
rule_files:
- 'alerts/*.yml'
// monitoring/grafana/dashboards/siga-overview.json
{
"dashboard": {
"title": "SIGA System Overview",
"panels": [
{
"title": "API Request Rate",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{method}} {{endpoint}}"
}
]
},
{
"title": "Empty KM Ratio",
"targets": [
{
"expr": "siga_empty_km_ratio",
"legendFormat": "Empty KM %"
}
]
},
{
"title": "ML Prediction Latency",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(ml_prediction_duration_seconds_bucket[5m]))",
"legendFormat": "95th percentile"
}
]
}
]
}
}
#!/bin/bash
# backup/backup.sh
# Variables
BACKUP_DIR="/backup/siga"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
S3_BUCKET="s3://siga-backups"
# Backup PostgreSQL
echo "Backing up PostgreSQL..."
PGPASSWORD=$POSTGRES_PASSWORD pg_dump \
-h $POSTGRES_HOST \
-U $POSTGRES_USER \
-d $POSTGRES_DB \
--format=custom \
--verbose \
--file="${BACKUP_DIR}/postgres_${TIMESTAMP}.dump"
# Backup TimescaleDB
echo "Backing up TimescaleDB..."
PGPASSWORD=$TIMESCALE_PASSWORD pg_dump \
-h $TIMESCALE_HOST \
-U $TIMESCALE_USER \
-d $TIMESCALE_DB \
--format=custom \
--verbose \
--file="${BACKUP_DIR}/timescale_${TIMESTAMP}.dump"
# Backup Redis
echo "Backing up Redis..."
redis-cli -h $REDIS_HOST -a $REDIS_PASSWORD --rdb "${BACKUP_DIR}/redis_${TIMESTAMP}.rdb"
# Compress backups
tar -czf "${BACKUP_DIR}/siga_backup_${TIMESTAMP}.tar.gz" \
"${BACKUP_DIR}/postgres_${TIMESTAMP}.dump" \
"${BACKUP_DIR}/timescale_${TIMESTAMP}.dump" \
"${BACKUP_DIR}/redis_${TIMESTAMP}.rdb"
# Upload to S3
aws s3 cp "${BACKUP_DIR}/siga_backup_${TIMESTAMP}.tar.gz" \
"${S3_BUCKET}/daily/${TIMESTAMP}/"
# Cleanup old backups (keep 30 days)
find ${BACKUP_DIR} -name "*.dump" -mtime +30 -delete
find ${BACKUP_DIR} -name "*.rdb" -mtime +30 -delete
find ${BACKUP_DIR} -name "*.tar.gz" -mtime +30 -delete
# Crontab entries
# Daily backup at 2 AM
0 2 * * * /backup/backup.sh >> /var/log/siga-backup.log 2>&1
# Weekly full backup on Sunday
0 3 * * 0 /backup/full-backup.sh >> /var/log/siga-backup.log 2>&1
# Monthly backup verification
0 4 1 * * /backup/verify-backups.sh >> /var/log/siga-backup.log 2>&1
# Verificar conectividad
psql -h localhost -U siga_user -d siga -c "SELECT 1"
# Verificar logs
docker logs siga_postgres_1 --tail 50
# Reiniciar servicio
docker-compose restart postgres
# Verificar uso de memoria
redis-cli -a $REDIS_PASSWORD info memory
# Limpiar cache
redis-cli -a $REDIS_PASSWORD FLUSHDB
# Ajustar maxmemory
redis-cli -a $REDIS_PASSWORD CONFIG SET maxmemory 4gb
# Verificar métricas
curl http://localhost:8000/metrics | grep http_request_duration
# Profiling
python -m cProfile -o profile.stats app/main.py
# Analizar con snakeviz
snakeviz profile.stats
⬅️ Volver a Documentación Técnica | ➡️ Siguiente: Manual Usuario