#!/usr/bin/env bash # Launch SearXNG (internal) then the Gradio app (public). SearXNG runs in the # background bound to 127.0.0.1:8080; the app talks to it over localhost. # Each process uses its own isolated virtualenv. set -euo pipefail SEARXNG_PY=/opt/searxng-venv/bin/python APP_PY=/opt/appenv/bin/python SEARXNG_HOST="127.0.0.1" SEARXNG_PORT="8080" # Point SearXNG at our settings at runtime only (not during the image build, where # the file doesn't exist yet and would break metadata generation). export SEARXNG_SETTINGS_PATH="${SEARXNG_SETTINGS_PATH:-/etc/searxng/settings.yml}" SETTINGS="$SEARXNG_SETTINGS_PATH" # A settings.yml secret_key must be set. If the shipped one is still the # placeholder, generate one at runtime (settings dir is made writable in the image). if grep -q 'ultrasecretkey_change_me' "$SETTINGS" 2>/dev/null; then KEY="$("$APP_PY" -c 'import secrets; print(secrets.token_hex(32))')" sed -i "s/ultrasecretkey_change_me/${KEY}/" "$SETTINGS" || true fi echo "[start] launching SearXNG on ${SEARXNG_HOST}:${SEARXNG_PORT} ..." "$SEARXNG_PY" -m searx.webapp & SEARXNG_PID=$! # Wait for SearXNG to accept connections before starting the app (max ~40s). for i in $(seq 1 40); do if "$APP_PY" - <<'PY' 2>/dev/null; then import socket, sys s = socket.socket() s.settimeout(1) try: s.connect(("127.0.0.1", 8080)) sys.exit(0) except Exception: sys.exit(1) finally: s.close() PY echo "[start] SearXNG is up." break fi if ! kill -0 "$SEARXNG_PID" 2>/dev/null; then echo "[start] WARNING: SearXNG process exited early; search will be degraded." break fi echo "[start] waiting for SearXNG ($i/40) ..." sleep 1 done echo "[start] launching Gradio app on 0.0.0.0:7860 ..." exec "$APP_PY" /app/app.py