- 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>
299 lines
11 KiB
Bash
Executable file
299 lines
11 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# RSS2 - Instalacion en Debian (sin Docker)
|
|
# Ejecutar como root: bash install.sh
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
RSS2_USER="rss2"
|
|
RSS2_HOME="/opt/rss2"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }
|
|
|
|
[[ "$EUID" -ne 0 ]] && error "Ejecutar como root: sudo bash install.sh"
|
|
|
|
# =============================================================================
|
|
# 1. DEPENDENCIAS DEL SISTEMA
|
|
# =============================================================================
|
|
info "Instalando dependencias del sistema..."
|
|
apt-get update -qq
|
|
apt-get install -y --no-install-recommends \
|
|
curl wget git build-essential \
|
|
postgresql postgresql-client \
|
|
redis-server \
|
|
nginx \
|
|
python3 python3-pip python3-venv python3-dev \
|
|
nodejs npm \
|
|
ca-certificates tzdata \
|
|
libpq-dev
|
|
|
|
# Go (rss-ingestor-go requiere Go 1.25)
|
|
if ! command -v go &>/dev/null || [[ "$(go version | awk '{print $3}' | tr -d 'go')" < "1.25" ]]; then
|
|
info "Instalando Go 1.25..."
|
|
GO_VERSION="1.25.0"
|
|
ARCH=$(dpkg --print-architecture)
|
|
case "$ARCH" in
|
|
amd64) GO_ARCH="amd64" ;;
|
|
arm64) GO_ARCH="arm64" ;;
|
|
*) error "Arquitectura no soportada: $ARCH" ;;
|
|
esac
|
|
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" -o /tmp/go.tar.gz
|
|
rm -rf /usr/local/go
|
|
tar -C /usr/local -xzf /tmp/go.tar.gz
|
|
echo 'export PATH=$PATH:/usr/local/go/bin' > /etc/profile.d/go.sh
|
|
export PATH=$PATH:/usr/local/go/bin
|
|
rm /tmp/go.tar.gz
|
|
fi
|
|
info "Go: $(go version)"
|
|
|
|
# Qdrant (binario oficial)
|
|
if [[ ! -f "$RSS2_HOME/qdrant/qdrant" ]]; then
|
|
info "Descargando Qdrant..."
|
|
QDRANT_VERSION="v1.12.1"
|
|
ARCH=$(dpkg --print-architecture)
|
|
case "$ARCH" in
|
|
amd64) QDRANT_ARCH="x86_64-unknown-linux-musl" ;;
|
|
arm64) QDRANT_ARCH="aarch64-unknown-linux-musl" ;;
|
|
*) error "Arquitectura no soportada para Qdrant: $ARCH" ;;
|
|
esac
|
|
mkdir -p "$RSS2_HOME/qdrant"
|
|
curl -fsSL "https://github.com/qdrant/qdrant/releases/download/${QDRANT_VERSION}/qdrant-${QDRANT_ARCH}.tar.gz" \
|
|
-o /tmp/qdrant.tar.gz
|
|
tar -C "$RSS2_HOME/qdrant" -xzf /tmp/qdrant.tar.gz
|
|
chmod +x "$RSS2_HOME/qdrant/qdrant"
|
|
rm /tmp/qdrant.tar.gz
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 2. USUARIO Y DIRECTORIOS
|
|
# =============================================================================
|
|
info "Creando usuario $RSS2_USER y directorios..."
|
|
id "$RSS2_USER" &>/dev/null || useradd -r -m -d "$RSS2_HOME" -s /bin/bash "$RSS2_USER"
|
|
|
|
mkdir -p \
|
|
"$RSS2_HOME/bin" \
|
|
"$RSS2_HOME/src" \
|
|
"$RSS2_HOME/data/wiki_images" \
|
|
"$RSS2_HOME/data/qdrant_storage" \
|
|
"$RSS2_HOME/hf_cache" \
|
|
"$RSS2_HOME/models" \
|
|
"$RSS2_HOME/frontend/dist" \
|
|
"$RSS2_HOME/logs"
|
|
|
|
# =============================================================================
|
|
# 3. CONFIGURACION ENTORNO
|
|
# =============================================================================
|
|
if [[ ! -f "$RSS2_HOME/.env" ]]; then
|
|
if [[ -f "$SCRIPT_DIR/env.example" ]]; then
|
|
cp "$SCRIPT_DIR/env.example" "$RSS2_HOME/.env"
|
|
warn "Copia env.example en $RSS2_HOME/.env - EDITA LAS CONTRASENAS antes de continuar"
|
|
warn "Presiona Enter cuando hayas editado el .env, o Ctrl+C para salir"
|
|
read -r
|
|
else
|
|
error "No se encontro env.example en $SCRIPT_DIR"
|
|
fi
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 4. POSTGRESQL
|
|
# =============================================================================
|
|
info "Configurando PostgreSQL..."
|
|
source "$RSS2_HOME/.env" 2>/dev/null || true
|
|
|
|
DB_NAME="${POSTGRES_DB:-rss}"
|
|
DB_USER="${POSTGRES_USER:-rss}"
|
|
DB_PASS="${POSTGRES_PASSWORD:-changeme}"
|
|
|
|
systemctl enable --now postgresql
|
|
|
|
# Crear usuario y base de datos si no existen
|
|
sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" | grep -q 1 || \
|
|
sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASS';"
|
|
|
|
sudo -u postgres psql -tc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" | grep -q 1 || \
|
|
sudo -u postgres createdb -O "$DB_USER" "$DB_NAME"
|
|
|
|
# Ejecutar migraciones SQL
|
|
if [[ -d "$REPO_ROOT/migrations" ]]; then
|
|
info "Ejecutando migraciones..."
|
|
for sql_file in "$REPO_ROOT/migrations"/*.sql; do
|
|
[[ -f "$sql_file" ]] || continue
|
|
info " Aplicando $(basename "$sql_file")..."
|
|
sudo -u postgres psql -d "$DB_NAME" -f "$sql_file" 2>/dev/null || warn " (ya aplicada o error ignorado)"
|
|
done
|
|
fi
|
|
|
|
# Ejecutar init-db scripts (schema inicial)
|
|
if [[ -d "$REPO_ROOT/init-db" ]]; then
|
|
info "Ejecutando scripts de init-db..."
|
|
for sql_file in "$REPO_ROOT/init-db"/*.sql; do
|
|
[[ -f "$sql_file" ]] || continue
|
|
info " $(basename "$sql_file")..."
|
|
sudo -u postgres psql -d "$DB_NAME" -f "$sql_file" 2>/dev/null || warn " (ya aplicada o error ignorado)"
|
|
done
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 5. REDIS
|
|
# =============================================================================
|
|
info "Configurando Redis..."
|
|
REDIS_PASS="${REDIS_PASSWORD:-changeme_redis}"
|
|
|
|
# Agregar autenticacion y limites de memoria a redis.conf
|
|
REDIS_CONF="/etc/redis/redis.conf"
|
|
grep -q "requirepass $REDIS_PASS" "$REDIS_CONF" 2>/dev/null || {
|
|
echo "requirepass $REDIS_PASS" >> "$REDIS_CONF"
|
|
echo "maxmemory 512mb" >> "$REDIS_CONF"
|
|
echo "maxmemory-policy allkeys-lru" >> "$REDIS_CONF"
|
|
echo "appendonly yes" >> "$REDIS_CONF"
|
|
}
|
|
systemctl enable --now redis-server
|
|
|
|
# =============================================================================
|
|
# 6. PYTHON VIRTUALENV + DEPENDENCIAS ML
|
|
# =============================================================================
|
|
info "Creando virtualenv Python y instalando dependencias..."
|
|
python3 -m venv "$RSS2_HOME/venv"
|
|
"$RSS2_HOME/venv/bin/pip" install --upgrade pip -q
|
|
|
|
if [[ -f "$REPO_ROOT/requirements.txt" ]]; then
|
|
"$RSS2_HOME/venv/bin/pip" install -r "$REPO_ROOT/requirements.txt" -q
|
|
fi
|
|
|
|
# spaCy modelo en español
|
|
"$RSS2_HOME/venv/bin/python" -m spacy download es_core_news_lg 2>/dev/null || \
|
|
warn "spaCy model es_core_news_lg no se pudo descargar, hazlo manualmente"
|
|
|
|
# Copiar workers Python al directorio de trabajo
|
|
info "Copiando workers Python..."
|
|
rsync -a --delete "$REPO_ROOT/workers/" "$RSS2_HOME/src/workers/"
|
|
cp "$REPO_ROOT/entity_config.json" "$RSS2_HOME/src/" 2>/dev/null || true
|
|
|
|
# =============================================================================
|
|
# 7. COMPILAR GO (backend + workers)
|
|
# =============================================================================
|
|
info "Compilando binarios Go..."
|
|
export PATH=$PATH:/usr/local/go/bin
|
|
export GOPATH=/tmp/go-build-rss2
|
|
|
|
# Backend API
|
|
if [[ -d "$REPO_ROOT/backend" ]]; then
|
|
(cd "$REPO_ROOT/backend" && \
|
|
CGO_ENABLED=0 GOOS=linux go build -buildvcs=false -o "$RSS2_HOME/bin/server" ./cmd/server && \
|
|
info " [OK] server") || warn " [FAIL] server"
|
|
for cmd in scraper discovery wiki_worker topics related; do
|
|
[[ -d "$REPO_ROOT/backend/cmd/$cmd" ]] || continue
|
|
(cd "$REPO_ROOT/backend" && \
|
|
CGO_ENABLED=0 GOOS=linux go build -buildvcs=false -o "$RSS2_HOME/bin/$cmd" "./cmd/$cmd" && \
|
|
info " [OK] $cmd") || warn " [FAIL] $cmd"
|
|
done
|
|
# qdrant worker: output como qdrant_worker para coincidir con el service
|
|
[[ -d "$REPO_ROOT/backend/cmd/qdrant" ]] && \
|
|
(cd "$REPO_ROOT/backend" && \
|
|
CGO_ENABLED=0 GOOS=linux go build -buildvcs=false -o "$RSS2_HOME/bin/qdrant_worker" "./cmd/qdrant" && \
|
|
info " [OK] qdrant_worker") || warn " [FAIL] qdrant_worker"
|
|
fi
|
|
|
|
# RSS Ingestor Go (repo separado, requiere Go 1.25)
|
|
if [[ -d "$REPO_ROOT/rss-ingestor-go" ]]; then
|
|
(cd "$REPO_ROOT/rss-ingestor-go" && \
|
|
GOTOOLCHAIN=local CGO_ENABLED=0 GOOS=linux go build -buildvcs=false -o "$RSS2_HOME/bin/ingestor" . && \
|
|
info " [OK] ingestor") || warn " [FAIL] ingestor"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 8. FRONTEND REACT
|
|
# =============================================================================
|
|
info "Compilando frontend React..."
|
|
if [[ -d "$REPO_ROOT/frontend" ]]; then
|
|
(cd "$REPO_ROOT/frontend" && \
|
|
npm install --silent && \
|
|
VITE_API_URL=/api npm run build -- --outDir "$RSS2_HOME/frontend/dist" && \
|
|
info " [OK] frontend compilado") || warn " [FAIL] frontend"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 9. NGINX
|
|
# =============================================================================
|
|
info "Configurando Nginx..."
|
|
cp "$SCRIPT_DIR/nginx.conf" /etc/nginx/nginx.conf
|
|
nginx -t && systemctl enable --now nginx && systemctl reload nginx
|
|
|
|
# =============================================================================
|
|
# 10. SYSTEMD SERVICES
|
|
# =============================================================================
|
|
info "Instalando servicios systemd..."
|
|
SERVICES=(
|
|
rss2-qdrant
|
|
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
|
|
)
|
|
|
|
for svc in "${SERVICES[@]}"; do
|
|
svc_file="$SCRIPT_DIR/systemd/${svc}.service"
|
|
if [[ -f "$svc_file" ]]; then
|
|
cp "$svc_file" "/etc/systemd/system/${svc}.service"
|
|
else
|
|
warn "No se encontro $svc_file"
|
|
fi
|
|
done
|
|
|
|
systemctl daemon-reload
|
|
|
|
for svc in "${SERVICES[@]}"; do
|
|
systemctl enable "$svc" 2>/dev/null || true
|
|
done
|
|
|
|
# =============================================================================
|
|
# 11. PERMISOS FINALES
|
|
# =============================================================================
|
|
info "Ajustando permisos..."
|
|
chown -R "$RSS2_USER:$RSS2_USER" "$RSS2_HOME"
|
|
chmod 600 "$RSS2_HOME/.env"
|
|
|
|
# =============================================================================
|
|
# 12. ARRANCAR SERVICIOS
|
|
# =============================================================================
|
|
info "Arrancando servicios..."
|
|
# Infraestructura primero
|
|
systemctl start rss2-qdrant
|
|
sleep 3
|
|
|
|
# API y workers Go
|
|
for svc in rss2-backend rss2-ingestor rss2-scraper rss2-discovery rss2-wiki rss2-topics rss2-related rss2-qdrant-worker; do
|
|
systemctl start "$svc" || warn "No se pudo arrancar $svc"
|
|
done
|
|
|
|
# Workers Python (modelos pesados, arrancan despues)
|
|
for svc in rss2-langdetect rss2-translation-scheduler rss2-translator rss2-embeddings rss2-ner rss2-cluster rss2-categorizer; do
|
|
systemctl start "$svc" || warn "No se pudo arrancar $svc"
|
|
done
|
|
|
|
# =============================================================================
|
|
echo ""
|
|
info "============================================="
|
|
info " RSS2 instalado en $RSS2_HOME"
|
|
info " Acceder en: http://$(hostname -I | awk '{print $1}'):8001"
|
|
info ""
|
|
info " Ver logs: journalctl -u rss2-backend -f"
|
|
info " Ver estado: systemctl status rss2-backend"
|
|
info " Editar env: nano $RSS2_HOME/.env"
|
|
info "============================================="
|