SSD Nodes Learn Hosting plans →
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-09-05

Paano mag-self-host ng pribadong SearXNG

Patakbuhin ang SearXNG sa sarili mong VPS gamit ang Docker Compose, settings.yml, limiter, nginx na may TLS, at JSON search API para sa scripts mo.

Ano ang ginagawa mo

Ang pag-self-host ng SearXNG ay nagbibigay sa iyo ng pribadong search engine na tumatakbo sa sarili mong server. Ang SearXNG ay isang metasearch engine: ipinapadala nito ang query mo sa iba pang engine gaya ng Google, Bing, DuckDuckGo, at Wikipedia, pagkatapos ay pinagsasama ang mga resulta sa iisang result page. Walang ginagawang profile at walang tracking cookie na sine-set dahil ang tanging machine na nagtatago ng query mo ay ang sarili mong machine. Kung may nakita kang mga lumang guide para sa tinatawag na Searx, iyon ang project kung saan ito nag-fork, at wala itong commit mula pa noong 2023, kaya suriin ang status ng dalawa bago sundin ang isa sa mga ito.

Maliit ang stack. Dalawang container, isang settings file, at isang reverse proxy. Madali itong makakasama sa isang maliit na VPS, pero hindi ito totoo para sa lahat ng self-hosted service: ang mga photo library na inihambing sa PhotoPrism laban sa Immich ay nagtatakda ng minimum RAM batay sa indexer, hindi sa web app. Ang tunay na desisyon ay kung pribado ang instance, na nangangahulugang ikaw at ang sarili mong script lamang ang makaka-access dito, o public, na nangangahulugang maaaring mag-query rito ang sinuman sa internet. Binabago ng pagpiling ito ang security settings, kaya magpasya bago ka mag-type ng anuman. Ang default na sagot ay pribado.

May isa pang dahilan para magpatakbo nito. Nagsasalita ang isang SearXNG instance ng JSON, kaya anumang script o AI agent na isusulat mo ay magkakaroon ng search API na pagmamay-ari mo, nang walang key, bayad sa bawat query, o email tungkol sa quota.

Mag-install ng SearXNG gamit ang Docker Compose

Naglalabas ang proyekto ng container image at Compose file. I-pull ang dalawang ito sa isang bagong Ubuntu 24.04 server na mayroon nang Docker Engine at Compose plugin. Kung bago sa iyo ang Docker, magsimula sa mga batayan ng Docker Compose sa isang VPS at bumalik dito.

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

Tinutukoy ng Compose file ang dalawang serbisyo. Ang core ay ang SearXNG mismo, at ang valkey ay isang in-memory data store na ginagamit para sa rate limiting at panandaliang state. Naka-mount ang ./core-config/ sa /etc/searxng/ sa loob ng container, kaya nasa iisang directory lang sa host ang lahat ng iko-configure mo.

Ngayon, i-edit ang .env. Naka-comment out ang bawat linya sa halimbawang kasama sa package. Kaya nagsisimula ang container sa port 8080 sa lahat ng address. I-uncomment at itakda ang tatlong ito.

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

Ang SEARXNG_HOST=127.0.0.1 ang pinakamahalaga. Itinatakda nito ang published port bilang 127.0.0.1:8080:8080 sa halip na [::]:8080:8080. Dahil dito, loopback address lang ang sinasagot ng container at hindi ito direktang maaabot ng internet. Kapag nilaktawan mo ito, exposed na agad ang container sa pagsisimula nito dahil inilalagay ang published Docker port bago ang iyong firewall rules. Basahin nang buo ang mahalagang pitfall na ito: nilalampasan ng published Docker ports ang ufw.

Ayos ang SEARXNG_VERSION=latest habang nag-aaral ka. Sa server na mahalaga sa iyo, i-pin ang tag. Noong July 2026, batay sa petsa ang release tags at ganito ang anyo: 2026.3.25-541c6c3cb. Dahil dito, nag-a-upgrade ang pinned deployment kapag ikaw ang nagpasya, hindi kapag nagbago ang registry nang hindi mo inaasahan. Kapaki-pakinabang din ang parehong disiplina sa iba pang matagal na tatakbo sa server. Kaya pini-pin din ng self-hosted RustDesk relay ang image tags nito: ang unattended upgrade ng remote access service ay maaaring lumitaw sa pinakamasamang oras.

settings.yml: mahahalagang bahagi

Gawin ang core-config/settings.yml bago ang unang pagsisimula. Sinasabi ng use_default_settings: true sa SearXNG na i-load ang sarili nitong shipped defaults at ilapat lamang ang mga key na isinulat mo. Dahil dito, maikli ang file at nananatiling compatible sa mga upgrade na nagdaragdag ng mga bagong option.

I-generate muna ang secret dahil direktang ilalagay ang value sa file.

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

Nilalagdaan ng secret_key ang session at token data. Ang shipped default ay literal na string na ultrasecretkey. Kapag iniwan ito, maaaring gumawa ng mga token ang sinumang nakaaalam ng default na iyon. Palitan ito nang isang beses at huwag nang baguhin: kapag binago mo ito kalaunan, mabubura ang lahat ng naka-save na preference.

Dapat ang base_url ang public HTTPS address, kasama ang trailing slash. Ito ang address na inilalagay ng SearXNG sa mga link na nirender nito. Kapag localhost ang itinuro rito, ang link na "next page" sa remote browser ay tuturo sa sariling machine ng reader at mabibigo.

Tinutukoy ng formats kung aling output type ang gagawin ng web endpoint. Wala ang json sa default list, kaya magbabalik ng 403 ang isang JSON request hanggang sa idagdag mo ito. Ipinapadaan ng image_proxy: true ang result thumbnail sa iyong server, kaya hindi makikita ng mga site na nagho-host ng mga larawang iyon ang mga address ng iyong mga visitor.

Ginagamit ng valkey.url ang hostname na valkey dahil iyon ang service name sa Compose file. Inilalagay ng Compose ang dalawang container sa iisang network kung saan nareresolba ang mga service name. Kapag itinuro mo ito sa localhost, mabibigo ang limiter dahil sa loob ng core container, ang localhost ay ang container mismo.

Nasa plain file ang secret, kaya protektahan ang directory na nakapaligid dito, hindi ang file mismo. Pinipigilan ng chmod 750 /opt/searxng na makapasok ang ibang user sa host. Huwag higpitan ang core-config/settings.yml sa mode na 600: tumatakbo ang container bilang sarili nitong unprivileged user, at kapag hindi nito mabasa ang file, hindi talaga magsisimula ang SearXNG.

Simulan ang stack at suriin ito.

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

Dapat ipakita ng docker compose ps ang dalawang container na nasa state na running. Dapat sumagot ang curl sa HTTP/1.1 200 OK. Kapag walang sagot, basahin ang docker compose logs core dahil lalabas doon bilang parse error na tumutukoy sa line ang YAML mistake sa settings.yml.

Ilagay ito sa likod ng nginx na may TLS

Loopback lamang ang pinakikinggan ng container, kaya nginx ang nagbibigay ng access dito. Ito rin ang nagdaragdag ng transport layer security (TLS). Isulat ang /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

Ipinapakita ng nginx -t ang syntax is ok at test is successful bago ka mag-reload. Muling isinusulat ng Certbot ang parehong file upang makinig sa 443 gamit ang certificate, at nagdaragdag ito ng redirect mula sa port 80. Dapat nakaturo na sa server na ito ang DNS record para sa search.example.com, dahil pinatutunayan ng certificate authority ang ownership sa pamamagitan ng pagkuha ng file gamit ang HTTP. Makikita ang kumpletong walkthrough, kabilang ang renewal, sa gabay sa Certbot at nginx para sa Ubuntu 24.04.

Hindi palamuti lamang ang dalawang forwarding header. Kung wala ang X-Forwarded-For at X-Real-IP, dala ng bawat request na dumarating sa SearXNG ang address ng proxy. Dahil dito, nakikita ng rate limiter na iisang client ang gumagawa ng lahat ng traffic at hindi nito matukoy ang pagkakaiba ng mga bisita.

Bakit kailangan ng mga script at agent ang JSON search API

Sa pamamagitan ng json sa formats, ang parehong endpoint na nagre-render ng page ay nagbabalik din ng structured data.

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

Makakakuha ka ng object na may results array. Ang bawat entry ay naglalaman ng url, title, content, at ng engine na nagbigay nito, kasama ng answers, infoboxes, at suggestions. Sapat na ito para pakainin ang isang summariser, link checker, o research loop. Mas malaking hakbang ang pagbibigay ng mga resultang ito sa isang language model kaysa sa inaakala, dahil ang search results ay untrusted text na maaaring maglaman ng sarili nitong mga instruction. Detalyadong tinatalakay ito sa pagkonekta ng AI agent sa iyong SearXNG instance.

Mahalaga ito sa anumang agent-shaped na workflow. May training cutoff ang isang language model, kaya kailangan nito ng live search para makasagot sa mga tanong tungkol sa kasalukuyang panahon. Samantala, naniningil ang commercial search API sa bawat query at mahigpit ang rate limit. Ang isang local instance ay katumbas lamang ng isang container sa server na binabayaran mo na, at hindi lumalabas dito ang mga query. Kung nagkakabit ka ng mga tool sa isang model, ito rin ang dahilan kung bakit karaniwang unang idinadagdag ang pagpapatakbo ng MCP servers sa isang VPS, kung saan madalas unang tool ang search tool.

May 2 panuntunan sa paggamit ng API. Panatilihing private ang instance. I-bind ang API side sa loopback address o sa private network, at payagan lamang ang sarili mong mga host na makaabot dito. Pagkatapos, dahan-dahan itong i-query. Ipinapasa ng SearXNG ang request mo sa mga aktuwal na search engine, kaya ang script na nagpapatakbo ng 100 query bawat segundo ay humihiling sa Google na i-block ang server mo.

Ang limiter at ang mga pagbabago para sa public instance

Ang limiter ang depensa ng SearXNG laban sa mga bot. Minomonitor nito ang request headers, mga address, at request rate, at dini-drop nito ang traffic na mukhang automated. Kailangan nito ng Valkey para i-store ang state na iyon, kaya kasama ito sa Compose file.

Sa isang private instance, panatilihing naka-enable ang limiter: false. Automated traffic sa mismong kahulugan nito ang mga sarili mong script, kaya iba-block ng limiter ang eksaktong JSON calls na ginawa mo para sa instance. Sa halip, trabaho ng reverse proxy ang access control: isang allow at deny pair sa nginx location, HTTP basic authentication, o firewall na tumatanggap lamang ng koneksyon mula sa iba mo pang server. Kung kailangan mong ma-access ang private instance mula sa laptop na lumilipat-lipat ng network, maglagay ng v3 onion address sa harap nito bilang ikaapat na opsyon, dahil kumokonekta ang tor sa parehong loopback port nang walang bagong inilalantad sa internet.

Kung ipo-publish mo ang instance para sa ibang tao, i-on ang dalawang switch.

server:
  limiter: true
  public_instance: true

Makikita ang mas pinong control sa core-config/limiter.toml, na binabasa ng container mula sa /etc/searxng/limiter.toml. Isulat lamang ang mga key na gusto mong baguhin. Kapag nasa likod ito ng proxy, kailangan mong ideklara ang proxy; kung hindi, ituturing ng limiter na ang address ng nginx ang iisang abusive client.

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

[botdetection.ip_limit]
link_token = true

Dahil sa link_token = true, mag-iisyu ang SearXNG ng token na kukunin lamang ng isang totoong browser session, kaya napipigilan nito ang karamihan sa mga simpleng scraper. Asahan mong maaakit ang mga ito sa loob ng ilang araw kapag public instance ito. Asahan din ang mga engine error, dahil habang mas maraming traffic ang ipinapasa mo, mas maagang magsisimulang magbalik ng CAPTCHA ang upstream engine sa address ng server mo. Tuloy-tuloy na trabaho ang pagpapatakbo ng public SearXNG instance. Hindi ganoon ang private instance, kaya kabilang ito sa karamihan ng maiikling listahan ng mga sulit i-self-host sa 2026. Hindi rin infrastructure ang bawat entry sa mga listahang iyon: ang pagrebuild ng Jellyfin library bilang isang 90s rental store na maaaring lakarin ay ang parehong isang container sa likod ng parehong nginx block, na nakaturo sa isang gabi sa halip na sa isang workflow.

Buksan ang /stats sa iyong instance. Inililista nito ang bawat engine kasama ang error rate at response time nito. Ito ang unang dapat tingnan kapag kakaunti ang lumalabas na resulta.

Ang engine na nagpapakita ng mga error na “Access denied” o “CAPTCHA” ay nag-block sa address ng iyong server. Karaniwan ito sa mga address na kabilang sa data centre range, dahil ipinapalagay ng mga search engine na ginagamit ang mga ito ng mga scraper. Isinususpinde ng SearXNG ang engine na nagfa-fail sa loob ng isang panahon sa halip na ulitin ang request, kaya tahimik na nawawala sa mga resulta mo ang isang naka-block na engine. I-disable ito sa settings.yml o tanggapin ang pagkawala nito. Hindi lamang ang dalawang hakbang na ito ang maaari mong gawin, dahil may ilang CAPTCHA block na may fix na nananatili kahit mag-restart. Patuloy pa ring sumasagot ang mga natitirang engine. Ang 429 ang hindi malinaw na kaso, dahil maaaring nagmula ito sa sarili mong limiter o sa upstream engine na tumatanggi sa server mo, at ipinapakita ng log line kung alin sa dalawang ito ang nangyayari bago ka magsimulang magbago ng settings.

Kung sabay-sabay na nagfa-fail ang lahat ng engine, walang gumaganang outbound name resolution ang container o wala itong route papunta sa internet. I-test ito mula sa loob ng container.

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

Walang magsasabi sa system kung kailan nagsimulang mag-fail ang check na ito. Kaya patakbuhin ito mula sa cron at hayaang magpadala ng alert sa iyong phone mula sa sarili mong ntfy server kapag may failure, sa halip na hintaying mapansin mong kakaunti na ang mga resulta.

FAQ

Ginagawa ba ng SearXNG na anonymous ang mga paghahanap ko?

Itinatago nito ang iyong pagkakakilanlan mula sa mga engine na tinatanungan nito, dahil server mo ang nakikita nilang gumagawa ng request sa halip na browser mo. Hindi nito itinatago ang query mula sa server mo, at hindi rin nito itinatago ang server mo mula sa mga engine. Sa isang single-user instance, sa iyo nagmumula ang lahat ng traffic mula sa address na iyon, kaya ang address mismo ang nagiging identifier. Pinoprotektahan ng TLS certificate ang traffic sa pagitan ng browser mo at ng instance mo. Ipinaliliwanag sa kung ano talaga ang itinatago ng SearXNG kung ano ang nalalaman ng ISP mo, ng operator ng isang public instance, at ng mga engine mismo.

Bakit nagbabalik ng 403 Forbidden ang isang JSON request?

May dalawang posibleng sanhi, at parehong configuration issue. Maaaring wala ang json sa listahan ng formats sa ilalim ng search: sa settings.yml, na siyang default na estado, o naka-enable ang limiter at natukoy nitong bot ang script mo. Idagdag muna ang format, mag-restart gamit ang docker compose restart core, at subukan ulit. Kung nabibigo pa rin, itakda ang limiter: false at sa reverse proxy na kontrolin ang access.

Kailangan ko ba ang Valkey container kung naka-off ang limiter?

Panatilihin itong tumatakbo. Gumagana ang SearXNG nang wala ito, ngunit hindi mo ma-e-enable ang limiter sa hinaharap kung wala ito, at nag-iimbak din ito ng iba pang panandaliang state. Maliit ang container at cached data lamang ang iniimbak nito, kaya kaunti lang ang matitipid sa pag-alis nito at mawawala naman ang opsyon mong gamitin ito sa hinaharap.

Paano ko ia-update ang SearXNG?

Patakbuhin ang docker compose pull at pagkatapos ay ang docker compose up -d sa /opt/searxng. Muling nililikha ng Compose ang anumang container na nagbago ang image at hindi nito ginagalaw ang iyong core-config/ directory, kaya nananatili ang settings.yml. Dahil pinagsasama ng use_default_settings: true ang iyong mga key sa mga default na kasama sa release, dumarating ang mga option na idinagdag upstream na may angkop na mga value sa halip na masira ang file.

Maaari bang magbahagi ng isang instance ang ilang tao?

Oo, at ito ang sitwasyong dapat mong i-enable ang limiter at itakda ang public_instance: true. Naka-store ang preferences sa sariling browser ng bawat bisita, kaya walang accounts na kailangang i-manage. I-monitor ang /stats sa loob ng isang linggo matapos itong buksan sa publiko, dahil nagsisimulang tanggihan ng upstream engine ang server mo bago mo pa mapansin na may nawawalang resulta.