- Eliminado el servicio openwebui del pack wordpress (no estaba integrado con WP; el chat IA vive ahora dentro del editor de WordPress). - Plugins IA oficiales preinstalados y configurados en el arranque: 'AI' (AI Experiments) + 'AI Provider for Ollama' (connector), host http://ollama:11434 (red interna del compose, sin puerto publicado). - Autoconfig via contenedor oficial wordpress:cli (--volumes-from): espera a core is-installed, instala plugins y setea el option. Si WP aun no esta instalado, aviso y re-ejecucion tras el asistente. - CPU cap dinamico en hermes/openclaw (min 6, nproc) y OLLAMA_CPUS parametrizado en compose (6.0 default) — evita fallo en hosts de 4 cores. - .gitignore raiz (**/.env, *.gguf, override GPU). - GATE A PASS: subagente independiente (5 findings aplicados: EAP 5.1, .gitignore, fallo autoconfig visible, red vacia, indentacion). - E2E verificado en VPS: plugins activos + option host + provider responde /v1/chat/completions del modelo local.
192 lines
8.3 KiB
Bash
Executable File
192 lines
8.3 KiB
Bash
Executable File
#!/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 "" |