Cara Self-host SearXNG dengan Docker Compose
Bina enjin carian peribadi menggunakan SearXNG pada VPS anda. Panduan ini merangkumi konfigurasi settings.yml, tetapan limiter, nginx dengan TLS serta API JSON untuk skrip.
Apa yang anda sedang bina
Self-hosting SearXNG memberikan anda enjin carian peribadi yang berjalan pada pelayan anda sendiri. SearXNG ialah enjin meta-carian: ia mengambil pertanyaan anda, meminta enjin lain seperti Google, Bing, DuckDuckGo dan Wikipedia, kemudian menggabungkan hasil yang diperoleh ke dalam satu halaman keputusan. Tiada profil dibina dan tiada kuki penjejakan ditetapkan, kerana satu-satunya mesin yang menyimpan pertanyaan anda ialah mesin anda sendiri. Jika anda menemui panduan lama untuk sesuatu yang dipanggil Searx sahaja, itu adalah projek asal yang menjadi punca SearXNG diwujudkan. Projek tersebut tidak lagi diselenggara sejak September 2023, apabila repositori asalnya mengumumkan bahawa Searx tidak lagi diselenggara, dan satu commit yang dibuat selepas itu, iaitu nota dokumentasi pada Mei 2026, tidak mengubah keadaan tersebut. Oleh itu, semak status kedua-duanya sebelum anda mengikuti mana-mana panduan.
Stak ini kecil. Dua kontena, satu fail tetapan, satu reverse proxy. Ia boleh berkongsi VPS kecil dengan mudah, yang tidak terpakai bagi setiap servis self-hosted: pustaka foto yang dibandingkan dalam PhotoPrism lawan Immich menetapkan had minimum RAM oleh pengindeks dan bukannya aplikasi web. Keputusan sebenar ialah sama ada instans tersebut bersifat peribadi, bermakna hanya anda dan skrip anda sendiri yang mengaksesnya, atau awam, bermakna sesiapa sahaja di internet boleh membuat pertanyaan. Pilihan itu mengubah tetapan keselamatan, jadi buat keputusan sebelum anda menaip apa-apa. Jawapan lalai ialah peribadi.
Terdapat sebab kedua untuk menjalankannya. Instans SearXNG menggunakan JSON, jadi mana-mana skrip atau ejen AI yang anda tulis akan mendapat API carian milik anda sendiri, tanpa kunci, tanpa bil bagi setiap pertanyaan dan tanpa e-mel kuota.
Memasang SearXNG dengan Docker Compose
Projek ini menerbitkan imej kontena dan fail Compose. Muat turun kedua-duanya ke pelayan Ubuntu 24.04 baharu yang sudah mempunyai Docker Engine dan pemalam Compose. Jika anda baharu menggunakan Docker, mulakan dengan asas Docker Compose pada VPS dan kembali semula ke sini.
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 .envFail Compose mentakrifkan dua servis. core ialah SearXNG itu sendiri, dan valkey ialah stor data dalam memori yang digunakan untuk pengehadan kadar (rate limiting) dan status jangka pendek. Ia melekapkan ./core-config/ pada /etc/searxng/ di dalam kontena, jadi semua yang anda konfigurasi berada dalam direktori tersebut pada hos.
Sekarang, sunting .env. Setiap baris dalam contoh yang dibekalkan telah dikomen, itulah sebabnya kontena bermula pada port 8080 pada setiap alamat. Nyahkomen dan tetapkan tiga perkara ini.
SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080SEARXNG_HOST=127.0.0.1 adalah yang paling penting. Ia menjadikan port yang diterbitkan sebagai 127.0.0.1:8080:8080 dan bukannya 8080:8080 biasa, yang diterbitkan oleh Docker pada setiap alamat, supaya kontena hanya menjawab pada alamat loopback dan internet tidak boleh mencapainya secara terus. Abaikan langkah ini dan kontena akan terdedah sebaik sahaja ia bermula, kerana port Docker yang diterbitkan akan dimasukkan sebelum peraturan firewall anda. Perangkap itu wajar dibaca sepenuhnya: port Docker yang diterbitkan memintas ufw.
SEARXNG_VERSION=latest adalah memadai semasa anda sedang belajar. Pada pelayan yang penting, tetapkan tag secara kekal (pin). Sehingga Oktober 2026, tag keluaran adalah berasaskan tarikh dan kelihatan seperti 2026.10.4-d48c4b555, jadi penggunaan yang ditetapkan akan dinaik taraf apabila anda membuat keputusan, bukan apabila pendaftaran berubah tanpa pengetahuan anda. Disiplin yang sama berbaloi untuk apa-apa sahaja yang berjalan lama pada mesin tersebut, itulah sebabnya relay RustDesk yang dihoskan sendiri turut menetapkan tag imejnya: naik taraf tanpa pengawasan bagi servis akses jauh akan berlaku pada saat yang paling tidak sesuai.
settings.yml: bahagian yang penting
Cipta core-config/settings.yml sebelum permulaan pertama. use_default_settings: true memberitahu SearXNG untuk memuatkan tetapan lalai yang dibekalkan dan kemudian menggunakan hanya kunci yang anda tulis, supaya fail anda kekal ringkas dan tidak terjejas oleh naik taraf yang menambah pilihan baharu.
Jana secret terlebih dahulu, kerana nilainya dimasukkan terus ke dalam fail.
openssl rand -hex 32use_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
- jsonsecret_key menandatangani data sesi dan token. Nilai lalai yang dibekalkan ialah rentetan literal ultrasecretkey, dan membiarkannya bermakna sesiapa yang mengetahui nilai lalai tersebut boleh memalsukan token berkenaan. Gantikannya sekali, kemudian jangan ubahnya lagi: menukarnya kemudian akan memadamkan semua keutamaan yang disimpan.
base_url mestilah alamat HTTPS awam, dengan garis miring (trailing slash) di hujung. Ia adalah apa yang ditulis oleh SearXNG ke dalam pautan yang dipaparkannya. Jika dibiarkan menghala ke localhost, pautan "halaman seterusnya" dalam pelayar jauh akan menghala ke mesin pembaca sendiri dan gagal.
formats menentukan jenis output yang akan dihasilkan oleh web endpoint. json tiada dalam senarai lalai, jadi permintaan JSON akan mengembalikan ralat 403 sehingga anda menambahkannya. image_proxy: true menghalakan imej kecil hasil carian melalui pelayan anda, supaya tapak yang mengehoskan imej tersebut tidak akan melihat alamat pelawat anda.
valkey.url menggunakan nama hos valkey kerana itu adalah nama servis dalam fail Compose, dan Compose meletakkan kedua-dua kontena pada satu rangkaian di mana nama servis boleh diselesaikan. Halakan ia ke localhost dan pengehad (limiter) akan gagal, kerana di dalam kontena core, localhost merujuk kepada kontena itu sendiri.
Secret disimpan dalam fail biasa, jadi lindungi direktori di sekelilingnya juga. chmod 750 /opt/searxng menghalang pengguna hos lain daripada mengaksesnya. Anda juga boleh mengetatkan core-config/settings.yml kepada mod 600 tanpa merosakkan apa-apa: entrypoint kontena rasmi bermula sebagai root dan, dengan FORCE_OWNERSHIP dibiarkan pada nilai lalai true, ia menyerahkan direktori konfigurasi yang dipasang (mounted) kepada pengguna searxng kontena tersebut sebelum SearXNG bermula, jadi fail itu kekal boleh dibaca olehnya. Kesan sampingannya kelihatan pada hos: langkah yang sama menukar pemilik core-config/ kepada ID pengguna kontena, jadi jangkakan untuk menyunting fail tersebut dengan sudo selepas itu.
Mulakan stack dan semaknya.
cd /opt/searxng
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080/docker compose ps sepatutnya menunjukkan kedua-dua kontena dalam status running. curl sepatutnya menjawab HTTP/1.1 200 OK. Jika ia tidak menjawab apa-apa, baca docker compose logs core, kerana kesilapan YAML dalam settings.yml akan dipaparkan di sana sebagai ralat penghuraian (parse error) yang menyatakan baris yang terlibat.
Letakkan ia di belakang nginx dengan TLS
Kontena tersebut hanya mendengar pada loopback, jadi nginx ialah komponen yang menjadikannya boleh dicapai, dan ia juga merupakan komponen yang menambah keselamatan lapisan pengangkutan (TLS). Tulis /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.comnginx -t mencetak syntax is ok dan test is successful sebelum anda memuat semula. Certbot menulis semula fail yang sama untuk mendengar pada port 443 dengan sijil dan menambah ubah hala (redirect) daripada port 80. Rekod DNS untuk search.example.com mestilah sudah menghala ke pelayan ini, kerana pihak berkuasa sijil (CA) membuktikan pemilikan dengan mengambil fail melalui HTTP. Panduan lengkap, termasuk pembaharuan sijil, terdapat dalam panduan Certbot dan nginx untuk Ubuntu 24.04.
Dua pengepala (header) pemajuan tersebut bukan sekadar hiasan. Tanpa X-Forwarded-For dan X-Real-IP, setiap permintaan yang sampai ke SearXNG membawa alamat proksi, jadi pengehad kadar (rate limiter) melihat satu klien yang menjana semua trafik dan tidak dapat membezakan antara pelawat.
Mengapa skrip dan ejen memerlukan API carian JSON
Dengan json dalam formats, endpoint yang sama yang memaparkan halaman akan mengembalikan data berstruktur.
curl -s 'http://127.0.0.1:8080/search?q=wireguard+mtu&format=json' \
| jq -r '.results[0:5][] | .url'Anda akan menerima objek dengan tatasusunan results, di mana setiap entri membawa url, title, content dan enjin yang membekalkannya, di samping answers, infoboxes dan suggestions. Itu sudah memadai untuk membekalkan data kepada peringkas, penyemak pautan atau gelung penyelidikan. Menyerahkan hasil tersebut kepada model bahasa merupakan langkah yang lebih besar daripada yang disangka, memandangkan hasil carian adalah teks yang tidak dipercayai dan boleh membawa arahan tersendiri, iaitu perkara yang dibincangkan secara terperinci dalam menghalakan ejen AI ke instans SearXNG anda.
Perkara ini penting bagi apa-apa sahaja yang berbentuk ejen. Model bahasa mempunyai had masa latihan, jadi ia memerlukan carian langsung untuk menjawab soalan tentang masa kini, manakala API carian komersial mengenakan bayaran bagi setiap pertanyaan dan mempunyai had kadar yang ketat. Instans tempatan hanya memerlukan satu kontena pada pelayan yang sudah pun anda bayar, dan pertanyaan tersebut tidak pernah keluar dari pelayan itu. Jika anda sedang menyambungkan alatan ke dalam model, alasan yang sama mendorong menjalankan pelayan MCP pada VPS, di mana alat carian biasanya merupakan alat pertama yang ditambah oleh pengguna.
Dua peraturan untuk penggunaan API. Pastikan instans bersifat peribadi, jadi ikat bahagian API ke alamat loopback atau ke rangkaian peribadi dan benarkan hanya hos anda sendiri untuk mencapainya, yang merupakan layanan sama yang diperlukan oleh penjejak lokasi yang dihoskan sendiri untuk endpoint yang digunakan oleh telefon anda bagi melaporkan kedudukannya. Kemudian, buat pertanyaan dengan berhemah. SearXNG memajukan permintaan anda kepada enjin carian sebenar, jadi skrip yang menjalankan seratus pertanyaan sesaat bermakna anda meminta Google untuk menyekat pelayan anda.
Limiter, dan perkara yang berubah untuk instans awam
Limiter ialah pertahanan bot SearXNG. Ia memantau pengepala permintaan, alamat, dan kadar permintaan, serta menggugurkan trafik yang kelihatan automatik. Ia memerlukan Valkey untuk menyimpan status tersebut, itulah sebabnya fail Compose menyertakannya.
Pada instans peribadi, kekalkan limiter: false. Skrip anda sendiri secara definisinya adalah trafik automatik, jadi limiter akan menyekat panggilan JSON yang anda bina instans tersebut untuknya. Kawalan akses sebaliknya adalah tugas reverse proxy: pasangan allow dan deny dalam location nginx, pengesahan asas HTTP, atau firewall yang hanya membenarkan pelayan anda yang lain. Jika anda perlu mencapai instans peribadi daripada komputer riba yang bertukar-tukar rangkaian, meletakkan alamat onion v3 di hadapannya ialah pilihan keempat, kerana tor bersambung ke port loopback yang sama tanpa mendedahkan apa-apa yang baharu kepada internet.
Jika anda menerbitkan instans tersebut untuk orang lain, hidupkan kedua-dua suis.
server:
limiter: true
public_instance: trueKawalan yang lebih terperinci terdapat dalam core-config/limiter.toml, yang dibaca oleh kontena pada /etc/searxng/limiter.toml. Anda hanya perlu menulis kunci yang ingin anda ubah. Di sebalik proksi, anda mesti mengisytiharkan proksi tersebut, atau limiter akan menganggap alamat nginx anda sebagai satu-satunya klien yang menyalahgunakan sistem.
[botdetection]
trusted_proxies = [
'127.0.0.0/8',
'::1',
]
[botdetection.ip_limit]
link_token = truelink_token = true menyebabkan SearXNG mengeluarkan token yang hanya akan diambil oleh sesi pelayar sebenar, yang menghentikan kebanyakan pengikis (scraper) ringkas. Jangkakan instans awam akan menarik perhatian mereka dalam masa beberapa hari. Jangkakan juga ralat enjin, kerana lebih banyak trafik yang anda majukan, lebih cepat enjin huluan mula mengembalikan CAPTCHA ke alamat pelayan anda. Instans SearXNG awam ialah tugas yang berterusan. Instans peribadi pula tidak, itulah sebabnya ia berada dalam kebanyakan senarai pendek perkara yang berbaloi untuk di-self-host pada tahun 2026. Tidak semua entri dalam senarai tersebut adalah infrastruktur: membina semula pustaka Jellyfin sebagai kedai sewa era 90-an yang boleh dilayari adalah kontena yang sama di sebalik blok nginx yang sama, yang ditujukan untuk hiburan malam dan bukannya aliran kerja.
Mengapa carian tidak memulangkan hasil
Buka /stats pada instans anda. Ia menyenaraikan setiap enjin beserta kadar ralat dan masa responsnya, dan ia merupakan tempat pertama untuk diperiksa apabila hasil carian terasa berkurangan.
Enjin yang memaparkan ralat "Access denied" atau "CAPTCHA" telah menyekat alamat pelayan anda. Ini adalah perkara biasa bagi alamat dalam julat pusat data, kerana enjin carian menganggap alamat tersebut milik pengikis (scraper). SearXNG kemudiannya akan menggantung enjin yang gagal untuk satu tempoh dan bukannya mencuba semula, jadi satu enjin yang disekat akan hilang secara senyap daripada hasil carian anda. Lumpuhkan enjin tersebut dalam settings.yml atau terima kehilangan tersebut. Itu bukan dua-dua langkah yang ada, kerana beberapa sekatan CAPTCHA mempunyai penyelesaian yang kekal selepas but semula. Enjin yang selebihnya masih akan menjawab. Ralat 429 adalah kes yang samar, kerana ia boleh datang daripada pengehad (limiter) anda sendiri atau daripada enjin huluan yang menolak pelayan anda, dan baris log memberitahu anda yang mana satu antara kedua-duanya sebelum anda mula menukar tetapan.
Jika setiap enjin gagal serentak, kontena tersebut tidak mempunyai resolusi nama keluar yang berfungsi atau tiada laluan ke internet. Uji perkara itu dari dalam kontena.
docker compose exec core wget -qO- https://duckduckgo.com > /dev/null && echo okTiada apa-apa pada kotak tersebut yang akan memberitahu anda apabila pemeriksaan itu mula gagal, jadi jalankannya daripada cron dan biarkan kegagalan menolak makluman ke telefon anda daripada pelayan ntfy anda sendiri dan bukannya menunggu sehingga anda perasan hasil carian telah berkurangan.
FAQ
Adakah SearXNG menjadikan carian saya tanpa nama?
Ia menyembunyikan identiti anda daripada enjin carian yang dihubungi, kerana enjin tersebut melihat pelayan anda yang membuat permintaan, bukannya pelayar web anda. Ia tidak menyembunyikan pertanyaan carian daripada pelayan anda, dan ia tidak menyembunyikan pelayan anda daripada enjin carian tersebut. Pada instans pengguna tunggal, semua trafik daripada alamat tersebut adalah milik anda, jadi alamat itu sendiri menjadi pengecam. Trafik antara pelayar web anda dan instans anda dilindungi oleh sijil TLS. Kedudukan anda berbanding ISP, pengendali instans awam, dan enjin carian itu sendiri dijelaskan dalam apa yang sebenarnya disembunyikan oleh SearXNG.
Mengapa permintaan JSON mengembalikan 403 Forbidden?
Terdapat dua punca, dan kedua-duanya berkaitan dengan konfigurasi. Sama ada json tiada dalam senarai formats di bawah search: dalam settings.yml, yang merupakan keadaan lalai, atau pengehad (limiter) diaktifkan dan telah mengelaskan skrip anda sebagai bot. Tambahkan format tersebut terlebih dahulu, mulakan semula dengan docker compose restart core, kemudian cuba lagi. Jika ia masih gagal, tetapkan limiter: false dan kawal akses pada reverse proxy sebagai gantinya.
Adakah saya memerlukan kontena Valkey jika saya mematikan pengehad?
Biarkan ia berjalan. SearXNG boleh berfungsi tanpanya, tetapi pengehad tidak boleh diaktifkan kemudian tanpa Valkey, dan ia juga menyimpan data sementara yang lain. Kontena tersebut bersaiz kecil dan hanya menyimpan data cache, jadi membuangnya tidak menjimatkan banyak ruang tetapi menghilangkan pilihan tersebut daripada anda.
Bagaimanakah cara untuk mengemas kini SearXNG?
Jalankan docker compose pull kemudian docker compose up -d dalam /opt/searxng. Compose akan mencipta semula mana-mana kontena yang imejnya telah berubah dan membiarkan direktori core-config/ anda tidak disentuh, jadi settings.yml akan kekal. Kerana use_default_settings: true menggabungkan kunci anda dengan tetapan lalai yang dibekalkan, pilihan yang ditambah oleh pembangun asal akan tiba dengan nilai yang wajar dan tidak merosakkan fail tersebut.
Bolehkah beberapa orang berkongsi satu instans?
Ya, dan itulah keadaan di mana anda perlu mengaktifkan pengehad dan menetapkan public_instance: true. Keutamaan disimpan dalam pelayar web setiap pelawat sendiri, jadi tiada akaun yang perlu diuruskan. Pantau /stats selama seminggu selepas membukanya kepada orang lain, kerana enjin carian akan mula menolak pelayan anda jauh sebelum anda menyedari kehilangan hasil carian.