Why Self-Host a Meta Search Engine
Every search query you type into Google, Bing, or DuckDuckGo sends your IP address, browser fingerprint, and search terms to servers you don’t control. SearXNG solves this by acting as a privacy proxy between you and the search engines — your browser talks to your SearXNG instance, and SearXNG queries the upstream engines on your behalf without leaking your IP.
Running SearXNG in your homelab gives you:
- Full visibility into which engines handle each query
- Engine selection per category (general, files, images, maps, social media)
- No rate limits from shared public instances
- Custom themes and dark mode out of the box
- Self-contained stack — Docker Compose, no external dependencies
I run SearXNG at my homelab behind Traefik, and it replaced browser-based search entirely. On mobile, I set the instance as the default search engine in Firefox. One config file controls which engines are enabled, how queries are routed, and what data is stored.
Prerequisites for SearXNG Docker Deployment
Before starting, make sure you have:
- Docker and Docker Compose installed on your Docker host (a Proxmox LXC or low-resource VM works fine — SearXNG runs on 512 MB RAM)
- A domain name pointing to your homelab (optional but recommended for Traefik)
- Traefik or another reverse proxy already running (this guide uses Traefik)
The SearXNG stack uses two containers: the SearXNG application itself and Valkey (the Redis-compatible key-value store) for caching and rate limiting.
Directory Structure
Create a clean directory for the stack:
|
|
SearXNG Docker Compose Setup
The official SearXNG compose template uses a docker-compose.yml and a .env file. Here is a version configured for homelab use with Traefik:
|
|
Generate a strong secret key for the .env file:
|
|
Then create /opt/searxng/.env:
|
|
What the Compose File Does
- core — The SearXNG application listening on port 8080 inside the container. The
SEARXNG_BASE_URLtells SearXNG what external URL to use for link generation. TheSEARXNG_SECRET_KEYencrypts session data and rate limiter state. - valkey — In-memory cache used by SearXNG for rate limiting and temporary data. Because it replaces Redis, all SearXNG Redis configuration works against it with no changes. The
--save 3600 1flag writes a snapshot every hour if at least one change occurred. - networks — The proxy network is external (shared with Traefik). The internal network isolates Valkey from the outside.
- cap_drop / cap_add — Minimal Linux capabilities for container hardening.
Configuring SearXNG Search Engines and Features
SearXNG generates a default settings.yml on first start. You can override it by placing a file in the mounted ./core-config directory.
Create /opt/searxng/core-config/settings.yml:
|
|
Key Configuration Points
use_default_settings: true— Loads the built-in defaults first, then your overrides apply on top. This keeps the file small and maintainable.image_proxy: true— Images served through SearXNG, not directly from the source, preventing referrer leakage.limiter: true— Enables rate limiting using Valkey. Without this, any bot can hammer your upstream search engines and get your IP rate-limited.redis_url: "redis://valkey:6379/0"— Points to the Valkey container in the internal Docker network. Theredis://protocol prefix works because Valkey is Redis-protocol compatible.public_instance: false— Prevents your instance from appearing in the public SearXNG instance list. Keep your instance private.default_theme_style: dark— Dark mode by default, with the simple theme.
Exposing SearXNG with Traefik Reverse Proxy
If you already run Traefik as a Docker reverse proxy, the compose file labels above handle the routing. Make sure you have:
- A DNS A record for
search.yourdomain.compointing to your homelab - The
traefik-netDocker network available (adjust the name to match your setup) - Traefik’s ACME (Let’s Encrypt) configuration active for TLS
Create or verify the Docker network:
|
|
The Traefik labels in the compose file:
traefik.http.routers.searxng.rule=Host(\search.yourdomain.com`)` — Routes traffic for that hostname to SearXNGtraefik.http.routers.searxng.entrypoints=websecure— Uses the HTTPS entrypointtraefik.http.services.searxng.loadbalancer.server.port=8080— Points to the container’s internal port 8080
If you use Nginx Proxy Manager or Caddy instead, the setup is similar — just proxy pass to http://searxng-core:8080 from the reverse proxy container.
Starting SearXNG and Verifying the Deployment
Start the stack:
|
|
Check the logs to confirm startup:
|
|
Look for the line:
[INFO] starting server on 0.0.0.0:8080
Visit your instance at https://search.yourdomain.com. You should see the SearXNG search interface with your configured instance_name.
Testing Searches
Type a query and verify:
- Results load from multiple engines
- The “Categories” dropdown shows enabled categories
- The preferences page (
/preferences) lists your configured settings - Dark mode renders correctly
Common Issues
“Invalid base_url” error in logs — The SEARXNG_BASE_URL in docker-compose.yml must match the actual URL you are accessing. If you are testing locally, use http://localhost:8080.
Search returns no results — Some engines require JavaScript and may not work with all themes. Try the simple theme if results fail with oscar. Check docker compose logs core for engine-specific error messages.
Rate limiter errors — If you see 429 Too Many Requests for upstream engines, SearXNG respects upstream rate limits. Reduce query frequency or add a delay in settings.yml:
|
|
Maintaining Your SearXNG Instance
Updating Containers
Pull the latest images and restart:
|
|
Always check the SearXNG release notes before updating, as configuration keys occasionally change.
Backup
Back up two directories — everything else is disposable:
|
|
Store the backup off-server (Proxmox Backup Server, remote storage).
Monitoring
Add a health check to the SearXNG service in docker-compose.yml:
|
|
SearXNG exposes a /health endpoint that returns a 200 status when the application is running and engines are responsive.
Conclusion
SearXNG replaces public search engines with a self-hosted, privacy-respecting alternative that gives you full control over which engines process your queries, what data is cached, and how rate limiting works. The Docker Compose stack runs on minimal hardware, integrates with any reverse proxy, and costs nothing beyond your homelab’s electricity.
Set up search categories — images through Pixabay, code through GitHub and StackOverflow, general queries through DuckDuckGo and Brave. Disable the engines you never use. Drop the default search engine into your browser settings and never expose your IP to a search engine again.