SSD Nodes Learn Hosting plans →
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-10-20

SearXNG zelf hosten met Docker Compose

Bouw uw eigen privé-zoekmachine met SearXNG op een VPS. Deze handleiding behandelt de settings.yml configuratie, de limiter, nginx met TLS en het gebruik van de JSON API.

Wat u bouwt

Het zelf hosten van SearXNG geeft u een privé-zoekmachine die op uw eigen server draait. SearXNG is een metazoekmachine: deze neemt uw zoekopdracht, vraagt andere zoekmachines zoals Google, Bing, DuckDuckGo en Wikipedia, en voegt de resultaten vervolgens samen op één pagina. Er wordt geen profiel opgebouwd en er worden geen tracking cookies geplaatst, omdat de enige machine die uw zoekopdracht bewaart, de uwe is. Als u oudere handleidingen heeft gevonden voor iets dat simpelweg Searx heet, dan is dat het project waarvan dit is afgesplitst. Searx wordt sinds september 2023 niet meer onderhouden, toen de eigen repository aankondigde dat Searx niet langer wordt ondersteund, en de enige commit sindsdien, een documentatienotitie in mei 2026, heeft daar geen verandering in gebracht. Dus controleer de status van beide voordat u er een volgt.

De stack is klein. Twee containers, één instellingenbestand, één reverse proxy. Het deelt met gemak een kleine VPS, wat niet voor elke zelfgehoste service geldt: de fotobibliotheken die in PhotoPrism versus Immich worden vergeleken, bepalen hun minimale RAM-gebruik op basis van de indexeerder in plaats van de webapplicatie. De echte beslissing is of de instantie privé is, wat betekent dat alleen u en uw eigen scripts deze kunnen bereiken, of publiek, wat betekent dat iedereen op het internet er zoekopdrachten naar kan sturen. Die keuze verandert de beveiligingsinstellingen, dus maak deze keuze voordat u iets typt. Het standaardantwoord is privé.

Er is een tweede reden om er een te draaien. Een SearXNG-instantie spreekt JSON, dus elk script of elke AI-agent die u schrijft, krijgt een zoek-API die van u is, zonder sleutel, zonder facturering per zoekopdracht en zonder quota-e-mails.

SearXNG installeren met Docker Compose

Het project publiceert een container-image en een Compose-bestand. Haal beide op naar een verse Ubuntu 24.04-server waarop Docker Engine en de Compose-plugin al zijn geïnstalleerd. Als Docker nieuw voor u is, begin dan bij Docker Compose basisbeginselen op een VPS en keer daarna terug.

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

Het Compose-bestand definieert twee services. core is SearXNG zelf, en valkey is een in-memory datastore die wordt gebruikt voor rate limiting en tijdelijke statusinformatie. Het koppelt ./core-config/ aan /etc/searxng/ binnen de container, waardoor alles wat u configureert in die ene map op de host blijft staan.

Bewerk nu .env. Elke regel in het meegeleverde voorbeeld is uitgeschakeld met commentaar, wat de reden is dat de container op elk adres op poort 8080 start. Verwijder het commentaar en stel deze drie in.

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1 is de belangrijkste. Deze maakt de gepubliceerde poort 127.0.0.1:8080:8080 in plaats van een kale 8080:8080, die Docker op elk adres publiceert, zodat de container alleen antwoordt op het loopback-adres en het internet deze niet rechtstreeks kan bereiken. Sla dit over en de container is direct bij het opstarten blootgesteld, omdat een gepubliceerde Docker-poort vóór uw firewallregels wordt ingevoegd. Die valkuil is het volledig lezen waard: gepubliceerde Docker-poorten omzeilen ufw.

SEARXNG_VERSION=latest is prima terwijl u aan het leren bent. Op een server die u belangrijk vindt, zet u de tag vast. Sinds oktober 2026 zijn de release-tags gebaseerd op de datum en zien ze eruit als 2026.10.4-d48c4b555, zodat een vastgezette implementatie pas upgradet wanneer u dat beslist, en niet wanneer het register onder u verandert. Dezelfde discipline loont voor alles wat langdurig op de machine draait, en dat is waarom een zelf-gehoste RustDesk relay zijn image-tags ook vastzet: een onbeheerde upgrade van een service voor toegang op afstand kondigt zichzelf aan op het slechtst mogelijke moment.

settings.yml: de relevante onderdelen

Maak core-config/settings.yml aan vóór de eerste start. use_default_settings: true instrueert SearXNG om de meegeleverde standaardinstellingen te laden en vervolgens alleen uw opgegeven waarden toe te passen. Hierdoor blijft het bestand kort en blijft de configuratie behouden bij upgrades die nieuwe opties introduceren.

Genereer eerst het geheim, aangezien de waarde direct in het bestand moet worden geplaatst.

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 ondertekent sessie- en tokendata. De standaardwaarde is de letterlijke tekenreeks ultrasecretkey. Als u deze laat staan, kan iedereen die deze standaardwaarde kent, tokens vervalsen. Vervang deze één keer en wijzig deze daarna niet meer: het wijzigen ervan maakt alle opgeslagen voorkeuren ongeldig.

base_url moet het publieke HTTPS-adres zijn, inclusief de afsluitende slash. Dit is het adres dat SearXNG gebruikt in de links die het genereert. Als u dit op localhost laat staan, verwijst de "volgende pagina"-link in een externe browser naar de machine van de bezoeker zelf, wat resulteert in een foutmelding.

formats bepaalt welke outputtypen het web-endpoint produceert. json staat niet in de standaardlijst, waardoor een JSON-verzoek een 403-foutmelding geeft totdat u dit toevoegt. image_proxy: true leidt resultaat-thumbnails via uw server, zodat de websites die deze afbeeldingen hosten nooit de IP-adressen van uw bezoekers zien.

De valkey.url gebruikt de hostnaam valkey omdat dit de servicenaam is in het Compose-bestand. Compose plaatst beide containers op hetzelfde netwerk waar servicenamen worden omgezet. Als u dit naar localhost wijst, faalt de limiter, omdat localhost binnen de core-container naar de container zelf verwijst.

Het geheim staat in een tekstbestand, dus beveilig ook de omliggende map. chmod 750 /opt/searxng houdt andere gebruikers op de host buiten. U kunt ook core-config/settings.yml beperken tot modus 600 zonder problemen: het entrypoint van de officiële container start als root en, met FORCE_OWNERSHIP op de standaardwaarde true, draagt de gemounte configuratiemap over aan de searxng-gebruiker van de container voordat SearXNG start. Het bestand blijft voor deze gebruiker leesbaar. Het neveneffect is zichtbaar op de host: deze stap wijzigt de eigenaar van core-config/ naar de user ID van de container, dus houd er rekening mee dat u het bestand daarna met sudo moet bewerken.

Start de stack en controleer deze.

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

docker compose ps hoort beide containers in de status running te tonen. De curl hoort HTTP/1.1 200 OK te antwoorden. Als er geen antwoord komt, lees dan docker compose logs core, aangezien een YAML-fout in settings.yml daar wordt weergegeven als een parse-fout met vermelding van het regelnummer.

Plaats het achter nginx met TLS

De container luistert alleen op loopback, dus nginx maakt de service bereikbaar en voegt transportlaagbeveiliging (TLS) toe. Schrijf /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 toont syntax is ok en test is successful voordat u de configuratie herlaadt. Certbot herschrijft hetzelfde bestand om op poort 443 te luisteren met een certificaat en voegt een redirect toe vanaf poort 80. Het DNS-record voor search.example.com moet al naar deze server verwijzen, omdat de certificaatautoriteit het eigendom verifieert door een bestand via HTTP op te halen. De volledige handleiding, inclusief vernieuwing, staat in de Certbot en nginx handleiding voor Ubuntu 24.04.

De twee forwarding-headers zijn geen overbodige luxe. Zonder X-Forwarded-For en X-Real-IP draagt elk verzoek dat bij SearXNG aankomt het adres van de proxy. Hierdoor ziet de rate limiter slechts één client die al het verkeer genereert en kan deze bezoekers niet van elkaar onderscheiden.

Waarom scripts en agents een JSON-zoek-API vereisen

Met json in formats retourneert hetzelfde eindpunt dat de pagina rendert ook gestructureerde data.

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

U ontvangt een object met een results-array, waarbij elk item url, title, content en de engine die het resultaat leverde bevat, naast answers, infoboxes en suggestions. Dat is voldoende om een samenvattingsfunctie, een link-checker of een onderzoekslus te voeden. Het doorgeven van deze resultaten aan een taalmodel is een grotere stap dan het lijkt, aangezien zoekresultaten niet-vertrouwde tekst zijn die eigen instructies kunnen bevatten; dit is wat het koppelen van een AI-agent aan uw SearXNG-instantie in detail behandelt.

Dit is van belang voor alles wat de vorm van een agent heeft. Een taalmodel heeft een trainingscutoff, dus heeft het live zoekopdrachten nodig om vragen over het heden te beantwoorden, en commerciële zoek-API's rekenen per query en hanteren strikte rate limits. Een lokale instantie kost één container op een server waar u al voor betaalt, en de zoekopdrachten verlaten de server nooit. Als u tools koppelt aan een model, volgt dezelfde redenering voor het draaien van MCP-servers op een VPS, waarbij een zoektool meestal de eerste is die wordt toegevoegd.

Twee regels voor API-gebruik. Houd de instantie privé; bind de API-kant aan het loopback-adres of aan een privénetwerk en sta alleen toe dat uw eigen hosts deze bereiken. Dit is dezelfde behandeling die een zelfgehoste locatietracker nodig heeft voor het eindpunt waarnaar uw telefoon zijn positie rapporteert. Voer de zoekopdrachten vervolgens voorzichtig uit. SearXNG stuurt uw verzoek door naar echte zoekmachines, dus een script dat honderd zoekopdrachten per seconde uitvoert, vraagt erom dat Google uw server blokkeert.

De limiter, en wat er verandert voor een publieke instantie

De limiter is de bot-beveiliging van SearXNG. Deze bewaakt request-headers, IP-adressen en de frequentie van verzoeken, en blokkeert verkeer dat er geautomatiseerd uitziet. Hiervoor is Valkey nodig om de status bij te houden, wat de reden is dat het Compose-bestand dit meelevert.

Houd voor een privé-instantie limiter: false aan. Uw eigen scripts zijn per definitie geautomatiseerd verkeer, waardoor de limiter precies de JSON-aanroepen zou blokkeren waarvoor u de instantie heeft opgezet. Toegangsbeheer is in plaats daarvan de taak van de reverse proxy: een allow en deny paar in de nginx location, HTTP basic authentication, of een firewall die alleen uw andere servers toelaat. Als u een privé-instantie wilt bereiken vanaf een laptop die tussen netwerken wisselt, is het plaatsen van een v3 onion-adres ervoor een vierde optie, omdat tor verbinding maakt met dezelfde loopback-poort zonder iets nieuws bloot te stellen aan het internet.

Als u de instantie openbaar maakt voor anderen, schakel dan beide opties in.

server:
  limiter: true
  public_instance: true

Fijner beheer vindt plaats in core-config/limiter.toml, dat de container inleest op /etc/searxng/limiter.toml. U schrijft alleen de keys die u wilt wijzigen. Achter een proxy moet u de proxy declareren, anders behandelt de limiter uw nginx-adres als de enige misbruikende client.

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

[botdetection.ip_limit]
link_token = true

link_token = true zorgt ervoor dat SearXNG een token uitgeeft dat alleen door een echte browsersessie wordt opgehaald, wat de meeste eenvoudige scrapers tegenhoudt. Ga ervan uit dat een publieke instantie binnen enkele dagen scrapers aantrekt. Verwacht ook engine-fouten, want hoe meer verkeer u doorstuurt, hoe sneller upstream-engines CAPTCHA's gaan retourneren naar uw serveradres. Een publieke SearXNG-instantie is een doorlopende taak. Een privé-instantie is dat niet, en daarom staat het op de meeste korte lijsten van dingen die de moeite waard zijn om in 2026 zelf te hosten. Niet elk item op die lijsten is infrastructuur: het herbouwen van een Jellyfin-bibliotheek als een beloopbare videotheek uit de jaren 90 is dezelfde container achter hetzelfde nginx-blok, gericht op een avondje ontspanning in plaats van een workflow.

Waarom zoekopdrachten geen resultaten opleveren

Open /stats op uw instantie. Hierin staan alle engines met hun foutpercentage en responstijd vermeld; dit is de eerste plek om te kijken wanneer resultaten achterblijven.

Een engine die de melding "Access denied" of "CAPTCHA" toont, heeft uw serveradres geblokkeerd. Dit komt vaak voor bij adressen in datacentrum-ranges, omdat zoekmachines aannemen dat deze toebehoren aan scrapers. SearXNG schorst de falende engine vervolgens voor een bepaalde periode in plaats van het opnieuw te proberen, waardoor een geblokkeerde engine stilletjes uit uw resultaten verdwijnt. Schakel deze uit in settings.yml of accepteer het verlies. Dit zijn niet de enige twee opties, want sommige CAPTCHA-blokkades hebben een oplossing die een herstart overleeft. De overige engines antwoorden nog wel. Een 429 is een ambigu geval, omdat dit afkomstig kan zijn van uw eigen limiter of van een upstream-engine die uw server weigert, en de logregel vertelt u met welke van de twee u te maken heeft voordat u instellingen gaat wijzigen.

Als elke engine tegelijkertijd faalt, heeft de container geen werkende uitgaande naamresolutie of geen route naar het internet. Test dit vanuit de container.

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

Niets op de server geeft aan wanneer deze controle begint te falen, dus voer deze uit via cron en laat een foutmelding een melding naar uw telefoon sturen vanaf uw eigen ntfy-server in plaats van te wachten tot u merkt dat de resultaten schaars zijn geworden.

FAQ

Maakt SearXNG mijn zoekopdrachten anoniem?

Het verbergt uw identiteit voor de zoekmachines die het bevraagt, omdat zij uw server het verzoek zien doen in plaats van uw browser. Het verbergt de zoekopdracht niet voor uw server, en het verbergt uw server niet voor hen. Op een instance voor één gebruiker is al het verkeer vanaf dat adres van u, waardoor het adres zelf de identificatie wordt. Verkeer tussen uw browser en uw instance is beveiligd door het TLS-certificaat. Wat dit betekent voor uw positie ten opzichte van uw ISP, de beheerder van een publieke instance en de zoekmachines zelf, wordt uiteengezet in wat SearXNG daadwerkelijk verbergt.

Waarom geeft een JSON-verzoek een 403 Forbidden foutmelding?

Er zijn twee oorzaken, en beide hebben te maken met de configuratie. Ofwel json ontbreekt in de formats-lijst onder search: in settings.yml, wat de standaardinstelling is, of de limiter staat aan en heeft uw script geclassificeerd als een bot. Voeg het formaat toe, herstart met docker compose restart core en probeer het opnieuw. Als het nog steeds niet werkt, stel dan limiter: false in en beheer de toegang via de reverse proxy.

Heb ik de Valkey-container nodig als ik de limiter uitgeschakeld laat?

Laat deze draaien. SearXNG werkt zonder, maar de limiter kan later niet worden ingeschakeld zonder deze container, en hij bevat ook andere tijdelijke statusinformatie. De container is klein en slaat alleen gecachte gegevens op, dus verwijderen levert nauwelijks winst op en kost u de optie om de limiter later te gebruiken.

Hoe update ik SearXNG?

Voer docker compose pull uit en daarna docker compose up -d in /opt/searxng. Compose maakt elke container opnieuw aan waarvan de image is gewijzigd en laat uw core-config/-directory ongemoeid, waardoor settings.yml behouden blijft. Omdat use_default_settings: true uw sleutels samenvoegt met de meegeleverde standaardinstellingen, komen opties die upstream worden toegevoegd aan met verstandige waarden in plaats van het bestand te verbreken.

Kunnen meerdere mensen één instance delen?

Ja, en dat is het scenario waarin u de limiter inschakelt en public_instance: true instelt. Voorkeuren worden opgeslagen in de browser van elke bezoeker zelf, dus er zijn geen accounts om te beheren. Monitor /stats gedurende een week nadat u de instance openstelt, omdat upstream-zoekmachines uw server al lang beginnen te blokkeren voordat u merkt dat er resultaten ontbreken.

Was dit artikel nuttig?