coconews/DEPLOY_DEBIAN.md
SITO ab3b0b53c5 fix(deploy): corregir 5 problemas bloqueantes para despliegue Debian
- install.sh/build.sh: actualizar Go 1.23 → 1.25 (requerido por rss-ingestor-go)
- install.sh/build.sh: nombrar binario qdrant como qdrant_worker para
  coincidir con rss2-qdrant-worker.service (ExecStart)
- install.sh/build.sh: GOTOOLCHAIN=local en ingestor para evitar
  descarga automatica de toolchain Go superior
- rss2-backend.service: sobreescribir hostnames Docker (libretranslate,
  ollama, spacy) por 127.0.0.1 para despliegue nativo
- env.example: agregar TRANSLATION_URL, OLLAMA_URL, SPACY_URL con nota
  explicativa sobre uso en endpoints admin
- DEPLOY_DEBIAN.md: corregir comando conversion NLLB-200 a CTranslate2
  usando OpusMTConverter Python API en lugar de CLI incorrecto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 21:11:56 +02:00

7.4 KiB

COCONEWS · Despliegue en Debian (sin Docker)

Guía completa para instalar y operar COCONEWS en un servidor Debian 12 (Bookworm) o Ubuntu 22.04+, sin Docker ni contenedores.


Requisitos de hardware

Modo CPU RAM Disco
Mínimo (solo CPU) 4 cores 8 GB 40 GB
Recomendado 8 cores 16 GB 80 GB
Con GPU 8 cores + NVIDIA 16 GB 80 GB

Los modelos de IA (NLLB-200 + MiniLM + spaCy) ocupan ~5 GB en disco una vez descargados.


Servicios que se instalan en el servidor

Servicio Tecnología Gestionado por
Base de datos PostgreSQL 16 apt + systemd
Caché Redis 7 apt + systemd
Búsqueda vectorial Qdrant (binario) systemd
API REST Go (backend) systemd
Ingestor RSS Go systemd
Scraper / Discovery / Wiki / Topics / Related / Qdrant-worker Go systemd
Traducción (NLLB-200) Python + CTranslate2 systemd
Embeddings Python + Sentence-Transformers systemd
NER Python + spaCy systemd
Clustering / Categorización Python systemd
Frontend React (estático compilado) nginx
Proxy / Web nginx apt + systemd

Instalación paso a paso

1. Clonar el repositorio

git clone https://gitea.laenre.net/pietre/rss2.git /opt/src/rss2
cd /opt/src/rss2
git checkout coconews

2. Configurar variables de entorno

cp deploy/debian/env.example /opt/rss2/.env
nano /opt/rss2/.env

Valores que debes cambiar obligatoriamente:

POSTGRES_PASSWORD=contraseña_segura_postgres
DB_PASS=contraseña_segura_postgres
REDIS_PASSWORD=contraseña_segura_redis
SECRET_KEY=cadena_aleatoria_minimo_32_caracteres

Genera claves seguras con:

openssl rand -hex 32

3. Descargar y convertir el modelo de traducción (NLLB-200)

Este paso se hace una sola vez y puede tardar 10-30 minutos dependiendo de la conexión.

# Instalar dependencias Python primero (si aun no se hizo)
python3 -m venv /opt/rss2/venv
/opt/rss2/venv/bin/pip install ctranslate2 transformers sentencepiece

# Convertir modelo NLLB-200 a formato CTranslate2 (tarda 10-30 min)
/opt/rss2/venv/bin/python - <<'EOF'
from ctranslate2.converters import OpusMTConverter
converter = OpusMTConverter("facebook/nllb-200-distilled-600M")
converter.convert("/opt/rss2/models/nllb-ct2", quantization="int8", force=True)
print("Modelo convertido OK en /opt/rss2/models/nllb-ct2")
EOF

El modelo ocupa ~600 MB convertido. Si la descarga de HuggingFace falla, exporta HF_ENDPOINT=https://huggingface.co o usa un mirror.

4. Ejecutar el instalador

sudo bash /opt/src/rss2/deploy/debian/install.sh

El script hace automáticamente:

  • Instala PostgreSQL, Redis, nginx, Go, Node.js via apt
  • Descarga el binario de Qdrant
  • Crea el usuario rss2 del sistema
  • Crea la base de datos y ejecuta las migraciones
  • Compila los 8 binarios Go
  • Compila el frontend React
  • Instala y habilita los 16 servicios systemd

Verificar que funciona

# Estado de todos los servicios
systemctl status rss2-backend rss2-ingestor rss2-translator rss2-embeddings

# Ver logs en tiempo real
journalctl -u rss2-backend -f
journalctl -u rss2-translator -f

# Comprobar que el API responde
curl http://localhost:8080/api/stats

# Acceder al frontend
# http://IP_DEL_SERVIDOR:8001

Gestión de servicios

Iniciar / parar / reiniciar

# Un servicio concreto
systemctl start rss2-backend
systemctl stop rss2-translator
systemctl restart rss2-embeddings

# Todos los workers de una vez
systemctl restart rss2-backend rss2-ingestor rss2-scraper rss2-discovery \
    rss2-wiki rss2-topics rss2-related rss2-qdrant-worker \
    rss2-langdetect rss2-translation-scheduler rss2-translator \
    rss2-embeddings rss2-ner rss2-cluster rss2-categorizer

Ver logs

journalctl -u rss2-backend        -f   # API Go
journalctl -u rss2-translator     -f   # Traductor
journalctl -u rss2-embeddings     -f   # Embeddings
journalctl -u rss2-ner            -f   # NER entidades
journalctl -u rss2-ingestor       -f   # Ingestor RSS

Actualizar el código

Cuando hay nuevos cambios en el repositorio:

cd /opt/src/rss2
git pull
sudo bash deploy/debian/build.sh

El script build.sh recompila los binarios Go, el frontend y sincroniza los workers Python, y reinicia los servicios automáticamente.


Estructura de directorios en el servidor

/opt/rss2/
├── .env                    # Variables de entorno (permisos 600)
├── bin/                    # Binarios Go compilados
│   ├── server              # API REST
│   ├── ingestor            # Ingestor RSS
│   ├── scraper
│   ├── discovery
│   ├── wiki_worker
│   ├── topics
│   ├── related
│   └── qdrant_worker
├── src/
│   └── workers/            # Workers Python
├── venv/                   # Virtualenv Python (ML)
├── models/
│   └── nllb-ct2/           # Modelo traduccion CTranslate2
├── hf_cache/               # Cache HuggingFace (embeddings, NER)
├── frontend/
│   └── dist/               # Frontend React compilado (servido por nginx)
├── data/
│   ├── wiki_images/        # Imagenes Wikipedia descargadas
│   └── qdrant_storage/     # Datos vectoriales Qdrant
└── qdrant/
    └── qdrant              # Binario Qdrant

Requisitos de red / firewall

Solo exponer al exterior el puerto 8001 (nginx). El resto deben ser internos:

# Con ufw:
ufw allow 8001/tcp   # COCONEWS web
ufw deny 5432/tcp    # PostgreSQL - solo localhost
ufw deny 6379/tcp    # Redis - solo localhost
ufw deny 6333/tcp    # Qdrant - solo localhost
ufw deny 8080/tcp    # API Go - solo localhost (nginx hace proxy)
ufw enable

Backup de datos

# PostgreSQL
sudo -u postgres pg_dump rss > /opt/rss2/backups/rss_$(date +%Y%m%d).sql

# Datos Qdrant
systemctl stop rss2-qdrant
tar -czf /opt/rss2/backups/qdrant_$(date +%Y%m%d).tar.gz /opt/rss2/data/qdrant_storage
systemctl start rss2-qdrant

# Imagenes Wikipedia (opcional, se pueden re-descargar)
tar -czf /opt/rss2/backups/wiki_images_$(date +%Y%m%d).tar.gz /opt/rss2/data/wiki_images

Solución de problemas frecuentes

El traductor no arranca

journalctl -u rss2-translator -n 50
# Si dice "model not found": el modelo NLLB-200 no está convertido
# Ejecutar el paso 3 de la instalación

PostgreSQL rechaza la conexión

# Verificar que el .env tiene DB_HOST=127.0.0.1 (no "db")
grep DB_HOST /opt/rss2/.env

# Verificar que el usuario existe
sudo -u postgres psql -c "\du"

nginx devuelve 502 Bad Gateway

# El backend Go no está corriendo
systemctl status rss2-backend
journalctl -u rss2-backend -n 30

Memoria insuficiente para los modelos Python

Con 8 GB RAM el translator + embeddings + NER pueden coincidir. Si el servidor tiene poca RAM, deshabilitar el translator-gpu y bajar el batch:

# En /opt/rss2/.env
TRANSLATOR_BATCH=8
EMB_BATCH=32
NER_BATCH=16
systemctl restart rss2-translator rss2-embeddings rss2-ner

Primer inicio de sesión

  1. Abrir http://IP:8001 en el navegador
  2. Al no haber usuarios, el sistema te redirige al registro
  3. El primer usuario registrado se convierte en administrador
  4. Ir a Configuración → Feeds → Importar el feeds.csv del repositorio para empezar con fuentes precargadas