#!/usr/bin/env bash # ============================================================================= # COCONEWS - Instalacion de prerequisites en Debian 12 / Ubuntu 22.04+ # Ejecutar ANTES de install.sh # Uso: sudo bash prerequisites.sh # ============================================================================= set -euo pipefail RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m' info() { echo -e "${GREEN}[OK]${NC} $*"; } step() { echo -e "${BLUE}[-->]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } [[ "$EUID" -ne 0 ]] && error "Ejecutar como root: sudo bash prerequisites.sh" # Detectar OS if [[ -f /etc/os-release ]]; then . /etc/os-release OS_ID="$ID" OS_VER="$VERSION_ID" else error "No se puede detectar el sistema operativo" fi [[ "$OS_ID" == "debian" || "$OS_ID" == "ubuntu" ]] || \ error "Solo soportado en Debian/Ubuntu. Detectado: $OS_ID" echo "" echo "=================================================" echo " COCONEWS - Instalador de Prerequisites" echo " OS: $PRETTY_NAME" echo "=================================================" echo "" # ============================================================================= # 1. PAQUETES APT BASE # ============================================================================= step "Actualizando repositorios apt..." apt-get update -qq step "Instalando paquetes del sistema..." apt-get install -y --no-install-recommends \ curl wget git build-essential \ ca-certificates gnupg lsb-release \ software-properties-common apt-transport-https \ tzdata locales \ rsync \ openssl \ libpq-dev \ libssl-dev \ libffi-dev \ libbz2-dev \ libreadline-dev \ libsqlite3-dev \ zlib1g-dev info "Paquetes base instalados" # ============================================================================= # 2. POSTGRESQL 16 # ============================================================================= step "Instalando PostgreSQL 16..." if ! command -v psql &>/dev/null; then # Repositorio oficial de PostgreSQL install -d /usr/share/postgresql-common/pgdg curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \ | gpg --dearmor -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.gpg echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.gpg] \ https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \ > /etc/apt/sources.list.d/pgdg.list apt-get update -qq apt-get install -y postgresql-16 postgresql-client-16 fi info "PostgreSQL: $(psql --version)" # ============================================================================= # 3. REDIS # ============================================================================= step "Instalando Redis..." if ! command -v redis-server &>/dev/null; then apt-get install -y redis-server fi info "Redis: $(redis-server --version | cut -d' ' -f3)" # ============================================================================= # 4. NGINX # ============================================================================= step "Instalando Nginx..." if ! command -v nginx &>/dev/null; then apt-get install -y nginx fi info "Nginx: $(nginx -v 2>&1 | cut -d'/' -f2)" # ============================================================================= # 5. PYTHON 3 + pip + venv # ============================================================================= step "Instalando Python 3..." apt-get install -y python3 python3-pip python3-venv python3-dev info "Python: $(python3 --version)" # ============================================================================= # 6. NODE.JS 20 LTS # ============================================================================= step "Instalando Node.js 20 LTS..." if ! command -v node &>/dev/null || [[ "$(node -v | tr -d 'v' | cut -d. -f1)" -lt 18 ]]; then curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y nodejs fi info "Node.js: $(node --version) | npm: $(npm --version)" # ============================================================================= # 7. GO 1.25 # ============================================================================= step "Instalando Go 1.25..." GO_VERSION="1.25.0" INSTALLED_GO=$(go version 2>/dev/null | awk '{print $3}' | tr -d 'go' || echo "0") # Comparar version instalada needs_go=false if ! command -v go &>/dev/null; then needs_go=true else IFS='.' read -ra INS <<< "$INSTALLED_GO" IFS='.' read -ra REQ <<< "$GO_VERSION" if [[ "${INS[0]}" -lt "${REQ[0]}" ]] || \ ([[ "${INS[0]}" == "${REQ[0]}" ]] && [[ "${INS[1]:-0}" -lt "${REQ[1]:-0}" ]]); then needs_go=true fi fi if [[ "$needs_go" == "true" ]]; then ARCH=$(dpkg --print-architecture) case "$ARCH" in amd64) GO_ARCH="amd64" ;; arm64) GO_ARCH="arm64" ;; *) error "Arquitectura no soportada para Go: $ARCH" ;; esac step " Descargando Go ${GO_VERSION} (${GO_ARCH})..." 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 rm /tmp/go.tar.gz # Perfil global cat > /etc/profile.d/golang.sh << 'GOEOF' export PATH=$PATH:/usr/local/go/bin export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin GOEOF chmod +x /etc/profile.d/golang.sh export PATH=$PATH:/usr/local/go/bin info "Go instalado: $(go version)" else export PATH=$PATH:/usr/local/go/bin info "Go ya instalado: $(go version)" fi # ============================================================================= # 8. QDRANT (binario oficial) # ============================================================================= step "Instalando Qdrant..." QDRANT_VERSION="v1.12.1" QDRANT_INSTALL_DIR="/opt/rss2/qdrant" mkdir -p "$QDRANT_INSTALL_DIR" if [[ ! -f "$QDRANT_INSTALL_DIR/qdrant" ]]; then 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 step " Descargando Qdrant ${QDRANT_VERSION}..." curl -fsSL \ "https://github.com/qdrant/qdrant/releases/download/${QDRANT_VERSION}/qdrant-${QDRANT_ARCH}.tar.gz" \ -o /tmp/qdrant.tar.gz tar -C "$QDRANT_INSTALL_DIR" -xzf /tmp/qdrant.tar.gz chmod +x "$QDRANT_INSTALL_DIR/qdrant" rm /tmp/qdrant.tar.gz info "Qdrant ${QDRANT_VERSION} instalado en ${QDRANT_INSTALL_DIR}" else info "Qdrant ya instalado en ${QDRANT_INSTALL_DIR}" fi # ============================================================================= # 9. USUARIO DEL SISTEMA rss2 # ============================================================================= step "Creando usuario del sistema 'rss2'..." if ! id rss2 &>/dev/null; then useradd -r -m -d /opt/rss2 -s /bin/bash rss2 info "Usuario 'rss2' creado" else info "Usuario 'rss2' ya existe" fi # Crear estructura de directorios mkdir -p \ /opt/rss2/bin \ /opt/rss2/src \ /opt/rss2/data/wiki_images \ /opt/rss2/data/qdrant_storage \ /opt/rss2/hf_cache \ /opt/rss2/models \ /opt/rss2/frontend/dist \ /opt/rss2/logs \ /opt/rss2/backups chown -R rss2:rss2 /opt/rss2 info "Directorios /opt/rss2 creados" # ============================================================================= # 10. PYTHON VIRTUALENV + DEPENDENCIAS BASE # ============================================================================= step "Creando virtualenv Python en /opt/rss2/venv..." if [[ ! -d /opt/rss2/venv ]]; then python3 -m venv /opt/rss2/venv fi /opt/rss2/venv/bin/pip install --upgrade pip setuptools wheel -q info "Virtualenv listo" # Dependencias base (sin los modelos pesados de ML) step "Instalando dependencias Python base..." /opt/rss2/venv/bin/pip install -q \ psycopg2-binary \ langdetect \ python-dotenv \ requests \ beautifulsoup4 \ lxml \ redis \ qdrant-client \ numpy \ scikit-learn \ tqdm info "Dependencias Python base instaladas" # ============================================================================= # 11. DEPENDENCIAS ML (pesadas - opcional en este paso) # ============================================================================= echo "" echo -e "${YELLOW}[?]${NC} Instalar dependencias ML pesadas ahora?" echo " (ctranslate2, transformers, sentence-transformers, spaCy)" echo " Puede tardar 20-40 minutos y usar ~5 GB de disco." echo -n " [s/N]: " read -r install_ml if [[ "${install_ml,,}" == "s" || "${install_ml,,}" == "si" || "${install_ml,,}" == "y" ]]; then step "Instalando dependencias ML (esto tarda)..." /opt/rss2/venv/bin/pip install -q \ ctranslate2>=4.0.0 \ transformers==4.43.3 \ sentencepiece \ sacremoses \ accelerate \ sentence-transformers==3.0.1 \ "spacy>=3.7,<4.0" \ torch --index-url https://download.pytorch.org/whl/cpu info "Dependencias ML instaladas" step "Descargando modelo spaCy en espaƱol..." /opt/rss2/venv/bin/python -m spacy download es_core_news_lg info "Modelo spaCy es_core_news_lg listo" step "Convirtiendo modelo NLLB-200 a CTranslate2..." warn "Esto puede tardar 10-30 minutos y requiere ~2 GB de RAM" mkdir -p /opt/rss2/models /opt/rss2/venv/bin/python - <<'EOF' import os, sys os.makedirs("/opt/rss2/models/nllb-ct2", exist_ok=True) os.environ["HF_HOME"] = "/opt/rss2/hf_cache" try: from ctranslate2.converters import OpusMTConverter converter = OpusMTConverter("facebook/nllb-200-distilled-600M") converter.convert("/opt/rss2/models/nllb-ct2", quantization="int8", force=True) print("[OK] Modelo NLLB-200 convertido en /opt/rss2/models/nllb-ct2") except Exception as e: print(f"[ERROR] {e}") print("Convierte manualmente despues con: deploy/debian/convert_model.sh") sys.exit(0) EOF chown -R rss2:rss2 /opt/rss2/models /opt/rss2/hf_cache else warn "ML omitido. Ejecuta 'deploy/debian/install.sh' para instalarlas junto con el resto." warn "Sin ML: la traduccion y los embeddings no funcionaran." fi chown -R rss2:rss2 /opt/rss2 # ============================================================================= # RESUMEN # ============================================================================= echo "" echo "=================================================" echo -e " ${GREEN}Prerequisites instalados correctamente${NC}" echo "=================================================" echo "" echo " Sistema: $PRETTY_NAME" echo " Go: $(go version 2>/dev/null | awk '{print $3}')" echo " Python: $(python3 --version)" echo " Node.js: $(node --version)" echo " PostgreSQL: $(psql --version | awk '{print $3}')" echo " Redis: $(redis-server --version | awk '{print $3}' | tr -d ',')" echo " Nginx: $(nginx -v 2>&1 | cut -d'/' -f2)" echo "" echo " Siguiente paso:" echo " sudo bash deploy/debian/install.sh" echo ""