SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor

Cara Self-Host SearXNG dengan Docker Compose

Bangun mesin pencari privat di VPS dengan Docker Compose, settings.yml, limiter, nginx dan TLS, lalu panggil API pencarian JSON dari skrip Anda sendiri.

Apa yang Anda bangun

Self-hosting SearXNG memberi Anda mesin pencari privat yang berjalan di server milik Anda sendiri. SearXNG adalah mesin metapencarian: SearXNG menerima kueri Anda, mengirimkannya ke mesin lain seperti Google, Bing, DuckDuckGo, dan Wikipedia, lalu menggabungkan hasilnya menjadi satu halaman hasil. Tidak ada profil yang dibuat dan tidak ada cookie pelacakan yang ditetapkan karena satu-satunya mesin yang menyimpan kueri Anda adalah milik Anda. Jika Anda menemukan panduan lama untuk sesuatu yang hanya disebut Searx, itulah proyek yang menjadi asal fork ini. Proyek tersebut tidak dipelihara sejak September 2023, ketika repositorinya sendiri mengumumkan bahwa Searx tidak lagi dipelihara, dan satu commit setelahnya, berupa catatan dokumentasi pada Mei 2026, tidak mengubah hal tersebut. Jadi, periksa status keduanya sebelum mengikuti salah satunya.

Stack ini kecil. Dua container, satu file settings, dan satu reverse proxy. Stack ini dapat berjalan dengan baik pada VPS kecil, tetapi hal itu tidak berlaku untuk setiap service self-hosted: pustaka foto yang dibandingkan dalam PhotoPrism dan Immich menetapkan kebutuhan RAM minimumnya berdasarkan indexer, bukan aplikasi web. Keputusan sebenarnya adalah apakah instance tersebut bersifat privat, yang berarti hanya Anda dan script milik Anda yang dapat mengaksesnya, atau publik, yang berarti siapa pun di Internet dapat menggunakannya untuk melakukan kueri. Pilihan tersebut mengubah pengaturan keamanan, jadi tentukan sebelum mengetik apa pun. Jawaban defaultnya adalah privat.

Ada alasan kedua untuk menjalankan instance ini. Instance SearXNG menyediakan JSON, sehingga script atau AI agent apa pun yang Anda buat memperoleh API pencarian milik Anda sendiri, tanpa key, biaya per kueri, atau email tentang kuota.

Instal SearXNG dengan Docker Compose

Proyek ini menyediakan image container dan file Compose. Tarik keduanya ke server Ubuntu 24.04 baru yang sudah memiliki Docker Engine dan plugin Compose. Jika Docker masih baru bagi Anda, mulai dengan dasar-dasar Docker Compose pada VPS, lalu kembali 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 .env

File Compose tersebut mendefinisikan dua service. core adalah SearXNG, sedangkan valkey adalah penyimpanan data dalam memori yang digunakan untuk rate limiting dan state berumur pendek. File ini me-mount ./core-config/ ke /etc/searxng/ di dalam container, sehingga semua konfigurasi yang Anda buat berada dalam satu direktori tersebut di host.

Sekarang edit .env. Setiap baris dalam contoh yang disediakan diberi komentar. Itu sebabnya container berjalan pada port 8080 di semua alamat. Hapus tanda komentar dan atur tiga baris berikut.

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1 adalah bagian yang penting. Pengaturan ini membuat port yang dipublikasikan menjadi 127.0.0.1:8080:8080, bukan 8080:8080 tanpa alamat tertentu. Docker memublikasikan port tanpa alamat tertentu pada semua alamat. Dengan demikian, container hanya merespons pada alamat loopback dan Internet tidak dapat menjangkaunya secara langsung. Jika langkah ini dilewati, container langsung terekspos saat mulai berjalan karena port Docker yang dipublikasikan dipasang sebelum aturan firewall Anda. Baca penjelasan lengkap tentang jebakan ini: port Docker yang dipublikasikan melewati ufw.

SEARXNG_VERSION=latest cukup digunakan saat Anda masih mempelajarinya. Pada server yang penting, tetapkan tag secara eksplisit. Per Oktober 2026, tag rilis menggunakan tanggal dan berbentuk 2026.10.4-d48c4b555. Dengan demikian, deployment yang menggunakan tag tetap hanya diperbarui ketika Anda memutuskan, bukan ketika registry berubah tanpa sepengetahuan Anda. Disiplin yang sama bermanfaat untuk komponen lain yang harus berjalan dalam jangka panjang di server. Karena itu, relay RustDesk yang di-host sendiri juga menetapkan tag image: pembaruan tanpa pengawasan pada service akses jarak jauh dapat muncul pada saat yang paling buruk.

settings.yml: bagian yang penting

Buat core-config/settings.yml sebelum menjalankan service untuk pertama kali. use_default_settings: true memerintahkan SearXNG untuk memuat default bawaan yang disertakan, lalu hanya menerapkan key yang Anda tulis. Dengan begitu, file tetap singkat dan tetap kompatibel ketika upgrade menambahkan opsi baru.

Buat secret terlebih dahulu karena nilainya akan langsung dimasukkan ke 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

secret_key menandatangani data sesi dan token. Default bawaan adalah string literal ultrasecretkey. Jika dibiarkan, siapa pun yang mengetahui default tersebut dapat memalsukan token. Ganti sekali, lalu jangan ubah lagi. Mengubahnya kemudian akan menghapus semua preferensi yang tersimpan.

base_url harus berisi alamat HTTPS publik dengan trailing slash. SearXNG menggunakan alamat ini saat menulis link yang direndernya. Jika tetap diarahkan ke localhost, link "next page" pada browser remote akan mengarah ke mesin milik pembaca sendiri dan gagal.

formats menentukan jenis output yang akan dihasilkan endpoint web. json tidak ada dalam daftar default, sehingga request JSON mengembalikan 403 sampai Anda menambahkannya. image_proxy: true meneruskan thumbnail hasil melalui server Anda. Dengan demikian, situs yang meng-host gambar tersebut tidak pernah melihat alamat pengunjung Anda.

valkey.url menggunakan hostname valkey karena itulah nama service dalam file Compose. Compose menempatkan kedua container pada satu network sehingga nama service dapat di-resolve. Jika diarahkan ke localhost, limiter akan gagal karena di dalam container core, localhost adalah container itu sendiri.

Secret tersimpan dalam file biasa, jadi lindungi direktori di sekitarnya juga. chmod 750 /opt/searxng mencegah user lain pada host mengaksesnya. Anda juga dapat memperketat core-config/settings.yml ke mode 600 tanpa menimbulkan masalah. Entrypoint container resmi dimulai sebagai root dan, jika FORCE_OWNERSHIP dibiarkan pada default true, menyerahkan direktori konfigurasi yang di-mount kepada user searxng milik container sebelum SearXNG dijalankan. Dengan demikian, file tetap dapat dibaca oleh user tersebut. Dampaknya terlihat pada host: langkah yang sama mengubah owner core-config/ menjadi user ID milik container. Karena itu, setelahnya Anda perlu mengedit file dengan sudo.

Jalankan stack dan periksa hasilnya.

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

docker compose ps seharusnya menampilkan kedua container dalam status running. curl seharusnya merespons dengan HTTP/1.1 200 OK. Jika tidak memberikan respons, baca docker compose logs core. Kesalahan YAML dalam settings.yml akan muncul di sana sebagai parse error yang mencantumkan nomor baris.

Tempatkan di belakang nginx dengan TLS

Container hanya mendengarkan pada loopback. Karena itu, nginx membuatnya dapat dijangkau dan juga menambahkan keamanan lapisan transport (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.com

nginx -t mencetak syntax is ok dan test is successful sebelum Anda memuat ulang konfigurasi. Certbot menulis ulang file yang sama agar mendengarkan pada 443 dengan sertifikat dan menambahkan pengalihan dari port 80. Catatan DNS untuk search.example.com harus sudah mengarah ke server ini karena otoritas sertifikat membuktikan kepemilikan dengan mengambil file melalui HTTP. Panduan lengkap, termasuk perpanjangan sertifikat, tersedia di panduan Certbot dan nginx untuk Ubuntu 24.04.

Kedua header penerusan tersebut bukan sekadar hiasan. Tanpa X-Forwarded-For dan X-Real-IP, setiap permintaan yang tiba di SearXNG membawa alamat proxy. Akibatnya, pembatas laju menganggap satu klien menghasilkan seluruh trafik dan tidak dapat membedakan pengunjung.

Mengapa skrip dan agent memerlukan API pencarian JSON

Dengan json di formats, endpoint yang sama untuk merender halaman juga mengembalikan data terstruktur.

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

Anda menerima objek dengan array results. Setiap entri memuat url, title, content, dan engine yang menyediakannya, serta answers, infoboxes, dan suggestions. Data ini cukup untuk diberikan kepada summariser, pemeriksa tautan, atau loop riset. Memberikan hasil tersebut kepada language model merupakan langkah yang dampaknya lebih besar daripada yang terlihat, karena hasil pencarian adalah teks tidak tepercaya yang dapat membawa instruksinya sendiri. Hal inilah yang dibahas secara terperinci dalam mengarahkan agent AI ke instance SearXNG Anda.

Hal ini penting untuk semua sistem berbasis agent. Language model memiliki batas waktu data pelatihan, sehingga memerlukan pencarian langsung untuk menjawab pertanyaan tentang kondisi terkini. Selain itu, API pencarian komersial mengenakan biaya per kueri dan menerapkan rate limit yang ketat. Instance lokal hanya memerlukan satu container pada server yang sudah Anda bayar, dan kueri tidak pernah keluar dari server tersebut. Jika Anda menghubungkan tool ke model, alasan yang sama juga mendasari menjalankan server MCP pada VPS, karena tool pencarian biasanya menjadi tool pertama yang ditambahkan.

Terapkan dua aturan saat menggunakan API. Jaga agar instance tetap privat. Bind sisi API ke alamat loopback atau jaringan privat, lalu izinkan hanya host milik Anda yang mengaksesnya. Perlakuan yang sama diperlukan oleh location tracker yang di-host sendiri untuk endpoint yang menerima laporan posisi dari ponsel Anda. Selanjutnya, kirim kueri secara wajar. SearXNG meneruskan permintaan Anda ke engine pencarian yang sebenarnya, sehingga skrip yang menjalankan seratus kueri per detik sama saja dengan meminta Google memblokir server Anda.

Limiter dan perubahan untuk instance publik

Limiter adalah pertahanan bot SearXNG. Limiter memantau header permintaan, alamat, dan laju permintaan, lalu membuang trafik yang terlihat otomatis. Limiter memerlukan Valkey untuk menyimpan status tersebut. Karena itu, Valkey disertakan dalam file Compose.

Pada instance privat, pertahankan limiter: false. Skrip Anda sendiri pada dasarnya merupakan trafik otomatis. Karena itu, limiter akan memblokir panggilan JSON yang memang menjadi tujuan instance tersebut. Sebagai gantinya, kontrol akses menjadi tugas reverse proxy: pasangan allow dan deny dalam location nginx, autentikasi dasar HTTP, atau firewall yang hanya mengizinkan server lain milik Anda. Jika Anda perlu mengakses instance privat dari laptop yang berpindah-pindah jaringan, pasang alamat onion v3 di depannya sebagai opsi keempat. Tor terhubung ke port loopback yang sama tanpa mengekspos apa pun yang baru ke Internet.

Jika instance tersebut dipublikasikan untuk orang lain, aktifkan kedua switch.

server:
  limiter: true
  public_instance: true

Kontrol yang lebih terperinci berada dalam core-config/limiter.toml, yang dibaca container dari /etc/searxng/limiter.toml. Anda hanya perlu menulis key yang ingin diubah. Jika menggunakan proxy, Anda harus mendeklarasikan proxy tersebut. Jika tidak, limiter akan menganggap alamat nginx Anda sebagai satu-satunya klien yang menyalahgunakan layanan.

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

[botdetection.ip_limit]
link_token = true

link_token = true membuat SearXNG menerbitkan token yang hanya akan diambil oleh sesi browser nyata. Ini menghentikan sebagian besar scraper sederhana. Perkirakan instance publik akan menarik scraper dalam hitungan hari. Perkirakan juga munculnya error engine, karena semakin banyak trafik yang Anda teruskan, semakin cepat engine upstream mulai mengembalikan CAPTCHA ke alamat server Anda. Instance publik SearXNG memerlukan pemeliharaan berkelanjutan. Instance privat tidak, sehingga instance ini tercantum dalam sebagian besar daftar singkat hal yang layak di-self-host pada 2026. Tidak semua entri dalam daftar tersebut merupakan infrastruktur: membangun ulang library Jellyfin sebagai toko rental era 90-an yang dapat dijelajahi tetap menggunakan satu container di balik blok nginx yang sama, tetapi diarahkan pada suasana malam, bukan alur kerja.

Mengapa pencarian tidak menghasilkan apa pun

Buka /stats pada instance Anda. Halaman ini mencantumkan setiap engine beserta tingkat error dan waktu responsnya. Ini adalah tempat pertama yang perlu diperiksa ketika hasil pencarian terlihat sedikit.

Engine dengan error "Access denied" atau "CAPTCHA" berarti telah memblokir alamat server Anda. Hal ini umum terjadi pada alamat dalam rentang data center karena search engine menganggap alamat tersebut milik scraper. SearXNG kemudian menangguhkan engine yang gagal selama periode tertentu, bukan langsung mencoba ulang. Akibatnya, satu engine yang diblokir diam-diam tidak lagi menyumbang hasil pencarian. Nonaktifkan engine tersebut di settings.yml atau terima kehilangan itu. Namun, hanya itu bukan satu-satunya pilihan, karena sebagian blokir CAPTCHA dapat diperbaiki secara permanen setelah restart. Engine lain tetap memberikan respons. Error 429 adalah kasus yang ambigu karena dapat berasal dari limiter Anda sendiri atau dari engine upstream yang menolak server Anda. Baris log menunjukkan sumbernya sebelum Anda mulai mengubah pengaturan.

Jika semua engine gagal secara bersamaan, container tidak memiliki resolusi nama outbound yang berfungsi atau tidak memiliki route ke Internet. Uji kondisi tersebut dari dalam container.

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

Tidak ada informasi pada server yang akan memberi tahu Anda saat pemeriksaan tersebut mulai gagal. Karena itu, jalankan pemeriksaan dari cron dan biarkan kegagalan mengirimkan alert ke ponsel Anda melalui server ntfy milik sendiri, alih-alih menunggu sampai Anda menyadari bahwa hasil pencarian mulai berkurang.

FAQ

Apakah SearXNG membuat pencarian saya anonim?

SearXNG menyembunyikan identitas Anda dari mesin pencari yang diaksesnya karena mesin tersebut melihat server Anda yang mengirimkan permintaan, bukan browser Anda. SearXNG tidak menyembunyikan kueri dari server Anda dan tidak menyembunyikan server Anda dari mesin pencari tersebut. Pada instance untuk satu pengguna, seluruh trafik dari alamat tersebut berasal dari Anda, sehingga alamat itu sendiri menjadi pengidentifikasi. Trafik antara browser dan instance Anda dilindungi oleh sertifikat TLS. Dampaknya terhadap hubungan Anda dengan ISP, operator instance publik, dan mesin pencari dibahas dalam apa yang sebenarnya disembunyikan SearXNG.

Mengapa permintaan JSON mengembalikan 403 Forbidden?

Ada dua penyebab, dan keduanya terkait konfigurasi. json tidak tercantum dalam daftar formats di bawah search: dalam settings.yml, yang merupakan kondisi default, atau limiter aktif dan mengklasifikasikan skrip Anda sebagai bot. Tambahkan format tersebut terlebih dahulu, lalu lakukan restart dengan docker compose restart core dan coba lagi. Jika masih gagal, tetapkan limiter: false dan kendalikan akses di reverse proxy.

Apakah saya memerlukan container Valkey jika limiter tetap dinonaktifkan?

Biarkan container tersebut tetap berjalan. SearXNG dapat bekerja tanpanya, tetapi limiter tidak dapat diaktifkan nanti tanpa container tersebut. Container itu juga menyimpan state lain yang berumur singkat. Ukuran container kecil dan hanya menyimpan data cache, sehingga menghapusnya hanya menghemat sedikit ruang dan membuat Anda kehilangan opsi tersebut.

Bagaimana cara memperbarui SearXNG?

Jalankan docker compose pull, lalu docker compose up -d di /opt/searxng. Compose membuat ulang setiap container yang image-nya berubah dan membiarkan direktori core-config/ tetap utuh, sehingga settings.yml tetap tersedia. Karena use_default_settings: true menggabungkan key Anda dengan default yang disertakan, opsi yang ditambahkan upstream akan menggunakan nilai yang sesuai, bukan menyebabkan file rusak.

Dapatkah beberapa orang menggunakan satu instance bersama-sama?

Ya. Dalam kondisi ini, aktifkan limiter dan tetapkan public_instance: true. Preferensi disimpan di browser masing-masing pengunjung, sehingga tidak ada akun yang perlu dikelola. Pantau /stats selama seminggu setelah instance dibuka untuk umum karena mesin pencari upstream mulai menolak server Anda jauh sebelum Anda menyadari bahwa hasil pencarian berkurang.

Apakah artikel ini bermanfaat?