SearXNG Docker Stack
Self-hosted SearXNG metasearch with Redis caching, a Python query CLI, an MCP server for AI tools, and optional LLM-backed structured extraction. Clone, configure .env, run docker compose up -d, then search in the browser, from scripts, or through Cursor/Claude.
Stack
Quick start
Prerequisites
- Docker and Docker Compose
- For extract: an OpenRouter API key in
.env
Configure and run
cp env.example .env
# Edit .env: set SEARXNG_SECRET_KEY (see below) and OPENROUTER_API_KEY if using extract
openssl rand -hex 32 # paste into SEARXNG_SECRET_KEY
docker compose up -d
Minimum .env values:
SEARXNG_PROTOCOL=http
SEARXNG_HOST=localhost
SEARXNG_PORT=7777
SEARXNG_BASE_URL=${SEARXNG_PROTOCOL}://${SEARXNG_HOST}:${SEARXNG_PORT}/
SEARXNG_SECRET_KEY=<from openssl rand -hex 32>
SEARXNG_MCP_PORT=7778
For structured extraction, keep EXTRACT_ENABLED=true (default in env.example) and set:
OPENROUTER_API_KEY=sk-or-...
To disable the extract tool (search/fetch/crawl only), set EXTRACT_ENABLED=false in .env.
Verify
docker compose ps
curl -sf "http://localhost:7777/search?q=test&format=json" | head -c 200
curl -sf http://localhost:7778/health
- Search UI: http://localhost:7777 (or your
SEARXNG_PORT) - MCP (streamable HTTP): http://localhost:7778/mcp
- REST mirror: http://localhost:7778
Usage
Pick the interface that fits your workflow. All paths use the same private SearXNG instance.
Web UI
Open the search URL in a browser. No extra setup beyond Quick start.
SearXNG search API
Direct JSON search against SearXNG (no MCP):
curl "http://localhost:7777/search?q=python+docker&format=json"
curl "http://localhost:7777/search?q=docker&categories=general,it&format=json"
Response fields, engines, and error handling: API_DOCUMENTATION.md.
Python: searxng_search.py
Command-line wrapper around the SearXNG API (stdlib only):
python searxng_search.py "your search term"
python searxng_search.py "docker" --categories general,it
python searxng_search.py "python" --output json
More flags and examples: QUERY_SCRIPT_README.md.
MCP server: tools and when to use them
The MCP server (searxng-mcp) exposes four capabilities. In agents, fetch returns full page text; extract fetches then returns JSON shaped by your schema and prompt—prefer extract on noisy pages when you want fields, not raw HTML.
REST examples (same host/port as health check):
# Search
curl -sS -X POST http://localhost:7778/search \
-H "Content-Type: application/json" \
-d '{"query": "python programming", "categories": "general,it"}'
# Fetch page text
curl -sS -X POST http://localhost:7778/fetch \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
# Crawl related pages
curl -sS -X POST http://localhost:7778/crawl \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "filters": ["documentation"], "subpage_limit": 5}'
# Extract structured JSON (EXTRACT_ENABLED=true, OPENROUTER_API_KEY set)
curl -sS -X POST http://localhost:7778/extract \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","json_schema":{"type":"object","properties":{"title":{"type":"string"}},"required":["title"]}}'
Python: extract_url.py
CLI for /extract without hand-writing JSON Schema:
python extract_url.py "https://example.com/article" --keys title,author,summary
python extract_url.py "https://example.com/article" \
--keys title,summary \
--prompt "Main article only; ignore navigation and related links"
python extract_url.py "https://example.com/article" \
--json '{"title":"Page title","summary":"Two-sentence summary"}'
Stdout is the extracted data object (indented JSON). Optional env: SEARXNG_MCP_HOST, SEARXNG_MCP_PORT (default localhost:7778), EXTRACT_TIMEOUT (default 120).
Cursor and Claude
1. Point the client at the MCP server (~/.cursor/mcp.json or Claude Desktop config).
Streamable HTTP (recommended when the container port is reachable):
{
"mcpServers": {
"searxng": {
"url": "http://localhost:7778/mcp",
"description": "Private SearXNG: search, fetch, crawl, extract"
}
}
}
stdio via Docker exec (no published port required):
{
"mcpServers": {
"searxng": {
"command": "docker",
"args": ["exec", "-i", "searxng-mcp", "python", "server.py"],
"description": "Private SearXNG: search, fetch, crawl, extract"
}
}
}
Claude Desktop paths: macOS ~/Library/Application Support/Claude/claude_desktop_config.json, Windows %APPDATA%\Claude\claude_desktop_config.json. Restart the app after editing.
2. Install the agent skill (Cursor, recommended) so the model knows when to use extract vs fetch and how to design schemas:
cp -r docs/searxng-skill ~/.cursor/skills/searxng-capabilities
Reload Cursor. Workflows: docs/searxng-skill/SKILL.md.
MCP implementation details: mcp-server/README.md. Extract pipeline: extractor-sidecar/README.md, docs/extract-sidecar-specification.md.
Operations
Services use restart: unless-stopped. Redis data lives in a Docker volume; SearXNG config in ./searxng/.
docker compose ps
docker compose logs --tail=50
docker compose pull && docker compose up -d # update images
Logs rotate at 1MB per container. Tune engines in searxng/settings.yml if needed.
Troubleshooting
Full reset (removes volumes):
docker compose down -v && docker compose up -d
Documentation
Acknowledgments
Built on SearXNG, Docker, Redis, and the Model Context Protocol.