#!/bin/bash # ────────────────────────────────────────────── # d0a1 pack — WordPress + IA # Tu WordPress con IA local. Genera borradores, modera comentarios. # ────────────────────────────────────────────── # Local: ./deploy.sh local → http://localhost:8080 # VPS: ./deploy.sh vps → http://TU_IP:8080 # 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 — WordPress + IA ║${NC}" echo -e "${BOLD}${CYAN}║ WP + IA local. Sin cuotas. ║${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 5 ]; then echo -e "${RED}✗ Se necesitan 6 GB de RAM mínimo (detectado: ${TOTAL_RAM_GB} GB).${NC}" exit 1 fi echo -e "${GREEN}✓${NC} RAM: ${TOTAL_RAM_GB} GB" # ── Setup .env ────────────────────────────── if [ ! -f "$SCRIPT_DIR/.env" ]; then echo -e "${YELLOW}⚠ No se encontró .env. Creando desde .env.example...${NC}" cp "$SCRIPT_DIR/.env.example" "$SCRIPT_DIR/.env" # Generate random passwords for local dev ROOT_PASS=$(openssl rand -hex 16 2>/dev/null || cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n1) WP_PASS=$(openssl rand -hex 16 2>/dev/null || cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n1) sed -i "s/change-me-to-a-strong-password/${ROOT_PASS}/g" "$SCRIPT_DIR/.env" # Second occurrence is MYSQL_PASSWORD sed -i "0,/change-me-to-a-strong-password/{s/change-me-to-a-strong-password/${WP_PASS}/}" "$SCRIPT_DIR/.env" echo -e "${GREEN}✓${NC} Contraseñas generadas en ${SCRIPT_DIR}/.env" fi # ── 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 WP_PORT=$(find_free_port 8080) export WEBUI_PORT=$(find_free_port 3000) # ── Mode info ─────────────────────────────── if [ "$MODE" = "local" ]; then echo -e "${YELLOW}Modo:${NC} local (tu ordenador)" echo -e " WordPress: ${CYAN}http://localhost:${WP_PORT}${NC}" echo -e " IA (chat): ${CYAN}http://localhost:${WEBUI_PORT}${NC}" elif [ "$MODE" = "vps" ]; then IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'TU_IP') echo -e "${YELLOW}Modo:${NC} VPS (accesible desde fuera)" echo -e " WordPress: ${CYAN}http://${IP}:${WP_PORT}${NC}" echo -e " IA (chat): ${CYAN}http://${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 [ "$WP_PORT" != "8080" ]; then echo -e "${YELLOW}⚠ Puerto 8080 ocupado, usando ${WP_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 (3-5 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-wp-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-wp-ollama${NC}" exit 1 fi done docker exec d0a1-wp-ollama ollama pull llama3.2:3b # ── Done ──────────────────────────────────── echo "" echo -e "${BOLD}${GREEN}¡Listo! Tu WordPress con IA está corriendo.${NC}" echo "" if [ "$MODE" = "local" ]; then echo -e " ${BOLD}WordPress:${NC} ${CYAN}http://localhost:${WP_PORT}${NC}" echo -e " ${BOLD}IA (chat):${NC} ${CYAN}http://localhost:${WEBUI_PORT}${NC}" else echo -e " ${BOLD}WordPress:${NC} ${CYAN}http://${IP}:${WP_PORT}${NC}" echo -e " ${BOLD}IA (chat):${NC} ${CYAN}http://${IP}:${WEBUI_PORT}${NC}" fi echo "" echo -e " ${BOLD}Configurar WordPress:${NC}" echo " 1. Abre la URL de WordPress en tu navegador" echo " 2. Sigue el asistente de instalación (2 minutos)" echo " 3. Instala el plugin 'AI Agent Bridge' desde el panel" echo "" echo -e " ${BOLD}Parar:${NC} ./deploy.sh stop" echo -e " ${BOLD}¿Quieres más?${NC} ${CYAN}https://d0a1.es/packs/${NC}" echo ""