#!/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 "0,/change-me-to-a-strong-password/{s/change-me-to-a-strong-password/${ROOT_PASS}/}" "$SCRIPT_DIR/.env" sed -i "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 WP_PORT=$(find_free_port 8080) # ── Mode info ─────────────────────────────── if [ "$MODE" = "local" ]; then echo -e "${YELLOW}Modo:${NC} local (tu ordenador)" echo -e " WordPress: ${CYAN}http://localhost:${WP_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 "" 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 [ "$WP_PORT" != "8080" ]; then echo -e "${YELLOW}⚠ Puerto 8080 ocupado, usando ${WP_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 (qwen3:4b, ~2.5 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 qwen3:4b # ── Done ──────────────────────────────────── echo "" echo -e "${BOLD}${GREEN}¡Listo! Tu WordPress con IA está corriendo.${NC}" echo "" # ── Auto-config WordPress (plugins IA + conexión a Ollama) ── # El contenedor wordpress:7.1 no trae WP-CLI; usar el contenedor wordpress:cli. echo -e "${YELLOW}Configurando los plugins de IA en WordPress (1-2 min la primera vez)...${NC}" docker pull wordpress:cli >/dev/null 2>&1 # Red real del compose (el nombre depende del directorio, no es fijo): WP_NET=$(docker inspect d0a1-wp --format '{{range $k,$_ := .NetworkSettings.Networks}}{{$k}}{{end}}' 2>/dev/null) if [ -z "$WP_NET" ]; then echo -e "${YELLOW}⚠ No se detecto la red del compose (d0a1-wp no corre). Saltando autoconfig.${NC}" exit 1 fi WP_DB_PASS=$(grep '^MYSQL_PASSWORD=' "$SCRIPT_DIR/.env" | cut -d= -f2) wpcli() { docker run --rm --network "$WP_NET" --volumes-from d0a1-wp \ --env WORDPRESS_DB_HOST=db:3306 \ --env WORDPRESS_DB_NAME=wordpress \ --env WORDPRESS_DB_USER=wordpress \ --env WORDPRESS_DB_PASSWORD="$WP_DB_PASS" \ wordpress:cli "$@" --allow-root } # Esperar a que WP esté instalado (el asistente del navegador es opcional: # si el usuario aun no instalo WP, la autoconfig se salta y se puede repetir # re-ejecutando deploy.sh). WP_READY=0 for i in $(seq 1 15); do if wpcli core is-installed >/dev/null 2>&1; then WP_READY=1 break fi sleep 4 done if [ "$WP_READY" = "1" ]; then wpcli plugin install ai ai-provider-for-ollama --activate >/dev/null 2>&1 \ && wpcli option update ai_provider_for_ollama_settings \ '{"host":"http://ollama:11434"}' --format=json >/dev/null 2>&1 \ && echo -e "${GREEN}✓${NC} Plugins de IA activados y conectados a Ollama (IA local)" \ || echo -e "${YELLOW}⚠ No se pudo auto-configurar. Re-ejecuta ./deploy.sh tras el asistente de WordPress.${NC}" else echo -e "${YELLOW}⚠ WordPress aun no está instalado. Tras el asistente del navegador," echo -e " vuelve a ejecutar ./deploy.sh y los plugins de IA se configuran solos.${NC}" fi echo "" if [ "$MODE" = "local" ]; then echo -e " ${BOLD}WordPress:${NC} ${CYAN}http://localhost:${WP_PORT}${NC}" else echo -e " ${BOLD}WordPress:${NC} ${CYAN}http://${IP}:${WP_PORT}${NC}" fi echo "" echo -e " ${BOLD}IA integrada en el editor:${NC} títulos sugeridos, extractos, alt text" echo -e " y moderación de comentarios con tu modelo local (qwen3:4b)." echo -e " Configuración en ${BOLD}Ajustes → Connectors${NC} dentro de WordPress." echo "" echo -e " ${BOLD}Parar:${NC} ./deploy.sh stop" echo -e " ${BOLD}¿Quieres más?${NC} ${CYAN}https://d0a1.es/packs/${NC}" echo ""