#!/bin/bash # ────────────────────────────────────────────── # d0a1 pack — Open WebUI # Chat de IA privado. Sin cuenta, sin API key. # ────────────────────────────────────────────── # Local: ./deploy.sh local → http://localhost:3000 # VPS: ./deploy.sh vps → http://TU_IP:3000 # Stop: ./deploy.sh stop # ────────────────────────────────────────────── set -e GREEN='\033[0;32m' CYAN='\033[0;36m' YELLOW='\033[0;33m' RED='\033[0;31m' BOLD='\033[1m' NC='\033[0m' MODE="${1:-local}" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" echo "" echo -e "${BOLD}${CYAN}╔══════════════════════════════════════════╗${NC}" echo -e "${BOLD}${CYAN}║ d0a1 pack — Open WebUI ║${NC}" echo -e "${BOLD}${CYAN}║ Chat de IA privado. Sin cuenta, sin API key. ║${NC}" echo -e "${BOLD}${CYAN}╚══════════════════════════════════════════╝${NC}" echo "" # ── Stop mode ─────────────────────────────── if [ "$MODE" = "stop" ]; then echo -e "${YELLOW}Parando...${NC}" docker compose -f "$COMPOSE_FILE" down echo -e "${GREEN}✓ Parado.${NC}" exit 0 fi # ── Check Docker ──────────────────────────── if ! command -v docker &>/dev/null; then echo -e "${RED}✗ Docker no está instalado.${NC}" echo "" echo "Instálalo: curl -fsSL https://get.docker.com | sh" exit 1 fi if ! docker compose version &>/dev/null; then echo -e "${RED}✗ Docker Compose v2 no disponible.${NC}" exit 1 fi echo -e "${GREEN}✓${NC} Docker: $(docker compose version --short 2>/dev/null || echo 'OK')" # ── Check RAM ─────────────────────────────── TOTAL_RAM_KB=$(grep MemTotal /proc/meminfo 2>/dev/null | awk '{print $2}' || echo "0") TOTAL_RAM_GB=$((TOTAL_RAM_KB / 1024 / 1024)) if [ "$TOTAL_RAM_GB" -lt 3 ]; then echo -e "${RED}✗ Se necesitan 4 GB de RAM mínimo (detectado: ${TOTAL_RAM_GB} GB).${NC}" exit 1 fi echo -e "${GREEN}✓${NC} RAM: ${TOTAL_RAM_GB} GB" # ── Auto-detect ports ─────────────────────── find_free_port() { local port=$1 local max_port=$((port + 20)) while [ "$port" -le "$max_port" ]; do if ! ss -tlnp 2>/dev/null | grep -q ":${port} " && ! netstat -tlnp 2>/dev/null | grep -q ":${port} "; then echo "$port" return 0 fi port=$((port + 1)) done echo "$1" return 1 } export OLLAMA_PORT=$(find_free_port 11434) export WEBUI_PORT=$(find_free_port 3000) # ── Mode info ─────────────────────────────── if [ "$MODE" = "local" ]; then echo -e "${YELLOW}Modo:${NC} local (tu ordenador)" echo -e " URL: ${CYAN}http://localhost:${WEBUI_PORT}${NC}" elif [ "$MODE" = "vps" ]; then echo -e "${YELLOW}Modo:${NC} VPS (accesible desde fuera)" echo -e " URL: ${CYAN}http://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'TU_IP'):${WEBUI_PORT}${NC}" echo "" echo -e " ${BOLD}¿No tienes VPS?${NC} Consigue uno con descuento:" echo -e " ${CYAN}https://d0a1.es/go/vultr/${NC} — Vultr" echo -e " ${CYAN}https://d0a1.es/go/digitalocean/${NC} — DigitalOcean (\$200 credit)" else echo -e "${RED}Modo desconocido: $MODE${NC}" echo "Usa: ./deploy.sh local | vps | stop" exit 1 fi if [ "$OLLAMA_PORT" != "11434" ]; then echo -e "${YELLOW}⚠ Puerto 11434 ocupado, usando ${OLLAMA_PORT}${NC}" fi if [ "$WEBUI_PORT" != "3000" ]; then echo -e "${YELLOW}⚠ Puerto 3000 ocupado, usando ${WEBUI_PORT}${NC}" fi echo "" # ── Deploy ────────────────────────────────── echo -e "${YELLOW}Descargando contenedores (2-3 min la primera vez)...${NC}" docker compose -f "$COMPOSE_FILE" up -d # ── Pull model ─────────────────────────────── echo -e "${YELLOW}Descargando modelo de IA (llama3.2:3b, ~2 GB)...${NC}" MAX_WAIT=60 WAITED=0 until docker exec d0a1-ollama ollama ps &>/dev/null; do sleep 2 WAITED=$((WAITED + 2)) if [ "$WAITED" -ge "$MAX_WAIT" ]; then echo -e "${RED}✗ Ollama no arrancó. Revisa: docker logs d0a1-ollama${NC}" exit 1 fi done docker exec d0a1-ollama ollama pull llama3.2:3b # ── Done ──────────────────────────────────── echo "" echo -e "${BOLD}${GREEN}¡Listo! Tu IA está corriendo.${NC}" echo "" if [ "$MODE" = "local" ]; then echo -e " ${BOLD}Abre:${NC} ${CYAN}http://localhost:${WEBUI_PORT}${NC}" else echo -e " ${BOLD}Abre:${NC} ${CYAN}http://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'TU_IP'):${WEBUI_PORT}${NC}" fi echo "" echo -e " ${BOLD}Modelos alternativos:${NC}" echo " docker exec d0a1-ollama ollama pull qwen3:4b # Mejor en español + razonamiento (4 GB RAM)" echo " docker exec d0a1-ollama ollama pull qwen3:8b # Más calidad (6 GB RAM)" echo "" echo -e " ${BOLD}Parar:${NC} ./deploy.sh stop" echo -e " ${BOLD}¿Quieres más?${NC} ${CYAN}https://d0a1.es/packs/${NC}" echo ""