#!/usr/bin/env bash set -e REPO_URL="https://github.com/TySP-Dev/ollama-ai-answers-searxng" REPO_DIR="/tmp/ollama-ai-answers-searxng" # ============================================================ echo "=== Step 1: Clone or update repo ===" # ============================================================ if [ -d "$REPO_DIR/.git" ]; then echo "Repository already exists — pulling latest changes..." git -C "$REPO_DIR" pull else git clone "$REPO_URL" "$REPO_DIR" fi cd "$REPO_DIR" # ============================================================ echo "=== Step 2: Build dist file ===" # ============================================================ if ! python3 build.py; then echo "ERROR: build.py failed" exit 1 fi # ============================================================ echo "=== Step 3: Detect SearXNG Docker Compose installation ===" # ============================================================ CANDIDATES=( "$HOME/searxng/docker-compose.yml" "$HOME/docker/searxng/docker-compose.yml" "/opt/searxng/docker-compose.yml" "/etc/searxng/docker-compose.yml" ) FOUND=() for f in "${CANDIDATES[@]}"; do if [ -f "$f" ] && grep -q "searxng" "$f" 2>/dev/null; then FOUND+=("$f") fi done # Also do a broader search while IFS= read -r f; do # Avoid duplicates already=false for existing in "${FOUND[@]}"; do [ "$f" = "$existing" ] && already=true && break done $already || FOUND+=("$f") done < <(find "$HOME" -maxdepth 6 -name "docker-compose.yml" -exec grep -l "searxng" {} \; 2>/dev/null) if [ ${#FOUND[@]} -eq 0 ]; then echo "ERROR: No docker-compose.yml containing 'searxng' was found." echo "Please set COMPOSE_FILE manually and re-run." exit 1 elif [ ${#FOUND[@]} -eq 1 ]; then COMPOSE_FILE="${FOUND[0]}" echo "Found: $COMPOSE_FILE" else echo "Multiple docker-compose.yml files found:" for i in "${!FOUND[@]}"; do echo " [$((i+1))] ${FOUND[$i]}" done read -rp "Select a file [1-${#FOUND[@]}]: " choice idx=$((choice - 1)) if [ "$idx" -lt 0 ] || [ "$idx" -ge "${#FOUND[@]}" ]; then echo "ERROR: Invalid selection" exit 1 fi COMPOSE_FILE="${FOUND[$idx]}" fi COMPOSE_DIR="$(dirname "$COMPOSE_FILE")" echo "Using: $COMPOSE_FILE" # ============================================================ echo "=== Step 4: Create plugins directory ===" # ============================================================ PLUGINS_DIR="$COMPOSE_DIR/plugins" mkdir -p "$PLUGINS_DIR" echo "Plugins directory: $PLUGINS_DIR" # ============================================================ echo "=== Step 5: Copy built plugin ===" # ============================================================ cp dist/ollama_answers.py "$PLUGINS_DIR/ollama_answers.py" echo "Plugin installed to $PLUGINS_DIR/ollama_answers.py" # ============================================================ echo "=== Step 6: Update docker-compose.yml volume mount ===" # ============================================================ python3 - "$COMPOSE_FILE" <<'PYEOF' import re, sys compose_file = sys.argv[1] content = open(compose_file).read() mount = ' - ./plugins/ollama_answers.py:/usr/local/searxng/searx/plugins/ollama_answers.py:Z' if 'ollama_answers.py' not in content: content = re.sub( r'(volumes:(?:\n\s+- [^\n]+)*)', lambda m: m.group(0) + '\n' + mount, content, count=1 ) open(compose_file, 'w').write(content) print('Added volume mount to docker-compose.yml') else: print('Volume mount already present') PYEOF # ============================================================ echo "=== Step 7: Find and update settings.yml ===" # ============================================================ SETTINGS_CANDIDATES=( "$COMPOSE_DIR/core-config/settings.yml" "$COMPOSE_DIR/config/settings.yml" "$COMPOSE_DIR/searxng/settings.yml" ) SETTINGS_FOUND=() for f in "${SETTINGS_CANDIDATES[@]}"; do [ -f "$f" ] && SETTINGS_FOUND+=("$f") done # Broader search within COMPOSE_DIR while IFS= read -r f; do already=false for existing in "${SETTINGS_FOUND[@]}"; do [ "$f" = "$existing" ] && already=true && break done $already || SETTINGS_FOUND+=("$f") done < <(find "$COMPOSE_DIR" -name "settings.yml" 2>/dev/null | head -5) if [ ${#SETTINGS_FOUND[@]} -eq 0 ]; then echo "WARNING: settings.yml not found. Add this manually:" echo "" echo " plugins:" echo " searx.plugins.ollama_answers.SXNGPlugin:" echo " active: true" echo "" SETTINGS_FILE="" elif [ ${#SETTINGS_FOUND[@]} -eq 1 ]; then SETTINGS_FILE="${SETTINGS_FOUND[0]}" echo "Found: $SETTINGS_FILE" else echo "Multiple settings.yml files found:" for i in "${!SETTINGS_FOUND[@]}"; do echo " [$((i+1))] ${SETTINGS_FOUND[$i]}" done read -rp "Select a file [1-${#SETTINGS_FOUND[@]}]: " schoice sidx=$((schoice - 1)) if [ "$sidx" -lt 0 ] || [ "$sidx" -ge "${#SETTINGS_FOUND[@]}" ]; then echo "ERROR: Invalid selection" exit 1 fi SETTINGS_FILE="${SETTINGS_FOUND[$sidx]}" fi if [ -n "$SETTINGS_FILE" ]; then python3 - "$SETTINGS_FILE" <<'PYEOF' import sys settings_file = sys.argv[1] content = open(settings_file).read() entry = 'searx.plugins.ollama_answers.SXNGPlugin:\n active: true' if 'ollama_answers' not in content: if 'plugins:' in content: content = content.replace('plugins:', 'plugins:\n\n ' + entry, 1) else: content += '\nplugins:\n\n ' + entry + '\n' open(settings_file, 'w').write(content) print('Added plugin entry to settings.yml') else: print('Plugin entry already present') PYEOF fi # ============================================================ echo "=== Step 8: Configure environment variables ===" # ============================================================ python3 - "$COMPOSE_FILE" <<'PYEOF' import sys compose_file = sys.argv[1] content = open(compose_file).read() has_llm_url = 'LLM_URL' in content has_llm_model = 'LLM_MODEL' in content sys.exit(0 if (has_llm_url and has_llm_model) else 1) PYEOF ENV_ALREADY=$? if [ $ENV_ALREADY -eq 0 ]; then echo "LLM_URL and LLM_MODEL already present in docker-compose.yml" else read -rp "Enter Ollama URL (default: http://ollama:11434/v1/chat/completions): " llm_url llm_url="${llm_url:-http://ollama:11434/v1/chat/completions}" read -rp "Enter model name (default: qwen3.5:9b): " llm_model llm_model="${llm_model:-qwen3.5:9b}" python3 - "$COMPOSE_FILE" "$llm_url" "$llm_model" <<'PYEOF' import re, sys compose_file, llm_url, llm_model = sys.argv[1], sys.argv[2], sys.argv[3] content = open(compose_file).read() env_lines = f' - LLM_URL={llm_url}\n - LLM_MODEL={llm_model}' if 'LLM_URL' not in content: content = re.sub( r'(environment:(?:\n\s+- [^\n]+)*)', lambda m: m.group(0) + '\n' + env_lines, content, count=1 ) open(compose_file, 'w').write(content) print(f'Added LLM_URL={llm_url} and LLM_MODEL={llm_model} to docker-compose.yml') else: print('LLM_URL already present, skipping') PYEOF fi # ============================================================ echo "=== Step 9: Restart SearXNG ===" # ============================================================ read -rp "Restart SearXNG now? (y/n): " restart_choice if [[ "$restart_choice" =~ ^[Yy]$ ]]; then echo "Restarting SearXNG..." cd "$COMPOSE_DIR" docker compose up -d --force-recreate core echo "SearXNG restarted." else echo "Skipping restart. Run manually:" echo " cd \"$COMPOSE_DIR\" && docker compose up -d --force-recreate core" fi # ============================================================ echo "" echo "=== Installation complete ===" echo "" echo "Summary:" echo " Plugin: $PLUGINS_DIR/ollama_answers.py" echo " Compose: $COMPOSE_FILE" [ -n "$SETTINGS_FILE" ] && echo " Settings: $SETTINGS_FILE" echo "" echo "Environment variables to verify in docker-compose.yml:" echo " LLM_URL — Ollama endpoint" echo " LLM_MODEL — Model name (e.g. qwen3.5:9b)" echo ""