Guía de Instalación Completa
Stack completo: Claude AI · Gemini · N8N · PostgreSQL · Redis · Nginx. Dos rutas de despliegue: contenedores Docker o servidor bare-metal. Elige la que mejor se adapte a tu entorno.
📖 Visión general
Esta guía te lleva desde un servidor vacío hasta un sistema completamente funcional con automatización de IA. El stack que vas a instalar incluye:
- Claude (Anthropic) + Gemini (Google) — modelos de IA integrados vía API para razonamiento y procesamiento multimodal
- N8N — orquestador de flujos self-hosted que conecta todo sin depender de plataformas externas
- PostgreSQL 16 — base de datos principal con soporte para pgvector (embeddings de IA)
- Redis 7 — caché, sesiones de usuario y colas de mensajes asíncronos
- Nginx — reverse proxy con SSL automático, rate limiting y caché HTTP
- Docker Compose (opción A) — todos los servicios en contenedores aislados y reproducibles
- Bare-metal con PM2 (opción B) — instalación directa en el servidor para máximo control
⚖️ Docker vs Bare-metal
Ambas rutas llegan al mismo resultado. La diferencia está en el nivel de control, facilidad de mantenimiento y requisitos del entorno.
| Aspecto | 🐳 Docker | 🖥️ Bare-metal |
|---|---|---|
| Facilidad de instalación | ✓ Alta — un solo comando | ⚠ Media — paso a paso |
| Aislamiento de servicios | ✓ Total | ⚠ Parcial (systemd) |
| Performance | ⚠ Overhead mínimo | ✓ Máximo |
| Reproducibilidad | ✓ Exacta en cualquier servidor | ✗ Depende del OS |
| Actualizaciones | ✓ Fácil — rebuild imagen | ⚠ Manual por servicio |
| Debugging | ⚠ Requiere conocer Docker | ✓ Directo en el sistema |
| Recomendado para | Equipos, múltiples ambientes, CI/CD | Servidor dedicado de producción |
Recomendación FMV InfraSec: Empieza con Docker para desarrollo y staging. Migra a bare-metal solo si necesitas exprimir el hardware al máximo en producción con mucho tráfico.
✅ Prerrequisitos
Antes de elegir tu ruta, asegúrate de tener lo siguiente:
Servidor recomendado
- RAM: mínimo 4 GB (recomendado 8 GB para N8N + IA)
- CPU: 2 vCPUs mínimo, 4 recomendado
- Disco: 40 GB SSD mínimo
- OS: Ubuntu 22.04 LTS o Debian 12
- Puertos abiertos: 22 (SSH), 80 (HTTP), 443 (HTTPS)
- API Keys: Anthropic (Claude) y Google AI Studio (Gemini)
- Dominio: con DNS apuntando al servidor (para SSL)
Acceso inicial al servidor
# Conectarse por SSH
ssh root@TU_IP_SERVIDOR
# Actualizar el sistema
apt update && apt upgrade -y
# Instalar herramientas básicas
apt install -y curl wget git ufw fail2ban unzip
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status
🐳 Ruta A — Docker Compose
Todos los servicios corren en contenedores aislados. Un único archivo docker-compose.yml define y orquesta toda la infraestructura.
Estructura del proyecto
docker-compose.yml
version: '3.9'
networks:
fmv-net:
driver: bridge
volumes:
postgres_data:
redis_data:
n8n_data:
nginx_certs:
services:
# ─── PostgreSQL ───────────────────────────
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
networks: [fmv-net]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 10s
retries: 5
# ─── Redis ────────────────────────────────
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks: [fmv-net]
# ─── Backend API ──────────────────────────
backend:
build: ./backend
restart: unless-stopped
env_file: .env
depends_on:
postgres: { condition: service_healthy }
redis: { condition: service_started }
networks: [fmv-net]
expose: ["3000"]
# ─── N8N ──────────────────────────────────
n8n:
image: n8nio/n8n:latest
restart: unless-stopped
environment:
N8N_HOST: ${N8N_HOST}
N8N_PORT: 5678
N8N_PROTOCOL: https
N8N_BASIC_AUTH_ACTIVE: true
N8N_BASIC_AUTH_USER: ${N8N_USER}
N8N_BASIC_AUTH_PASSWORD: ${N8N_PASSWORD}
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: ${DB_NAME}
DB_POSTGRESDB_USER: ${DB_USER}
DB_POSTGRESDB_PASSWORD: ${DB_PASSWORD}
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PASSWORD: ${REDIS_PASSWORD}
volumes:
- n8n_data:/home/node/.n8n
depends_on: [postgres, redis]
networks: [fmv-net]
expose: ["5678"]
# ─── Nginx ────────────────────────────────
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/sites:/etc/nginx/conf.d
- nginx_certs:/etc/letsencrypt
depends_on: [backend, n8n]
networks: [fmv-net]
Variables de entorno (.env)
# ── Base de datos ──────────────────────
DB_NAME=fmvinfrasec
DB_USER=fmvadmin
DB_PASSWORD=CAMBIA_ESTA_CONTRASENA_SEGURA
# ── Redis ──────────────────────────────
REDIS_PASSWORD=CAMBIA_REDIS_PASSWORD
# ── N8N ────────────────────────────────
N8N_HOST=n8n.tudominio.com
N8N_USER=admin
N8N_PASSWORD=CAMBIA_N8N_PASSWORD
# ── IA APIs ────────────────────────────
ANTHROPIC_API_KEY=sk-ant-XXXXXXXXXXXXXXXXXXXX
GOOGLE_AI_API_KEY=AIzaSyXXXXXXXXXXXXXXXXXXX
# ── App ────────────────────────────────
APP_URL=https://tudominio.com
NODE_ENV=production
JWT_SECRET=GENERA_UN_SECRET_LARGO_Y_ALEATORIO
Nunca subas el .env a Git. Asegúrate de que .env esté en tu .gitignore. Usa un gestor de secretos (Vault, AWS Secrets Manager) en producción.
Configuración de Nginx
# Redirección HTTP → HTTPS
server {
listen 80;
server_name tudominio.com n8n.tudominio.com;
return 301 https://$host$request_uri;
}
# App principal
server {
listen 443 ssl http2;
server_name tudominio.com;
ssl_certificate /etc/letsencrypt/live/tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tudominio.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Headers de seguridad
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000";
add_header Content-Security-Policy "default-src 'self'";
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
location / {
proxy_pass http://backend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
limit_req zone=api burst=10 nodelay;
}
}
# N8N
server {
listen 443 ssl http2;
server_name n8n.tudominio.com;
ssl_certificate /etc/letsencrypt/live/tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tudominio.com/privkey.pem;
location / {
proxy_pass http://n8n:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
Despliegue
Instalar Docker y Docker Compose
curl -fsSL https://get.docker.com | sh
systemctl enable docker && systemctl start docker
docker --version && docker compose versionClonar el repositorio y configurar
git clone https://github.com/tuusuario/fmv-infrasec.git
cd fmv-infrasec
cp .env.example .env
nano .env # Completar con tus valores realesLevantar todos los servicios
docker compose up -d --build
docker compose ps # verificar estado
docker compose logs -f # ver logs en tiempo realSSL con Let's Encrypt (Certbot)
apt install certbot -y
# Detener Nginx temporalmente para el challenge
docker compose stop nginx
certbot certonly --standalone \
-d tudominio.com \
-d n8n.tudominio.com \
--email admin@tudominio.com \
--agree-tos --non-interactive
# Reiniciar todo
docker compose start nginx
# Renovación automática
echo "0 0 1 * * certbot renew --quiet && docker compose restart nginx" | crontab -🖥️ Ruta B — Bare-metal
Instalación directa en el sistema operativo. Mayor control y performance, sin overhead de contenedores. Requiere más pasos pero es ideal para servidores dedicados.
Instalar Node.js 20 LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
node --version && npm --versionPostgreSQL 16
Instalar PostgreSQL
apt install -y postgresql postgresql-contrib
systemctl enable postgresql && systemctl start postgresql
psql --versionCrear base de datos y usuario
sudo -u postgres psql
CREATE USER fmvadmin WITH PASSWORD 'CONTRASENA_SEGURA';
CREATE DATABASE fmvinfrasec OWNER fmvadmin;
GRANT ALL PRIVILEGES ON DATABASE fmvinfrasec TO fmvadmin;
-- Instalar extensión para embeddings de IA
\c fmvinfrasec
CREATE EXTENSION IF NOT EXISTS vector;
\qRedis 7
apt install -y redis-server
systemctl enable redis-server
# Configurar contraseña y bind
sed -i 's/# requirepass.*/requirepass TU_REDIS_PASSWORD/' /etc/redis/redis.conf
sed -i 's/bind 127.0.0.1.*/bind 127.0.0.1/' /etc/redis/redis.conf
systemctl restart redis-server
redis-cli -a TU_REDIS_PASSWORD ping # → PONGN8N
# Instalar N8N globalmente
npm install -g n8n
# Crear usuario del sistema para N8N
useradd -r -s /bin/false n8nuser
mkdir -p /home/n8nuser/.n8n
chown -R n8nuser:n8nuser /home/n8nuser
# Crear servicio systemd
cat > /etc/systemd/system/n8n.service << 'EOF'
[Unit]
Description=N8N Workflow Automation
After=network.target postgresql.service redis-server.service
[Service]
Type=simple
User=n8nuser
WorkingDirectory=/home/n8nuser
Environment=N8N_HOST=n8n.tudominio.com
Environment=N8N_PORT=5678
Environment=N8N_PROTOCOL=https
Environment=N8N_BASIC_AUTH_ACTIVE=true
Environment=N8N_BASIC_AUTH_USER=admin
Environment=N8N_BASIC_AUTH_PASSWORD=TU_N8N_PASSWORD
Environment=DB_TYPE=postgresdb
Environment=DB_POSTGRESDB_HOST=localhost
Environment=DB_POSTGRESDB_DATABASE=fmvinfrasec
Environment=DB_POSTGRESDB_USER=fmvadmin
Environment=DB_POSTGRESDB_PASSWORD=TU_DB_PASSWORD
ExecStart=/usr/bin/n8n start
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable n8n && systemctl start n8n
systemctl status n8nBackend (API Node.js)
cd /opt
git clone https://github.com/tuusuario/fmv-backend.git
cd fmv-backend
npm install --production
cp .env.example .env && nano .envPM2 — Gestor de procesos
npm install -g pm2
cd /opt/fmv-backend
pm2 start src/index.js --name "fmv-api" --instances 2 --exec-mode cluster
# Persistir entre reinicios
pm2 save
pm2 startup systemd
# Ejecuta el comando que PM2 te indique
pm2 status # ver estado
pm2 logs # ver logs
pm2 monit # monitor en tiempo realNginx en bare-metal
apt install -y nginx certbot python3-certbot-nginx
# Obtener SSL
certbot --nginx -d tudominio.com -d n8n.tudominio.com \
--email admin@tudominio.com --agree-tos --non-interactive
# Crear virtual host
cat > /etc/nginx/sites-available/fmv << 'EOF'
server {
listen 443 ssl http2;
server_name tudominio.com;
ssl_certificate /etc/letsencrypt/live/tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tudominio.com/privkey.pem;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000";
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
}
server {
listen 443 ssl http2;
server_name n8n.tudominio.com;
ssl_certificate /etc/letsencrypt/live/tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tudominio.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
EOF
ln -s /etc/nginx/sites-available/fmv /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx🤖 Integración de IA
Claude AI (Anthropic)
Integración vía SDK oficial de Anthropic. Instala en tu backend:
npm install @anthropic-ai/sdkimport Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
// Función reutilizable para tu web
export async function askClaude(userMessage, systemPrompt = '') {
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: systemPrompt,
messages: [{ role: 'user', content: userMessage }],
});
return response.content[0].text;
}
// Endpoint REST para tu frontend
// POST /api/ai/claude
export async function claudeEndpoint(req, res) {
try {
const { message, context } = req.body;
const reply = await askClaude(message, context);
res.json({ reply, model: 'claude-sonnet-4-6' });
} catch (err) {
res.status(500).json({ error: err.message });
}
}Gemini (Google AI)
npm install @google/generative-aiimport { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_AI_API_KEY);
export async function askGemini(prompt) {
const model = genAI.getGenerativeModel({ model: 'gemini-1.5-pro' });
const result = await model.generateContent(prompt);
return result.response.text();
}Flujos N8N para automatizar tu web
N8N se accede en https://n8n.tudominio.com. Inicia sesión con las credenciales configuradas en tu .env y crea flujos desde la interfaz visual.
Flujos recomendados para automatizar tu web FMV InfraSec:
- Formulario de contacto → Claude → Email: cuando un usuario llena el formulario, Claude analiza el mensaje, lo clasifica (soporte, ventas, auditoría) y genera una respuesta inicial automática
- Webhook → Análisis de logs → Alerta: recibe eventos de seguridad, Claude los analiza y si detecta anomalías envía alerta por Slack o email
- Chatbot de la web → Claude API → Redis caché: el chatbot del sitio consulta a Claude, Redis cachea respuestas frecuentes para reducir costos de API
- CRM → Gemini → Reporte semanal: cada lunes, extrae datos del CRM y Gemini genera un resumen ejecutivo automático para el equipo
🛡️ Post-instalación: Hardening
Configuración de Fail2ban
apt install -y fail2ban
cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true
[nginx-http-auth]
enabled = true
EOF
systemctl enable fail2ban && systemctl restart fail2banMonitoreo básico
# Instalar Netdata para métricas en tiempo real
wget -O /tmp/netdata-kickstart.sh https://get.netdata.cloud/kickstart.sh
bash /tmp/netdata-kickstart.sh
# Ver estado de todos los servicios
systemctl status postgresql redis-server nginx n8n
# Docker: ver uso de recursos
docker statsBackups automáticos de PostgreSQL
# Script de backup
cat > /opt/backup-db.sh << 'EOF'
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR=/var/backups/postgres
mkdir -p $BACKUP_DIR
# Docker
docker exec postgres pg_dump -U fmvadmin fmvinfrasec | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# Bare-metal
# pg_dump -U fmvadmin fmvinfrasec | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# Eliminar backups más viejos de 30 días
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete
echo "Backup $DATE completado"
EOF
chmod +x /opt/backup-db.sh
# Ejecutar cada día a las 3 AM
echo "0 3 * * * /opt/backup-db.sh >> /var/log/backup.log 2>&1" | crontab -Checklist final: Firewall activo · SSL instalado · Fail2ban corriendo · Backups programados · Logs rotando · Variables de entorno seguras · API keys con permisos mínimos.
¿Necesitas ayuda con la implementación?
El equipo de FMV InfraSec puede hacer la instalación, configuración y hardening por ti.
Contactar al equipo →