SearXNG selbst hosten: Deine private Metasuche mit Docker Compose
Google sammelt, Bing auch – SearXNG nicht. Die Open-Source-Metasuche fragt Google, Bing, Wikipedia, DuckDuckGo & Co. für dich ab, filtert Werbung und Tracking aus den Ergebnissen und protokolliert nichts. In diesem Tutorial richtest du dir deine eigene Instanz mit Docker Compose ein – inklusive Konfigurationsdateien, Reverse Proxy und Bot-Schutz per Limiter.
Warum eine eigene Suchmaschine?
Eine Metasuchmaschine hat selbst keinen eigenen Suchindex – sie schickt deine Anfrage an viele Anbieter gleichzeitig und bündelt die Ergebnisse. Der entscheidende Unterschied zu den kommerziellen Portalen: Bei SearXNG geschieht das auf deinem Server. Es werden keine Profile über dich angelegt, keine Suchanfragen geloggt, keine personalisierten (und teuren) Werbe-Links vorgeschaltet.
Die Vorteile deiner eigenen Instanz:
- Kein Tracking, kein Profiling – Suchanfragen verlassen deinen Server nur anonymisiert zu den End-Engines.
- Keine Werbung & keine Filterblase – dieselben Ergebnisse für alle, unabhängig von deinem Browser-Verlauf.
- Ein eigenes Such-UI – als Startseite im Browser, als Standard-Suchmaschine oder per Firefox-Add-on nutzbar.
- Volle Kontrolle: Engines an-/abwählen, Sprache, Theme, SafeSearch – alles konfigurierbar.
- Keine Rate-Limits kommerzieller Frontends, keine Cloud-Abhängigkeit.
💡 Erst ausprobieren? Unsere öffentliche Test-Instanz läuft unter s.huuu.biz – dort kannst du Oberfläche und Ergebnisqualität checken, bevor du dir deine eigene Instanz aufsetzt.
Vorbereitung: Ordnerstruktur & Grundlagen
Du brauchst einen Linux-Server (x86_64 oder arm64) mit Docker und dem Compose-Plugin – wie das geht,
zeigen wir in unserem Docker-Compose-Einsteiger-Artikel.
Anschließend legen wir ein sauberes Projektverzeichnis an. Die Struktur lehnt sich an die
offizielle
Installationsanleitung an – eine Sache ist dabei wichtig: Die settings.yml liegt in
einem eigenen Ordner config/, der später ins Container-Verzeichnis
/etc/searxng gemountet wird:
mkdir -p ~/searxng/config && cd ~/searxng
# Nachher sollte die Struktur so aussehen:
# ~/searxng/
# ├── docker-compose.yml
# ├── .env
# └── config/
# └── settings.yml
Die drei Dateien: docker-compose.yml, .env & settings.yml
1. docker-compose.yml
SearXNG läuft heute mit zwei Diensten: dem SearXNG-Container selbst und einer Valkey-Datenbank. Valkey ist der Nachfolger von Redis (das Projekt hat wegen der Lizenzänderung auf den Redis-Fork gewechselt) und wird vom Limiter – dem Bot-Schutz – als Speicher für Zähler und Sperren verwendet.
services:
searxng:
image: docker.io/searxng/searxng:latest
container_name: searxng
restart: unless-stopped
env_file: .env
ports:
- "127.0.0.1:8080:8080"
volumes:
- ./config:/etc/searxng/
- searxng-cache:/var/cache/searxng/
depends_on:
- valkey
valkey:
image: docker.io/valkey/valkey:9-alpine
container_name: searxng-valkey
restart: unless-stopped
command: valkey-server --save 30 1 --loglevel warning
volumes:
- valkey-data:/data/
volumes:
searxng-cache:
valkey-data:
Die wichtigsten Entscheidungen in dieser Datei:
- Port nur auf localhost:
127.0.0.1:8080:8080macht die Instanz von außen unsichtbar – HTTPS und Domain übernimmt ein Reverse Proxy (Abschnitt weiter unten). Die Web-UI wird also nie unverschlüsselt exponiert. - Zwei Volumes:
./configenthält deinesettings.yml(lesbar & versionierbar),searxng-cachespeichert Daten wie den Favicon-Cache. Das benannte Volume bleibt beim Update erhalten. - Valkey bekommt nur ein Daten-Volume, keinen öffentlichen Port – erreichbar ist er für SearXNG im internen Compose-Netz unter dem Dienstnamen
valkey.
💡 DockerHub-Rate-Limits? DockerHub begrenzt inzwischen unauthentifizierte
Image-Pulls. Wer davon betroffen ist, nutzt stattdessen den offiziellen Spiegel:
ghcr.io/searxng/searxng (GitHub Container Registry). Wer Updates reproduzierbar halten
will, pinnt statt :latest ein konkretes Datums-Tag wie
:2026.9.18-xxxxx – abrufbar unter den Tags der Registry.
2. .env
SearXNG liest Umgebungsvariablen mit dem Präfix SEARXNG_* und überschreibt damit gezielt
Werte der Konfiguration – so bleibt die settings.yml schlank. Wir legen die Datei
.env im Projektordner an (sie wird per env_file an den Container gereicht):
# Öffentliche Adresse deiner Instanz (mit Slash am Ende!)
SEARXNG_BASE_URL=https://search.example.org/
# Geheimer Schlüssel – generieren, NICHT übernehmen!
SEARXNG_SECRET=HIER_LANGES_GEHEIMNIS_EINFUEGEN
# Optionale Einstellungen (Standard ist deaktiviert):
# Limiter (Bot-Schutz) aktivieren – benötigt Valkey, siehe Abschnitt weiter unten
#SEARXNG_LIMITER=true
#SEARXNG_PUBLIC_INSTANCE=false
#SEARXNG_VALKEY_URL=valkey://valkey:6379/0
# Bestimmte Versions-Tags pinnen (statt :latest im Compose-File)
#SEARXNG_VERSION=2026.9.18-xxxxx
3. config/settings.yml
Das Herzstück der Konfiguration. Wichtig: Mit use_default_settings: true übernehmen wir
die sinnvollen Standardwerte und überschreiben nur, was wir wirklich ändern wollen. So bleibt die
Datei klein und Updates brechen nicht an veralteten Optionen:
# config/settings.yml
use_default_settings: true
general:
instance_name: "Search" # Name, der in der Oberfläche angezeigt wird
debug: false # NIEMALS in Produktion aktivieren
search:
default_lang: "de" # Sprache der Ergebnisse
ui:
default_locale: "de" # Sprache der Oberfläche
Secret, Base-URL & Co. – die wichtigsten Einstellungen
Drei Werte solltest du verstehen, bevor du startest:
SEARXNG_SECRET: Signiert u. a. Cookies und Formulare. Der Standardwertultrasecretkeyist tabu. Ein sicheres Secret erzeugst du mit:openssl rand -hex 32– das Ergebnis in die.envübernehmen.SEARXNG_BASE_URL: Die öffentliche URL deiner Instanz mit abschließendem Slash (https://search.example.org/). Sie sorgt dafür, dass Links, RSS-Feeds und die API korrekt auf deine Domain zeigen. Änderst du später die Domain, muss auch dieser Wert mit.server.public_instance/server.limiter: Für den rein privaten Gebrauch bleiben beide deaktiviert (Standard). Sobald die Instanz im Internet erreichbar ist, gehörenlimiterund die Valkey-Anbindung aktiviert – dazu gleich mehr.
⚠️ Achtung: debug: true in der settings.yml gibt dir
hilfreiche Fehlermeldungen, aber auch interne Details preis und bremst die Instanz. Auf öffentlichen
Systemen immer debug: false lassen – Fehler siehst du dann in den Logs:
docker compose logs -f searxng.
Start & Funktionstest
Jetzt wird gestartet:
cd ~/searxng
docker compose up -d
Beim ersten Start lädt Compose beide Images und startet SearXNG samt Valkey. Danach der Funktionstest:
# Läuft der Container?
docker compose ps
# Antwortet SearXNG? (HTTP 200 erwartet)
curl -sI http://127.0.0.1:8080 | head -n 1
# Ergebnis-API direkt testen (liefert JSON-Treffer)
curl -s "http://127.0.0.1:8080/search?q=docker+compose&format=json" | head -c 300
Auf dem Server selbst erreichst du die Oberfläche unter http://127.0.0.1:8080 – etwa per
SSH-Tunnel (ssh -L 8080:127.0.0.1:8080 dein-server). Für den Zugriff von außen folgt jetzt
der Reverse Proxy.
Reverse Proxy & HTTPS
Wer seine Instanz öffentlich nutzen will, hängt sie hinter einen Reverse Proxy mit HTTPS – so, wie wir
es auch im Proxy-Vergleich empfehlen. Da SearXNG nur auf
127.0.0.1:8080 lauscht, genügt beim Caddy ein Eintrag:
# Caddyfile
search.example.org {
encode zstd gzip
reverse_proxy 127.0.0.1:8080
}
Wer einen Nginx Proxy Manager oder Traefik nutzt, trägt entsprechend den Upstream
http://127.0.0.1:8080 ein. In der Firewall reichen dann Port 80/443 – der SearXNG-Port
8080 bleibt außen zu.
⚠️ Limiter & Proxy-IPs: Läuft der Limiter und dein Reverse Proxy ist der einzige Zugang, sieht SearXNG zunächst nur die Proxy-IP (127.0.0.1) – alle Besucher teilen sich dann ein Limit. Damit der Limiter die echten Client-IPs auswertet, muss er entsprechend konfiguriert werden (Details in der offiziellen Doku zu Valkey/ Limiter-Konfiguration). Das ist unkritisch, solange SearXNG ausschließlich lokal erreichbar ist – exponiere den Port also nie direkt ins Internet.
Limiter & Valkey: Schutz für öffentliche Instanzen
Öffentliche SearXNG-Instanzen werden von Bots und Missbrauchsskripten regelmäßig als freie
„Such-API“ zweckentfremdet. Dagegen hilft der eingebaute Limiter: Er begrenzt
Anfragen pro IP-Zeitfenster und erkennt Bot-Muster. Seit dem Wechsel auf Valkey gilt:
Der Limiter benötigt zwingend eine Valkey-Datenbank – genau dafür ist der
valkey-Dienst in unserem Compose-File zuständig.
So aktivierst du den Schutz für eine öffentliche Instanz (in der .env):
SEARXNG_LIMITER=true
SEARXNG_PUBLIC_INSTANCE=true
SEARXNG_VALKEY_URL=valkey://valkey:6379/0
valkey://valkey:6379/0 ist dabei kein Tippfehler: valkey ist der
Dienstname des Containers im Compose-Netzwerk, Port 6379 der Valkey-Standardport, /0
die Datenbank-Nummer. Für den rein privaten Gebrauch (nur du und Familie) darf der Limiter
aus bleiben – die Standardeinstellung limiter: false ist dann völlig in Ordnung.
💡 Tipp fürs Finetuning: Wer die Schwellenwerte anpassen will (z. B. höhere
Limits für eigene Geräte), legt in config/ eine limiter.toml an – Details
dazu und zur Bot-Erkennung stehen in der offiziellen Doku. Einfacher für den Anfang: die
Standardwerte nutzen und nach ein paar Tagen in die Logs schauen.
Updates & Backups
Das Update ist dank Compose ein Zweizeiler – Volumes und Konfiguration bleiben unangetastet:
cd ~/searxng
docker compose pull
docker compose up -d
Und so sicherst du deine Instanz:
- Konfiguration: Der Ordner
~/searxng/config/ist deine gesamte manuelle Konfiguration – regelmäßig sichern (z. B. per Git-Repo oder rsync). - Cache & Valkey-Daten: Beides ist regenerierbar (Favicon-Cache, Limiter-Zähler). Ein Backup der benannten Volumes ist möglich
(
docker compose down, dann~/.docker/volumes/…kopieren), für den Normalbetrieb aber nicht zwingend nötig. - Komplett-Wiederherstellung: Neuer Server → Projektordner wiederherstellen →
docker compose up -d→ fertig. Schöner Nebeneffekt: SearXNG hat keine eigene Datenbank, die konsistent gesichert werden müsste.
Fehlerbehebung: Die häufigsten Stolperfallen
| Problem | Lösung |
|---|---|
| Keine Ergebnisse / Engine-Fehler („Rate limit“) | Einzelne Engines limitieren Server-IPs. In den Logs nachsehen (docker compose logs -f searxng), betroffene Engines in der settings.yml temporär deaktivieren oder Abfrage später wiederholen. |
| Instanz ist langsam oder antwortet nicht | Debug aus (debug: false), Container-Ressourcen prüfen (docker stats) – die Metasuche braucht pro Anfrage mehrere parallele Engine-Requests. |
| Limiter-Fehler „Valkey connection refused“ | Valkey-URL prüfen: SEARXNG_VALKEY_URL=valkey://valkey:6379/0 und depends_on: valkey im Compose-File nicht vergessen. |
| Alle Besucher teilen sich ein Limit | Reverse-Proxy-IP-Problem: Limiter-IP-Auswertung konfigurieren (siehe Abschnitt „Limiter & Proxy-IPs“) – Port 8080 niemals öffentlich binden. |
| Bilder werden nicht geladen | Für den Bild-Proxy server.image_proxy: true setzen – dann lädt SearXNG Bilder über die eigene Domain (optional, bei HTTPS-Instanzen häufig nötig). |
| „Unknown setting“-Warnungen im Log | Meist veraltete Optionen aus alten Tutorials. Mit use_default_settings: true arbeiten und nur dokumentierte Schlüssel überschreiben. |
Fazit
Eine eigene SearXNG-Instanz ist eines der dankbarsten Self-Hosting-Projekte überhaupt: Sie braucht
kaum Ressourcen, keine Datenbank, keine regelmäßige Wartung – und liefert dir von Tag eins an
werbefreie, trackingfreie Suchergebnisse für die ganze Familie. Mit der Struktur aus
docker-compose.yml, .env und einer schlanken settings.yml
ist das Setup in zehn Minuten erledigt. Wer die Instanz öffentlich anbietet, aktiviert zusätzlich
den Valkey-gestützten Limiter und hängt sie hinter HTTPS – mehr braucht es nicht.
✅ Zum Mitnehmen: (1) use_default_settings: true hält deine
settings.yml klein und update-sicher. (2) Secret per openssl rand -hex 32
erzeugen, base_url mit Slash am Ende setzen. (3) Port 8080 nur an
127.0.0.1 binden, außen läuft ein Reverse Proxy mit HTTPS. (4) Öffentliche Instanz =
Limiter aktivieren, und der braucht Valkey. (5) Backup = Ordner config/ sichern;
Updates = docker compose pull && up -d.