SearXNG is a metasearch engine: one box, many search engines, no tracking, no profiling, no third-party cookies. The same query fans out to Google, Bing, Brave, Wikipedia, Stack Overflow and dozens more, and returns one clean, neutral results page.
What it is
A single-page search interface over a configured set of engines. Because every query originates from your server, the search engines see one client instead of a fingerprintable population, and you get results without ad injection. There's also a JSON API, which is what makes it useful as a backend.
Before you start
- The stock settings will get you rate-limited or blocked within days. Making the outgoing traffic look like a normal browser is a configuration task, not a default.
- Decide whether it's public. An open instance on the internet gets scraped and used to launder traffic to search engines within about a week.
- Redis is optional but strongly recommended. Without it, SearXNG can't deduplicate concurrent identical requests and a burst of traffic hammers the upstream engines.
1 — Write the settings file first
mkdir -p ~/services/searxng
cd ~/services/searxng
cat > settings.yml <<'EOF'
use_default_settings: true
general:
instance_name: "my search"
debug: false
server:
secret_key: "CHANGE_ME_48_random_chars"
limiter: true
image_proxy: true
bind_address: "0.0.0.0"
port: 8080
search:
safe_search: 1
autocomplete: "duckduckgo"
default_lang: "en"
outgoing:
request_timeout: 5.0
max_request_timeout: 10.0
pool_connections: 100
pool_maxsize: 20
enable_http2: true
engines:
- name: google
disabled: false
- name: duckduckgo
disabled: false
- name: brave
disabled: false
- name: wikipedia
disabled: false
- name: stackexchange
disabled: false
EOF
2 — Write the compose file
services:
searxng:
image: searxng/searxng:latest
container_name: searxng
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
volumes:
- ./searxng:/etc/searxng
- ./searxng-data:/var/cache/searxng
environment:
SEARXNG_BASE_URL: https://search.example.com/
INSTANCE_NAME: my search
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080/"]
interval: 30s
timeout: 5s
retries: 3
valkey:
image: valkey/valkey:8-bookworm
container_name: searxng-valkey
restart: unless-stopped
volumes:
- ./valkey:/data
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 30s
timeout: 5s
retries: 3
3 — Start it
docker compose up -d
docker compose logs -f searxng | grep -i "started\|error"
4 — First-run setup
- Open
https://search.example.comand run a test search. If every engine returns nothing, it's a rate limit, not a bug. - Check Preferences → Engines and enable the ones you want. Google's JSON API has long since been shut down, so the "google" engine scrapes — functional, but fragile.
- Set an outbound proxy or rotate the
User-Agentif you're being blocked. Persistent 403s from one engine mean that specific engine needs to go. - Enable the limiter and keep it on. It stops a single client from running thousands of queries and getting your whole instance banned upstream.
- Use the JSON API for scripted queries:
curl -s "https://search.example.com/search?q=nextcloud&format=json".