SearXNG + Tor in Docker: Your Own Private Search Engine
Every search you type into Google, Bing, or DuckDuckGo gets logged, profiled, and sold. Your search history is a detailed map of your thoughts, fears, medical concerns, financial worries, and political leanings.
SearXNG fixes this. It’s an open-source metasearch engine that queries 40+ search engines on your behalf — without sending your identity along for the ride. Add Tor routing and you’ve got a search engine that doesn’t even reveal your IP to the engines it queries.
This guide gets you from zero to running in about fifteen minutes.
What You’re Building
Browser ──HTTPS:443──► Caddy ──HTTP:8080──► SearXNG (Docker)
│
SOCKS5:9050
│
Tor (systemd)
- SearXNG aggregates results from Google, Bing, DuckDuckGo, Brave, and dozens more
- Tor anonymises outgoing queries so search engines can’t see your IP
- Caddy encrypts browser-to-server traffic with HTTPS (even on a LAN, encrypted is better)
- Docker keeps everything contained and easy to update
Prerequisites
- A Linux box (Raspberry Pi, old laptop, VM — anything with Docker)
- Docker installed (
sudo apt install docker.ioor official docs) - Root/sudo access
- 512MB RAM minimum (1GB+ recommended)
Step 1: Install and Configure Tor
sudo apt update && sudo apt install -y tor
Edit /etc/tor/torrc and add:
SocksPort 0.0.0.0:9050
Start it:
sudo systemctl enable --now tor
Verify Tor works:
curl -x socks5h://127.0.0.1:9050 https://check.torproject.org 2>&1 | grep -i congratulations
You should see: “Congratulations. This browser is configured to use Tor.”
Step 2: Configure SearXNG
Create the config directory and settings file:
sudo mkdir -p /etc/searxng
Generate a secret key:
python3 -c "import secrets; print(secrets.token_hex(32))"
Create /etc/searxng/settings.yml:
use_default_settings: true
general:
instance_name: "SearXNG Local"
enable_metrics: true
server:
secret_key: "PASTE_YOUR_GENERATED_KEY_HERE"
limiter: false
image_proxy: true
bind_address: "0.0.0.0:8080"
search:
safe_search: 0
default_lang: en
formats:
- html
- json
ui:
default_theme: simple
theme_args:
simple_style: light
outgoing:
request_timeout: 15
max_request_timeout: 25
proxies:
http: socks5h://127.0.0.1:9050
https: socks5h://127.0.0.1:9050
engines:
- name: google
disabled: false
- name: bing
disabled: false
- name: duckduckgo
disabled: false
- name: brave
disabled: false
- name: startpage
disabled: false
- name: wikipedia
disabled: false
- name: google news
disabled: false
- name: bing news
disabled: false
- name: duckduckgo news
disabled: false
- name: github
disabled: false
- name: stackoverflow
disabled: false
- name: arxiv
disabled: false
- name: reddit
disabled: false
The proxies block under outgoing routes all search queries through Tor. Remove it if you prefer direct queries (e.g., when your network already uses a VPN).
Timeout note: Tor adds latency. The 15/25 second timeouts accommodate this. Without Tor, 10/20 is fine.
Step 3: Launch SearXNG
docker run -d \
--name searxng \
--network host \
--restart unless-stopped \
-v /etc/searxng:/etc/searxng \
searxng/searxng:latest
Why --network host? SearXNG needs to reach Tor’s SOCKS proxy at 127.0.0.1:9050. Host networking makes this seamless — no Docker bridge routing needed.
Verify it’s running:
curl -s 'http://localhost:8080/search?q=test&format=json' | python3 -m json.tool | head -20
You should see JSON search results. Open http://YOUR_HOST_IP:8080 in a browser for the web interface.
Step 4: Add HTTPS with Caddy (Recommended)
Even on a private network, encrypting traffic is good practice. Caddy makes this trivial with automatic self-signed certificates.
Install Caddy:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install -y caddy
Edit /etc/caddy/Caddyfile:
http://YOUR_HOST_IP {
redir https://{host}{uri} permanent
}
https://YOUR_HOST_IP {
tls internal
reverse_proxy localhost:8080
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
Referrer-Policy "no-referrer"
}
}
Replace YOUR_HOST_IP with the machine’s LAN IP (e.g., 10.0.0.50).
tls internal generates a self-signed certificate — public CAs like Let’s Encrypt won’t issue certs for private IPs.
caddy validate --config /etc/caddy/Caddyfile
sudo systemctl restart caddy
To avoid browser warnings, trust the self-signed CA system-wide:
sudo cp /var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt \
/usr/local/share/ca-certificates/caddy-local-ca.crt
sudo update-ca-certificates
For browser trust, import the same root.crt file into your browser’s certificate authorities (Firefox: Settings → Privacy → Certificates → Import).
Step 5: Verify the Full Stack
# HTTP direct
curl -s 'http://localhost:8080/search?q=privacy&format=json' \
| python3 -c "import sys,json; r=json.load(sys.stdin); print(f'{len(r.get(\"results\",[]))} results')"
# HTTPS through Caddy
curl -s 'https://YOUR_HOST_IP/search?q=privacy&format=json' \
| python3 -c "import sys,json; r=json.load(sys.stdin); print(f'{len(r.get(\"results\",[]))} results')"
# Tor verification
docker exec searxng curl -x socks5h://127.0.0.1:9050 \
https://check.torproject.org 2>&1 | grep -i congratulations
All three should succeed. You now have a private, Tor-routed, HTTPS-encrypted search engine running on your own hardware.
Maintenance
# View logs
docker logs searxng --tail 50
# Restart after settings change
docker restart searxng
# Update SearXNG
docker pull searxng/searxng:latest
docker stop searxng && docker rm searxng
# Re-run the docker run command from Step 3
# Check Tor status
sudo systemctl status tor
Optional: JSON API for Automation
With json in the formats list, SearXNG doubles as a search API:
curl -s 'http://localhost:8080/search?q=linux+hardening&format=json' | jq '.results[:3]'
This is useful for feeding search results into scripts, monitoring tools, or AI pipelines — all without touching a commercial API or leaking your queries.
What You’ve Gained
| Before | After |
|---|---|
| Google logs every search | Your queries stay on your hardware |
| One engine’s bias | 40+ engines aggregated |
| Your IP visible to search engines | Tor hides your origin |
| HTTP on LAN | HTTPS encrypted |
| Dependent on external services | Self-hosted, yours to control |
Your search history is nobody’s business but yours.
Search is thinking out loud. Keep your thoughts private.