From 00aa4bf6cbf389322c2a2ec05b881fcf5d2bb2a5 Mon Sep 17 00:00:00 2001 From: Sivarius Date: Fri, 7 Aug 2026 08:10:39 +0800 Subject: [PATCH] Initial commit: Hermes Docker Stack (SearXNG :8964 + Camofox :9377) --- .env.example | 4 ++ .gitignore | 22 ++++++++++ README.md | 64 +++++++++++++++++++++++++++++ compose/camofox/docker-compose.yml | 44 ++++++++++++++++++++ compose/searxng/docker-compose.yml | 38 +++++++++++++++++ dev/camofox/docker-compose.yml | 13 ++++++ dev/searxng/docker-compose.yml | 15 +++++++ docker-compose.yml | 15 +++++++ scripts/manage.sh | 47 +++++++++++++++++++++ src/camofox/Dockerfile | 35 ++++++++++++++++ volumes/searxng/config/settings.yml | 48 ++++++++++++++++++++++ 11 files changed, 345 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 README.md create mode 100644 compose/camofox/docker-compose.yml create mode 100644 compose/searxng/docker-compose.yml create mode 100644 dev/camofox/docker-compose.yml create mode 100644 dev/searxng/docker-compose.yml create mode 100644 docker-compose.yml create mode 100644 scripts/manage.sh create mode 100644 src/camofox/Dockerfile create mode 100644 volumes/searxng/config/settings.yml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..97db465 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Hermes Docker Stack — .env template +# Copy to .env and fill in + +SEARXNG_SECRET_KEY=change_me_to_random_hex diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57ff614 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Environment +.env +!.env.example + +# Volume data (persistent container state) +volumes/searxng/data/ +volumes/camofox/browser/ +volumes/shared/ + +# Keep gitkeep files +!volumes/**/.gitkeep + +# Python +__pycache__/ +*.pyc + +# Node +node_modules/ + +# OS +.DS_Store +Thumbs.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..e49149e --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Hermes Docker Stack + +Self-hosted SearXNG (metasearch) + Camofox (browser) for Hermes Agent. + +## Структура + +``` +docker/ +├── compose/ # Production compose-файлы (по одному на сервис) +│ ├── searxng/ # SearXNG — self-hosted metasearch +│ └── camofox/ # Camofox — anti-detection browser (Firefox) +├── dev/ # Dev-версии (другие порты) +│ ├── searxng/ +│ └── camofox/ +├── volumes/ # Persistent volume data +│ ├── searxng/config/ # settings.yml +│ ├── searxng/data/ # Search engine data +│ ├── camofox/browser/ # Firefox profiles +│ └── shared/ # Shared downloads +├── scripts/ # Утилиты +│ └── manage.sh +├── tests/ # Тесты +├── docker-compose.yml # Главный стек (extends compose/*) +├── .env # Секреты (gitignored) +├── .env.example # Шаблон .env +└── .gitignore +``` + +## Порты + +| Сервис | Prod | Dev | +|----------|------|------| +| SearXNG | 8964 | 8965 | +| Camofox | 9377 | 9378 | + +## Использование + +```bash +./scripts/manage.sh start # Запустить стек +./scripts/manage.sh status # Статус +./scripts/manage.sh logs # Логи +./scripts/manage.sh stop # Остановить +./scripts/manage.sh dev # Dev-режим +./scripts/manage.sh dev-stop # Остановить dev +``` + +## Интеграция с Hermes + +В `~/.hermes/.env`: +``` +SEARXNG_URL=http://localhost:8964 +CAMOFOX_URL=http://localhost:9377 +``` + +В `~/.hermes/config.yaml`: +```yaml +web: + search_backend: searxng +browser: + backend: camofox + camofox: + rewrite_loopback_urls: true + loopback_host_alias: host.docker.internal +``` diff --git a/compose/camofox/docker-compose.yml b/compose/camofox/docker-compose.yml new file mode 100644 index 0000000..91d0778 --- /dev/null +++ b/compose/camofox/docker-compose.yml @@ -0,0 +1,44 @@ +services: + camofox: + build: ../../src/camofox + container_name: hermes-camofox + restart: unless-stopped + ports: + - "127.0.0.1:9377:9377" + networks: + - hermes-net + environment: + - CAMOFOX_PORT=9377 + - CAMOFOX_REWRITE_LOOPBACK_URLS=true + - CAMOFOX_LOOPBACK_HOST_ALIAS=host.docker.internal + volumes: + - ../../volumes/camofox/browser:/home/browser/.camoufox:rw + - ../../volumes/shared:/shared:rw + cap_drop: + - ALL + cap_add: + - SYS_ADMIN + - NET_ADMIN + - NET_RAW + - CHOWN + - SETGID + - SETUID + - DAC_OVERRIDE + - FOWNER + shm_size: 2gb + logging: + driver: json-file + options: + max-size: 10m + max-file: 3 + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:9377/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 15s + +networks: + hermes-net: + name: hermes-net + driver: bridge diff --git a/compose/searxng/docker-compose.yml b/compose/searxng/docker-compose.yml new file mode 100644 index 0000000..703cec0 --- /dev/null +++ b/compose/searxng/docker-compose.yml @@ -0,0 +1,38 @@ +services: + searxng: + image: searxng/searxng:latest + container_name: hermes-searxng + restart: unless-stopped + ports: + - "127.0.0.1:8964:8080" + networks: + - hermes-net + volumes: + - ../../volumes/searxng/config:/etc/searxng:rw + - ../../volumes/searxng/data:/etc/searxng/data:rw + environment: + - SEARXNG_BASE_URL=http://localhost:8964/ + - SEARXNG_SECRET_KEY=${SEARXNG_SECRET_KEY:?err} + cap_drop: + - ALL + cap_add: + - CHOWN + - SETGID + - SETUID + - DAC_OVERRIDE + logging: + driver: json-file + options: + max-size: 10m + max-file: 3 + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:8080/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + +networks: + hermes-net: + name: hermes-net + driver: bridge diff --git a/dev/camofox/docker-compose.yml b/dev/camofox/docker-compose.yml new file mode 100644 index 0000000..22d381a --- /dev/null +++ b/dev/camofox/docker-compose.yml @@ -0,0 +1,13 @@ +services: + camofox: + extends: + file: ../../compose/camofox/docker-compose.yml + service: camofox + container_name: hermes-camofox-dev + ports: + - "127.0.0.1:9378:9377" + +networks: + hermes-net: + name: hermes-net + driver: bridge diff --git a/dev/searxng/docker-compose.yml b/dev/searxng/docker-compose.yml new file mode 100644 index 0000000..2df6d37 --- /dev/null +++ b/dev/searxng/docker-compose.yml @@ -0,0 +1,15 @@ +services: + searxng: + extends: + file: ../../compose/searxng/docker-compose.yml + service: searxng + container_name: hermes-searxng-dev + ports: + - "127.0.0.1:8965:8080" + environment: + - SEARXNG_BASE_URL=http://localhost:8965/ + +networks: + hermes-net: + name: hermes-net + driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c4345a9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +services: + searxng: + extends: + file: ./compose/searxng/docker-compose.yml + service: searxng + + camofox: + extends: + file: ./compose/camofox/docker-compose.yml + service: camofox + +networks: + hermes-net: + name: hermes-net + driver: bridge diff --git a/scripts/manage.sh b/scripts/manage.sh new file mode 100644 index 0000000..d8a6976 --- /dev/null +++ b/scripts/manage.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Hermes Docker Stack — manage script +set -euo pipefail +DIR="$(cd "$(dirname "$0")/.." && pwd)" +cd "$DIR" + +case "${1:-status}" in + start) + echo "🚀 Starting Hermes Docker Stack..." + docker compose -f docker-compose.yml up -d + echo "SearXNG: http://localhost:8964" + echo "Camofox: http://localhost:9377" + ;; + stop) + echo "🛑 Stopping..." + docker compose -f docker-compose.yml down + ;; + restart) + docker compose -f docker-compose.yml down + docker compose -f docker-compose.yml up -d + ;; + status) + echo "=== Hermes Docker Stack ===" + docker compose -f docker-compose.yml ps + echo "---" + for url in http://localhost:8964/health http://localhost:9377/health; do + code=$(curl -s -o /dev/null -w '%{http_code}' "$url" 2>/dev/null || echo "down") + echo "$url → $code" + done + ;; + logs) + docker compose -f docker-compose.yml logs --tail=50 -f + ;; + dev) + echo "🧪 Starting DEV stack..." + docker compose -f dev/searxng/docker-compose.yml -f dev/camofox/docker-compose.yml up -d + echo "SearXNG: http://localhost:8965" + echo "Camofox: http://localhost:9378" + ;; + dev-stop) + docker compose -f dev/searxng/docker-compose.yml -f dev/camofox/docker-compose.yml down + ;; + *) + echo "Usage: $0 [start|stop|restart|status|logs|dev|dev-stop]" + exit 1 + ;; +esac diff --git a/src/camofox/Dockerfile b/src/camofox/Dockerfile new file mode 100644 index 0000000..7f67dae --- /dev/null +++ b/src/camofox/Dockerfile @@ -0,0 +1,35 @@ +FROM node:22-alpine + +RUN apk add --no-cache \ + # Playwright deps + nss \ + freetype \ + freetype-dev \ + harfbuzz \ + ca-certificates \ + ttf-freefont \ + # Firefox deps + libstdc++ \ + dbus-glib \ + # Xvfb for headless mode + xvfb \ + xauth \ + # General + wget \ + curl \ + yt-dlp + +# Install Camofox browser globally +RUN npm install -g @askjo/camofox-browser@1.13.1 + +# Install Playwright Firefox +RUN npx playwright install firefox + +EXPOSE 9377 + +ENV CAMOFOX_PORT=9377 +ENV CAMOFOX_REWRITE_LOOPBACK_URLS=true +ENV CAMOFOX_LOOPBACK_HOST_ALIAS=host.docker.internal +ENV DISPLAY=:99 + +CMD Xvfb :99 -screen 0 1920x1080x24 & sleep 0.5 && camofox-browser diff --git a/volumes/searxng/config/settings.yml b/volumes/searxng/config/settings.yml new file mode 100644 index 0000000..b833041 --- /dev/null +++ b/volumes/searxng/config/settings.yml @@ -0,0 +1,48 @@ +# SearXNG settings — Hermes Agent instance +# Port 8964 (internal 8080) +# See: https://docs.searxng.org/admin/settings/settings.yml.html + +use_default_settings: true + +general: + instance_name: "Hermes SearXNG" + debug: false + privacypolicy_url: false + contact_url: false + enable_metrics: false + +search: + safe_search: 0 + autocomplete: "" + default_lang: "" + formats: + - html + - json + +server: + secret_key: "" # will be overridden by SEARXNG_SECRET_KEY env + bind_address: "0.0.0.0" + port: 8080 + base_url: "http://localhost:8964/" + limiter: false + image_proxy: false + method: "GET" + +ui: + static_use_hash: true + default_theme: simple + default_locale: "" + +outgoing: + request_timeout: 10.0 + max_request_timeout: 15.0 + useragent_suffix: "" + verify: true + +enabled_plugins: + - BasicPlugin + - DictPlugin + - HeaderPlugin + - SearchSuggestionsPlugin + - SelfInformationPlugin + - TrackerUrlPlugin