Privacy-respecting metasearch engine that aggregates results from 70+ search engines without tracking. Primary consumer is the haiven-mcp search/web tool used by LLM agents.
https://search.haiven.site — gated by Authentik SSO (no application provider configured yet; returns 404 for unauthenticated external requests)http://searxng:8080 — direct, bypasses Traefik and Authentikhttp://searxng:8080/healthz (internal) — returns OKhttp://searxng:8080/stats/errors — JSON, from inside the container or backend-networked callers| Container | Role | Networks | Port |
|---|---|---|---|
searxng |
Main metasearch engine | web, backend |
8080 (internal) |
searxng-redis |
Session/cache store (Redis 7-alpine) | backend |
6379 (internal) |
searxng-tor |
Tor SOCKS5 proxy for arxiv engine | backend |
9050 (internal) |
searxng-metrics |
Prometheus exporter (polls /stats/errors every 30s) |
backend, monitoring |
9109 |
# Start all containers
docker compose -f /mnt/apps/docker/searxng/docker-compose.yml up -d
# Check status
docker compose -f /mnt/apps/docker/searxng/docker-compose.yml ps
# View logs
docker logs --tail 100 searxng
| File | Purpose |
|---|---|
docker-compose.yml |
Service definitions for all 4 containers |
.env |
SEARXNG_SECRET, SEARXNG_VALKEY_URL |
config/settings.yml |
SearxNG engine config, timeouts, Tor network routing |
config/limiter.toml |
Rate limiter — 10.10.1.0/24 in pass_ip for internal callers |
tor/Dockerfile |
Alpine 3.20 + tor, runs as tor user |
tor/torrc |
Tor configuration (SocksPort 9050, ExitRelay 0) |
exporter/Dockerfile |
Python 3.11-slim + prometheus-client + httpx |
exporter/exporter.py |
Metrics exporter source (120 lines) |
searxng-tor is an Alpine-based Tor container providing a SOCKS5 proxy at tor:9050. Only the arxiv engine routes through it (selective routing via outgoing.networks.tor_network in settings.yml). This recovered arxiv from 100% TooManyRequests errors to 0%. Other engines (brave, duckduckgo) are not routed via Tor because Cloudflare blocks Tor exits — routing them through Tor made their error rates worse.
Traefik label authentik-secure-chain@file,searxng-headers gates the public domain. Internal MCP callers use http://searxng:8080 directly on the backend network and are unaffected. As of 2026-05-02, no Authentik application provider is configured for this service — a follow-up task.
server.limiter: true is enabled. The backend subnet 10.10.1.0/24 is in config/limiter.toml pass_ip so internal callers bypass rate limiting. Without this entry, all internal tool calls return 429.
SearxNG's redis: config block is named valkey: and the env var is SEARXNG_VALKEY_URL (renamed from SEARXNG_REDIS_URL). The underlying container still runs redis:7-alpine.
The searxng-metrics sidecar exposes metrics at port 9109, auto-discovered by Prometheus via Docker labels. Grafana dashboard UID: searxng-engine-health (auto-provisioned from docker/infrastructure/grafana/dashboards/09-ai/).
Alert rule SearxNGEnginesDegraded fires when searxng_engines_with_errors_count >= 4 for 10m.
searxng/
├── docker-compose.yml # All 4 containers
├── .env # Secrets (gitignored)
├── config/
│ ├── settings.yml # SearxNG engine and network config
│ └── limiter.toml # Rate limiter pass_ip list
├── tor/
│ ├── Dockerfile # Alpine 3.20 + tor
│ └── torrc # Tor configuration
├── exporter/
│ ├── Dockerfile # Python 3.11-slim
│ └── exporter.py # Prometheus metrics exporter
├── data/ # SearxNG runtime cache (bind-mounted)
├── CLAUDE.md # Agent context and operations
├── USER_GUIDE.md # Operator guide
├── MEMORY.md # Operational history
└── README.md # This file