SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-09-05

SearXNG selbst hosten: private Suche mit Docker

Betreiben Sie SearXNG auf einem eigenen VPS mit Docker Compose. Die Anleitung zeigt settings.yml, Limiter, nginx mit TLS und eine JSON-Such-API für eigene Skripte.

Was Sie erstellen

Mit einem selbst gehosteten SearXNG betreiben Sie eine private Suchmaschine auf Ihrem eigenen Server. SearXNG ist eine Metasuchmaschine: Sie nimmt Ihre Suchanfrage entgegen, fragt andere Suchmaschinen wie Google, Bing, DuckDuckGo und Wikipedia ab und fasst die Ergebnisse auf einer gemeinsamen Ergebnisseite zusammen. Es wird kein Profil erstellt und kein Tracking-Cookie gesetzt, weil nur Ihr eigener Rechner Ihre Suchanfrage speichert. Wenn Sie ältere Anleitungen zu einem Projekt namens Searx gefunden haben, handelt es sich dabei um das Projekt, von dem dieses Projekt abgespalten wurde. Seit 2023 gab es dort keinen Commit mehr. Prüfen Sie daher den Status beider Projekte, bevor Sie einer Anleitung folgen.

Der Stack ist klein. Er besteht aus zwei Containern, einer Einstellungsdatei und einem Reverse Proxy. SearXNG lässt sich problemlos auf einem kleinen VPS betreiben. Das gilt nicht für jeden selbst gehosteten Dienst: Bei den in PhotoPrism und Immich verglichenen Fotobibliotheken wird der minimale RAM-Bedarf durch den Indexer und nicht durch die Webanwendung bestimmt. Die eigentliche Entscheidung ist, ob die Instanz privat oder öffentlich sein soll. Privat bedeutet, dass nur Sie und Ihre eigenen Skripte darauf zugreifen. Öffentlich bedeutet, dass jeder im Internet Suchanfragen senden kann. Diese Entscheidung ändert die Sicherheitseinstellungen. Treffen Sie sie, bevor Sie Befehle eingeben. Die Standardeinstellung ist privat.

Es gibt noch einen weiteren Grund für den Betrieb einer eigenen Instanz. Eine SearXNG-Instanz stellt eine JSON-Schnittstelle bereit. Jedes Skript und jeder von Ihnen erstellte AI-Agent erhält damit eine Such-API, die Sie selbst kontrollieren. Sie benötigen keinen Schlüssel, zahlen nicht pro Suchanfrage und erhalten keine Quota-E-Mails.

SearXNG mit Docker Compose installieren

Das Projekt stellt ein Container-Image und eine Compose-Datei bereit. Laden Sie beides auf einen neuen Ubuntu-24.04-Server herunter, auf dem Docker Engine und das Compose-Plugin bereits installiert sind. Wenn Docker für Sie neu ist, beginnen Sie mit Docker-Compose-Grundlagen auf einem VPS und kehren Sie anschließend hierher zurück.

sudo install -d -o "$USER" -g "$USER" -m 750 /opt/searxng
cd /opt/searxng
mkdir -p core-config
curl -fsSL \
  -O https://raw.githubusercontent.com/searxng/searxng/master/container/docker-compose.yml \
  -O https://raw.githubusercontent.com/searxng/searxng/master/container/.env.example
cp -i .env.example .env

Die Compose-Datei definiert zwei Dienste. core ist SearXNG selbst, und valkey ist ein In-Memory-Datenspeicher, der für die Ratenbegrenzung und für kurzlebigen Status verwendet wird. Sie bindet ./core-config/ im Container unter /etc/searxng/ ein. Dadurch befindet sich die gesamte Konfiguration, die Sie vornehmen, in diesem einen Verzeichnis auf dem Host.

Bearbeiten Sie jetzt .env. Jede Zeile im mitgelieferten Beispiel ist auskommentiert. Deshalb startet der Container auf Port 8080 an jeder Adresse. Entfernen Sie die Kommentarzeichen bei diesen drei Zeilen und setzen Sie die angegebenen Werte.

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1 ist die entscheidende Einstellung. Sie sorgt dafür, dass der veröffentlichte Port 127.0.0.1:8080:8080 statt [::]:8080:8080 verwendet wird. Der Container antwortet dadurch nur über die Loopback-Adresse, und das Internet kann ihn nicht direkt erreichen. Wenn Sie diese Einstellung auslassen, ist der Container sofort nach dem Start exponiert. Ein veröffentlichter Docker-Port wird vor Ihren Firewall-Regeln eingefügt. Diese häufige Fehlerquelle wird hier vollständig erläutert: Veröffentlichte Docker-Ports umgehen ufw.

SEARXNG_VERSION=latest ist in Ordnung, solange Sie sich mit dem System vertraut machen. Auf einem Server, der Ihnen wichtig ist, sollten Sie den Tag festlegen. Im Juli 2026 basieren die Release-Tags auf dem Datum und sehen wie 2026.3.25-541c6c3cb aus. Eine festgelegte Version wird dann aktualisiert, wenn Sie es entscheiden, und nicht wenn sich die Registry unbemerkt ändert. Dieselbe Disziplin lohnt sich bei allen anderen dauerhaft laufenden Diensten auf dem Server. Deshalb legt auch ein selbst gehostetes RustDesk-Relay seine Image-Tags fest: Ein unbeaufsichtigtes Upgrade eines Fernzugriffsdienstes macht sich im ungünstigsten Moment bemerkbar.

settings.yml: die relevanten Teile

Erstellen Sie core-config/settings.yml vor dem ersten Start. use_default_settings: true weist SearXNG an, zunächst die mitgelieferten Standardeinstellungen zu laden und anschließend nur die von Ihnen gesetzten Schlüssel anzuwenden. Dadurch bleibt Ihre Datei kurz und übersteht Upgrades, die neue Optionen hinzufügen.

Generieren Sie zuerst das Secret, da der Wert direkt in die Datei übernommen wird.

openssl rand -hex 32
use_default_settings: true

general:
  instance_name: "search.example.com"

server:
  base_url: "https://search.example.com/"
  secret_key: "paste-the-openssl-output-here"
  limiter: false
  public_instance: false
  image_proxy: true

valkey:
  url: valkey://valkey:6379/0

search:
  safe_search: 0
  autocomplete: "duckduckgo"
  formats:
    - html
    - json

secret_key signiert Sitzungs- und Token-Daten. Der mitgelieferte Standardwert ist die Zeichenfolge ultrasecretkey. Wenn Sie ihn beibehalten, kann jeder, der diesen Standardwert kennt, diese Token fälschen. Ersetzen Sie ihn einmal und ändern Sie ihn danach nicht mehr. Eine spätere Änderung verwirft alle gespeicherten Einstellungen.

base_url muss die öffentliche HTTPS-Adresse mit abschließendem Schrägstrich sein. Diese Adresse verwendet SearXNG für die Links, die es rendert. Wenn sie auf localhost zeigt, verweist der Link „nächste Seite“ in einem entfernten Browser auf den Rechner des Lesers und schlägt fehl.

formats legt fest, welche Ausgabetypen der Web-Endpunkt bereitstellt. json ist nicht in der Standardliste enthalten. Eine JSON-Anfrage liefert daher 403, bis Sie den Typ hinzufügen. image_proxy: true leitet Vorschaubilder der Ergebnisse über Ihren Server. Dadurch sehen die Websites, auf denen diese Bilder liegen, nicht die Adressen Ihrer Besucher.

Der valkey.url verwendet den Hostnamen valkey, weil dies der Servicename in der Compose-Datei ist. Compose setzt beide Container in ein gemeinsames Netzwerk, in dem Servicenamen aufgelöst werden. Wenn Sie auf localhost verweisen, schlägt der Limiter fehl, weil localhost innerhalb des core-Containers auf diesen Container selbst zeigt.

Das Secret liegt in einer Klartextdatei. Schützen Sie daher das Verzeichnis darum herum und nicht die Datei selbst. chmod 750 /opt/searxng hält andere Benutzer des Hosts fern. Setzen Sie core-config/settings.yml nicht auf den Modus 600. Der Container läuft als eigener unprivilegierter Benutzer. Wenn dieser die Datei nicht lesen kann, startet SearXNG überhaupt nicht.

Starten Sie den Stack und prüfen Sie ihn.

cd /opt/searxng
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080/

docker compose ps sollte beide Container im Zustand running anzeigen. Der curl sollte auf HTTP/1.1 200 OK antworten. Wenn keine Antwort kommt, lesen Sie docker compose logs core. Ein YAML-Fehler in settings.yml erscheint dort als Parse-Fehler mit Angabe der betroffenen Zeile.

Hinter nginx mit TLS betreiben

Der Container lauscht nur auf Loopback. nginx macht ihn erreichbar und fügt außerdem die Transportsicherheit (TLS) hinzu. Schreiben Sie /etc/nginx/sites-available/searxng.

server {
    listen 80;
    server_name search.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
sudo ln -s /etc/nginx/sites-available/searxng /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d search.example.com

nginx -t gibt syntax is ok und test is successful aus, bevor Sie nginx neu laden. Certbot schreibt dieselbe Datei um, damit sie auf 443 mit einem Zertifikat lauscht, und fügt eine Weiterleitung von Port 80 hinzu. Der DNS-Eintrag für search.example.com muss bereits auf diesen Server zeigen, weil die Zertifizierungsstelle den Besitz prüft, indem sie eine Datei über HTTP abruft. Die vollständige Anleitung einschließlich der Erneuerung finden Sie in der Certbot- und-nginx-Anleitung für Ubuntu 24.04.

Die beiden Weiterleitungs-Header sind nicht nur Dekoration. Ohne X-Forwarded-For und X-Real-IP enthält jede bei SearXNG eingehende Anfrage die Proxy-Adresse. Dadurch sieht der Ratenbegrenzer einen Client, der den gesamten Datenverkehr erzeugt, und kann die Besucher nicht voneinander unterscheiden.

Warum Skripte und Agenten eine JSON-Such-API verwenden

Mit json in formats liefert derselbe Endpunkt, der die Seite rendert, strukturierte Daten zurück.

curl -s 'http://127.0.0.1:8080/search?q=wireguard+mtu&format=json' \
  | jq -r '.results[0:5][] | .url'

Sie erhalten ein Objekt mit einem results-Array. Jeder Eintrag enthält url, title, content und die Suchmaschine, die das Ergebnis geliefert hat, sowie answers, infoboxes und suggestions. Das reicht aus, um einen Zusammenfasser, einen Linkprüfer oder eine Recherche-Schleife zu versorgen. Diese Ergebnisse an ein Sprachmodell zu übergeben, ist ein größerer Schritt, als es zunächst scheint, da Suchergebnisse nicht vertrauenswürdiger Text sind und eigene Anweisungen enthalten können. Genau damit befasst sich einen KI-Agenten auf Ihre SearXNG-Instanz zu richten ausführlich.

Das ist für alles relevant, was agentenähnlich arbeitet. Ein Sprachmodell hat einen Trainingsstichtag. Daher benötigt es eine Live-Suche, um Fragen zur Gegenwart zu beantworten. Kommerzielle Such-APIs berechnen Gebühren pro Abfrage und begrenzen die Rate meist stark. Eine lokale Instanz benötigt einen Container auf einem Server, für den Sie bereits bezahlen, und die Abfragen verlassen ihn nie. Wenn Sie Tools in ein Modell integrieren, führt dieselbe Überlegung zum Betreiben von MCP-Servern auf einem VPS. Ein Such-Tool ist dabei meist das erste Tool, das hinzugefügt wird.

Für die API-Nutzung gelten zwei Regeln. Halten Sie die Instanz privat. Binden Sie die API daher an die Loopback-Adresse oder an ein privates Netzwerk, und erlauben Sie nur Ihren eigenen Hosts den Zugriff. Fragen Sie die API anschließend mit geringer Frequenz ab. SearXNG leitet Ihre Anfrage an echte Suchmaschinen weiter. Ein Skript, das hundert Abfragen pro Sekunde ausführt, fordert Google daher geradezu auf, Ihren Server zu blockieren.

Der Limiter und was sich bei einer öffentlichen Instanz ändert

Der Limiter ist die Bot-Abwehr von SearXNG. Er überwacht Request-Header, Adressen und Request-Raten und verwirft Datenverkehr, der automatisiert wirkt. Dafür benötigt er Valkey, um diesen Status zu speichern. Deshalb ist Valkey in der Compose-Datei enthalten.

Auf einer privaten Instanz lassen Sie limiter: false aktiviert. Ihre eigenen Skripte erzeugen definitionsgemäß automatisierten Datenverkehr. Der Limiter würde daher genau die JSON-Aufrufe blockieren, für die Sie die Instanz eingerichtet haben. Die Zugriffskontrolle ist stattdessen Aufgabe des Reverse Proxy: ein allow- und deny-Paar in der nginx-location, HTTP-Basisauthentifizierung oder eine Firewall, die nur Ihre anderen Server zulässt. Wenn Sie von einem Laptop aus auf eine private Instanz zugreifen müssen, der zwischen verschiedenen Netzwerken wechselt, setzen Sie eine v3-Onion-Adresse davor. Tor verbindet sich dann mit demselben Loopback-Port, ohne etwas zusätzlich im Internet zu veröffentlichen.

Wenn Sie die Instanz für andere Benutzer veröffentlichen, aktivieren Sie beide Schalter.

server:
  limiter: true
  public_instance: true

Eine feinere Steuerung erfolgt in core-config/limiter.toml, das der Container unter /etc/searxng/limiter.toml einliest. Tragen Sie nur die Schlüssel ein, die Sie ändern möchten. Hinter einem Proxy müssen Sie den Proxy angeben. Andernfalls behandelt der Limiter Ihre nginx-Adresse als den einen Client, von dem der missbräuchliche Datenverkehr ausgeht.

[botdetection]
trusted_proxies = [
  '127.0.0.0/8',
  '::1',
]

[botdetection.ip_limit]
link_token = true

link_token = true veranlasst SearXNG, ein Token auszugeben, das nur eine echte Browsersitzung abruft. Dadurch werden die meisten einfachen Scraper gestoppt. Rechnen Sie damit, dass eine öffentliche Instanz innerhalb weniger Tage solche Zugriffe anzieht. Rechnen Sie außerdem mit Fehlern bei den Suchmaschinen. Je mehr Datenverkehr Sie weiterleiten, desto früher senden die Upstream-Suchmaschinen CAPTCHAs an Ihre Serveradresse zurück. Eine öffentliche SearXNG-Instanz erfordert laufende Betreuung. Eine private Instanz nicht. Deshalb steht sie auf den meisten kurzen Listen der Dienste, die sich 2026 für Self-Hosting lohnen. Nicht jeder Eintrag auf diesen Listen ist Infrastruktur: Eine Jellyfin-Bibliothek als begehbaren Verleih aus den 90er-Jahren neu aufzubauen nutzt ebenfalls nur denselben Container hinter demselben nginx-Block, der statt auf einen Workflow auf einen Abend ausgerichtet ist.

Warum Suchanfragen keine Ergebnisse liefern

Öffnen Sie /stats auf Ihrer Instanz. Dort werden alle Engines mit ihrer Fehlerquote und Antwortzeit aufgelistet. Diese Übersicht ist die erste Anlaufstelle, wenn die Ergebnisse unvollständig wirken.

Ein in settings.yml mit „Access denied“ oder „CAPTCHA“-Fehlern angezeigter Dienst hat Ihre Serveradresse blockiert. Das kommt bei Adressen aus Rechenzentrumsbereichen häufig vor, weil Suchmaschinen davon ausgehen, dass diese zu Scraping-Diensten gehören. SearXNG setzt den fehlschlagenden Dienst dann für einen bestimmten Zeitraum aus, statt ihn erneut abzufragen. Dadurch fällt ein blockierter Dienst unbemerkt aus Ihren Ergebnissen heraus. Deaktivieren Sie ihn in settings.yml oder akzeptieren Sie den Verlust. Das sind nicht die einzigen Möglichkeiten, denn für manche CAPTCHA-Sperren gibt es eine Lösung, die einen Neustart übersteht. Die übrigen Dienste antworten weiterhin. Ein 429-Fehler ist der mehrdeutige Fall. Er kann von Ihrem eigenen Rate-Limiter stammen oder von einem übergeordneten Dienst, der Ihren Server ablehnt. Die Logzeile zeigt, welcher dieser beiden Fälle vorliegt, bevor Sie Einstellungen ändern.

Wenn alle Engines gleichzeitig fehlschlagen, verfügt der Container entweder über keine funktionierende Namensauflösung für ausgehende Verbindungen oder über keine Route ins Internet. Testen Sie das innerhalb des Containers.

docker compose exec core wget -qO- https://duckduckgo.com > /dev/null && echo ok

Das System informiert Sie nicht automatisch, wenn diese Prüfung fehlschlägt. Führen Sie sie daher per cron aus und lassen Sie bei einem Fehler eine Meldung von Ihrem eigenen ntfy-Server an Ihr Telefon senden, statt erst auf die fehlenden Ergebnisse aufmerksam zu werden.

FAQ

Macht SearXNG meine Suchanfragen anonym?

SearXNG verbirgt Ihre Identität vor den abgefragten Suchmaschinen, weil diese Ihren Server als Absender der Anfrage sehen und nicht Ihren Browser. Vor Ihrem Server wird die Suchanfrage dadurch nicht verborgen. Auch Ihr Server bleibt für die Suchmaschinen sichtbar. Bei einer Instanz für einen einzelnen Benutzer stammt der gesamte Datenverkehr von dieser Adresse von Ihnen. Dadurch wird die Adresse selbst zum Identifikator. Die Verbindung zwischen Ihrem Browser und Ihrer Instanz ist durch das TLS-Zertifikat geschützt. Wie sich das gegenüber Ihrem ISP, dem Betreiber einer öffentlichen Instanz und den Suchmaschinen auswirkt, wird in was SearXNG tatsächlich verbirgt erläutert.

Warum gibt eine JSON-Anfrage den Fehler 403 Forbidden zurück?

Dafür gibt es zwei Ursachen. Beide hängen mit der Konfiguration zusammen. Entweder fehlt json in der Liste formats unter search: in settings.yml. Das ist der Standardzustand. Oder der Limiter ist aktiviert und hat Ihr Skript als Bot eingestuft. Fügen Sie zuerst das Format hinzu und starten Sie mit docker compose restart core neu. Versuchen Sie es anschließend erneut. Falls die Anfrage weiterhin fehlschlägt, setzen Sie limiter: false und steuern Sie den Zugriff stattdessen am Reverse Proxy.

Benötige ich den Valkey-Container, wenn der Limiter deaktiviert bleibt?

Lassen Sie ihn laufen. SearXNG funktioniert ohne den Container. Der Limiter kann dann jedoch später nicht aktiviert werden. Außerdem speichert der Container weiteren kurzlebigen Zustand. Der Container ist klein und speichert nur zwischengespeicherte Daten. Durch seine Entfernung sparen Sie daher nur sehr wenig und verlieren diese Option.

Wie aktualisiere ich SearXNG?

Führen Sie zuerst docker compose pull und anschließend docker compose up -d in /opt/searxng aus. Compose erstellt jeden Container neu, dessen Image geändert wurde. Das Verzeichnis core-config/ bleibt unverändert. Daher bleibt settings.yml erhalten. Da use_default_settings: true Ihre Schlüssel mit den ausgelieferten Standardwerten zusammenführt, werden von Upstream hinzugefügte Optionen mit sinnvollen Werten übernommen, ohne die Datei unbrauchbar zu machen.

Können mehrere Personen eine Instanz gemeinsam verwenden?

Ja. In diesem Fall aktivieren Sie den Limiter und setzen public_instance: true. Einstellungen werden im Browser jedes Besuchers gespeichert. Daher müssen Sie keine Benutzerkonten verwalten. Überwachen Sie /stats eine Woche lang, nachdem Sie die Instanz freigegeben haben. Die Suchmaschinen beginnen, Ihren Server abzulehnen, lange bevor Sie fehlende Ergebnisse bemerken.