SearXNG को अपने VPS पर Docker के साथ कैसे होस्ट करें
Docker Compose का उपयोग करके अपना निजी SearXNG सर्च इंजन सेटअप करें। इसमें settings.yml कॉन्फ़िगरेशन, Nginx TLS सुरक्षा और स्क्रिप्ट के लिए JSON API का उपयोग करना शामिल है।
आप क्या बना रहे हैं
SearXNG को self-host करने से आपको अपना निजी सर्च इंजन मिलता है जो आपके अपने सर्वर पर चलता है। SearXNG एक मेटासर्च इंजन है: यह आपकी क्वेरी लेता है, Google, Bing, DuckDuckGo और Wikipedia जैसे अन्य इंजनों से पूछता है, और फिर जो परिणाम मिलते हैं उन्हें एक पेज पर मिला देता है। कोई प्रोफाइल नहीं बनाई जाती और कोई ट्रैकिंग कुकी सेट नहीं की जाती, क्योंकि आपकी क्वेरी को रखने वाली एकमात्र मशीन आप स्वयं हैं। यदि आपको केवल Searx नामक किसी चीज़ के लिए पुराने गाइड मिले हैं, तो यह वही प्रोजेक्ट है जिससे यह fork हुआ है, और इसमें 2023 के बाद से कोई commit नहीं आया है, इसलिए किसी एक का पालन करने से पहले दोनों की स्थिति की जाँच करें।
इसका स्टैक छोटा है। दो कंटेनर, एक सेटिंग्स फ़ाइल, एक रिवर्स प्रॉक्सी। यह एक छोटे VPS पर आसानी से चल जाएगा, जो हर self-hosted सर्विस के लिए सच नहीं है: PhotoPrism बनाम Immich में तौली गई फोटो लाइब्रेरी ने अपना RAM फ्लोर वेब ऐप के बजाय इंडेक्सर द्वारा निर्धारित किया था। वास्तविक निर्णय यह है कि क्या इंस्टेंस निजी है, जिसका अर्थ है कि केवल आप और आपकी अपनी स्क्रिप्ट्स ही उस तक पहुँचती हैं, या सार्वजनिक है, जिसका अर्थ है कि इंटरनेट पर कोई भी इसे क्वेरी कर सकता है। वह विकल्प सुरक्षा सेटिंग्स को बदल देता है, इसलिए कुछ भी टाइप करने से पहले उसे तय कर लें। डिफ़ॉल्ट उत्तर निजी है।
इसे चलाने का दूसरा कारण भी है। एक SearXNG इंस्टेंस JSON में बात करता है, इसलिए आपके द्वारा लिखी गई कोई भी स्क्रिप्ट या AI एजेंट को एक सर्च API मिलता है जिसका स्वामित्व आपके पास होता है, जिसमें कोई की (key), प्रति-क्वेरी बिलिंग और कोई कोटा मेल नहीं होता है।
Docker Compose के साथ SearXNG इंस्टॉल करें
यह प्रोजेक्ट एक container image और एक Compose file प्रकाशित करता है। इन दोनों को एक नए Ubuntu 24.04 सर्वर पर pull करें, जिस पर Docker Engine और Compose plugin पहले से मौजूद हों। यदि आप Docker में नए हैं, तो VPS पर Docker Compose की बुनियादी जानकारी से शुरुआत करें और फिर वापस आएं।
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 .envCompose file दो services को परिभाषित करती है। core स्वयं SearXNG है, और valkey एक in-memory data store है जिसका उपयोग rate limiting और अल्पकालिक state के लिए किया जाता है। यह container के अंदर /etc/searxng/ पर ./core-config/ को mount करता है, इसलिए आप जो कुछ भी configure करते हैं, वह host पर उसी एक directory में रहता है।
अब .env को edit करें। दिए गए उदाहरण में हर line comment की गई है, इसीलिए container हर address पर port 8080 पर start होता है। इन तीनों को uncomment करें और set करें।
SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080SEARXNG_HOST=127.0.0.1 सबसे महत्वपूर्ण है। यह published port को [::]:8080:8080 के बजाय 127.0.0.1:8080:8080 बना देता है, ताकि container केवल loopback address पर ही जवाब दे और internet उस तक सीधे न पहुँच सके। इसे न छोड़ें, अन्यथा container start होते ही expose हो जाएगा, क्योंकि एक published Docker port आपके firewall rules से पहले insert हो जाता है। यह trap विस्तार से पढ़ने योग्य है: published Docker ports ufw को bypass करते हैं।
सीखने के दौरान SEARXNG_VERSION=latest ठीक है। जिस सर्वर की आप परवाह करते हैं, उस पर tag को pin करें। जुलाई 2026 तक release tags तारीख पर आधारित हैं और 2026.3.25-541c6c3cb जैसे दिखते हैं, इसलिए एक pinned deployment तब upgrade होता है जब आप तय करते हैं, न कि तब जब registry में बदलाव होता है। यही अनुशासन box पर मौजूद किसी भी अन्य long-lived service के लिए भी फायदेमंद है, इसीलिए एक self-hosted RustDesk relay भी अपने image tags को pin करता है: remote access service का अनपेक्षित upgrade सबसे खराब समय पर समस्या पैदा कर सकता है।
settings.yml: महत्वपूर्ण हिस्से
पहली बार start करने से पहले core-config/settings.yml बनाएँ। use_default_settings: true SearXNG को अपने डिफ़ॉल्ट मान लोड करने और फिर केवल आपके द्वारा लिखे गए keys को लागू करने का निर्देश देता है, जिससे आपकी फ़ाइल छोटी रहती है और नए विकल्प जोड़ने वाले अपग्रेड के बाद भी सुरक्षित रहती है।
सबसे पहले secret जनरेट करें, क्योंकि यह मान सीधे फ़ाइल में जाता है।
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 सेशन और टोकन डेटा को साइन करता है। डिफ़ॉल्ट मान literal स्ट्रिंग ultrasecretkey है, और इसे ऐसे ही छोड़ने का मतलब है कि कोई भी व्यक्ति जो इस डिफ़ॉल्ट को जानता है, वह टोकन को forge कर सकता है। इसे एक बार बदलें, फिर इसे न छुएं: इसे बाद में बदलने से सभी सेव की गई प्राथमिकताएँ (preferences) हट जाएँगी।
base_url को trailing slash के साथ public HTTPS पता होना चाहिए। SearXNG इसी का उपयोग उन लिंक को लिखने में करता है जिन्हें वह रेंडर करता है। यदि इसे localhost पर छोड़ दिया जाए, तो रिमोट ब्राउज़र में "अगला पेज" लिंक रीडर की अपनी मशीन पर पॉइंट करेगा और विफल हो जाएगा।
formats यह तय करता है कि वेब एंडपॉइंट किस प्रकार के आउटपुट तैयार करेगा। json डिफ़ॉल्ट सूची में नहीं है, इसलिए जब तक आप इसे जोड़ नहीं लेते, JSON अनुरोध 403 एरर देगा। image_proxy: true रिजल्ट थंबनेल को आपके सर्वर के माध्यम से रूट करता है, ताकि उन छवियों को होस्ट करने वाली साइटें आपके विज़िटर्स के पते कभी न देख सकें।
valkey.url होस्टनेम valkey का उपयोग करता है क्योंकि Compose फ़ाइल में यही सर्विस का नाम है, और Compose दोनों कंटेनरों को एक ही नेटवर्क पर रखता है जहाँ सर्विस नाम रिज़ॉल्व हो जाते हैं। इसे localhost पर पॉइंट न करें, अन्यथा लिमिटर विफल हो जाएगा, क्योंकि core कंटेनर के अंदर localhost वही कंटेनर होता है।
secret एक सादी फ़ाइल में होता है, इसलिए फ़ाइल के बजाय उसके आसपास की डायरेक्टरी को सुरक्षित करें। chmod 750 /opt/searxng अन्य होस्ट यूज़र्स को बाहर रखता है। core-config/settings.yml को मोड 600 तक न कसें: कंटेनर अपने स्वयं के unprivileged यूज़र के रूप में चलता है, और यदि वह फ़ाइल को पढ़ नहीं पाएगा, तो SearXNG स्टार्ट ही नहीं होगा।
स्टैक को स्टार्ट करें और उसे चेक करें।
cd /opt/searxng
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080/docker compose ps में दोनों कंटेनर running स्थिति में दिखने चाहिए। curl को HTTP/1.1 200 OK का उत्तर देना चाहिए। यदि कोई उत्तर नहीं मिलता है, तो docker compose logs core पढ़ें, क्योंकि settings.yml में कोई भी YAML गलती वहाँ एक पार्स एरर के रूप में दिखाई देगी जिसमें लाइन नंबर का उल्लेख होगा।
इसे Nginx के पीछे TLS के साथ रखें
Container केवल loopback पर listen करता है, इसलिए Nginx ही इसे सुलभ बनाता है और यही transport layer security (TLS) भी जोड़ता है। /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, reload करने से पहले syntax is ok और test is successful को print करता है। Certbot उसी file को rewrite करके 443 port पर certificate के साथ listen करने के लिए set करता है और port 80 से एक redirect जोड़ता है। search.example.com के लिए DNS record का इस सर्वर पर point करना अनिवार्य है, क्योंकि certificate authority HTTP के माध्यम से एक file fetch करके स्वामित्व की पुष्टि करती है। renewal सहित पूरी प्रक्रिया Ubuntu 24.04 के लिए Certbot और Nginx गाइड में दी गई है।
ये दो forwarding headers केवल दिखावे के लिए नहीं हैं। X-Forwarded-For और X-Real-IP के बिना, SearXNG पर आने वाली हर request में proxy का address होता है, जिससे rate limiter को लगता है कि सारा traffic एक ही client से आ रहा है और वह visitors के बीच अंतर नहीं कर पाता।
स्क्रिप्ट और एजेंटों को JSON सर्च API की आवश्यकता क्यों है
json में formats के साथ, वही एंडपॉइंट जो पेज को रेंडर करता है, स्ट्रक्चर्ड डेटा भी लौटाता है।
curl -s 'http://127.0.0.1:8080/search?q=wireguard+mtu&format=json' \
| jq -r '.results[0:5][] | .url'आपको एक results ऐरे वाला ऑब्जेक्ट मिलता है, जहाँ प्रत्येक एंट्री में url, title, content और उसे प्रदान करने वाला इंजन होता है, साथ ही answers, infoboxes और suggestions भी होते हैं। यह किसी समराइज़र, लिंक चेकर या रिसर्च लूप को फीड करने के लिए पर्याप्त है। उन परिणामों को किसी लैंग्वेज मॉडल को सौंपना दिखने में जितना सरल है, उससे कहीं अधिक बड़ा कदम है, क्योंकि सर्च परिणाम अविश्वसनीय टेक्स्ट होते हैं जिनमें स्वयं के निर्देश हो सकते हैं, और यही वह विषय है जिसे अपने SearXNG इंस्टेंस पर AI एजेंट को पॉइंट करना विस्तार से समझाता है।
यह एजेंट-आधारित किसी भी चीज़ के लिए महत्वपूर्ण है। एक लैंग्वेज मॉडल की ट्रेनिंग कटऑफ होती है, इसलिए उसे वर्तमान के बारे में सवालों के जवाब देने के लिए लाइव सर्च की आवश्यकता होती है, और कमर्शियल सर्च API प्रति क्वेरी शुल्क लेते हैं और उन पर सख्त रेट लिमिट होती है। एक लोकल इंस्टेंस का खर्च उस सर्वर पर केवल एक कंटेनर का होता है जिसके लिए आप पहले से भुगतान कर रहे हैं, और क्वेरी कभी भी उससे बाहर नहीं जाती हैं। यदि आप किसी मॉडल में टूल्स जोड़ रहे हैं, तो यही तर्क VPS पर MCP सर्वर चलाने को प्रेरित करता है, जहाँ सर्च टूल आमतौर पर वह पहला टूल होता है जिसे लोग जोड़ते हैं।
API उपयोग के लिए दो नियम हैं। इंस्टेंस को प्राइवेट रखें, इसलिए API साइड को लूपबैक एड्रेस या प्राइवेट नेटवर्क से बाइंड करें और केवल अपने होस्ट्स को ही इसे एक्सेस करने दें। फिर इसे सावधानी से क्वेरी करें। SearXNG आपकी रिक्वेस्ट को वास्तविक सर्च इंजनों को फॉरवर्ड करता है, इसलिए प्रति सेकंड सौ क्वेरी चलाने वाली स्क्रिप्ट Google को आपके सर्वर को ब्लॉक करने के लिए मजबूर कर सकती है।
Limiter, और एक public instance के लिए क्या बदलाव होते हैं
Limiter, SearXNG का bot defence है। यह request headers, addresses और request rates की निगरानी करता है, और automated दिखने वाले traffic को drop कर देता है। इस state को hold करने के लिए इसे Valkey की आवश्यकता होती है, इसीलिए Compose file में यह शामिल है।
Private instance पर limiter: false को चालू रखें। आपकी अपनी scripts परिभाषा के अनुसार automated traffic हैं, इसलिए limiter ठीक उन्हीं JSON calls को block कर देगा जिनके लिए आपने instance बनाया था। इसके बजाय, access control reverse proxy का काम है: nginx location में एक allow और deny pair, HTTP basic authentication, या एक ऐसा firewall जो केवल आपके अन्य servers को ही अनुमति दे। यदि आपको किसी ऐसे laptop से private instance तक पहुँचना है जो अलग-अलग networks के बीच move करता है, तो इसके सामने v3 onion address लगाना एक चौथा विकल्प है, क्योंकि tor internet पर कुछ भी नया expose किए बिना उसी loopback port से connect हो जाता है।
यदि आप instance को अन्य लोगों के लिए publish करते हैं, तो दोनों switches को on कर दें।
server:
limiter: true
public_instance: trueअधिक सूक्ष्म नियंत्रण core-config/limiter.toml में होता है, जिसे container /etc/searxng/limiter.toml पर read करता है। आप केवल वही keys लिखें जिन्हें आप बदलना चाहते हैं। Proxy के पीछे आपको proxy घोषित करना होगा, अन्यथा limiter आपके nginx address को ही एकमात्र abusive client मान लेगा।
[botdetection]
trusted_proxies = [
'127.0.0.0/8',
'::1',
]
[botdetection.ip_limit]
link_token = truelink_token = true, SearXNG को एक token जारी करने के लिए कहता है जिसे केवल एक वास्तविक browser session ही fetch करेगा, जो अधिकांश साधारण scrapers को रोक देता है। उम्मीद रखें कि एक public instance कुछ ही दिनों में उन्हें आकर्षित कर लेगा। Engine errors की भी उम्मीद रखें, क्योंकि आप जितना अधिक traffic forward करेंगे, upstream engines उतनी ही जल्दी आपके server address पर CAPTCHAs भेजना शुरू कर देंगे। एक public SearXNG instance एक निरंतर चलने वाला काम है। एक private instance ऐसा नहीं है, इसीलिए यह 2026 में self-host करने योग्य चीजों की अधिकांश छोटी सूचियों में शामिल है। उन सूचियों में हर entry infrastructure भी नहीं है: Jellyfin library को 90 के दशक के rental store जैसा बनाना उसी nginx block के पीछे वही एक container है, जो workflow के बजाय शाम के मनोरंजन के लिए है।
खोज परिणाम खाली क्यों आते हैं
अपने instance पर /stats खोलें। यह प्रत्येक engine को उसकी error rate और response time के साथ सूचीबद्ध करता है, और जब परिणाम कम महसूस हों तो सबसे पहले यहीं देखना चाहिए।
"Access denied" या "CAPTCHA" errors के साथ दिखने वाले engine ने आपके server address को block कर दिया है। Data centre ranges के addresses के लिए यह सामान्य है, क्योंकि search engines मानते हैं कि वे scrapers के हैं। इसके बाद SearXNG विफल engine को दोबारा retry करने के बजाय कुछ समय के लिए suspend कर देता है, इसलिए एक blocked engine चुपचाप आपके results से हट जाता है। इसे settings.yml में disable करें या इस कमी को स्वीकार करें। ये केवल दो विकल्प नहीं हैं, क्योंकि कुछ CAPTCHA blocks का ऐसा समाधान है जो restart के बाद भी बना रहता है। बाकी engines फिर भी response देते रहते हैं। 429 अस्पष्ट स्थिति है, क्योंकि यह आपके अपने limiter से आ सकता है या upstream engine आपके server को अस्वीकार कर सकता है। Settings बदलने से पहले log line बताती है कि इनमें से कौन-सी स्थिति है।
यदि हर engine एक साथ विफल हो जाता है, तो container के पास कोई कार्यशील outbound name resolution नहीं है या internet के लिए कोई route नहीं है। container के अंदर से इसका परीक्षण करें।
docker compose exec core wget -qO- https://duckduckgo.com > /dev/null && echo okbox पर कुछ भी आपको यह नहीं बताएगा कि वह check कब विफल होना शुरू होता है, इसलिए इसे cron से चलाएँ और विफलता को अपने स्वयं के ntfy server से अपने फोन पर alert भेजने दें बजाय इसके कि आप तब तक प्रतीक्षा करें जब तक आप यह न देख लें कि परिणाम कम हो गए हैं।
FAQ
क्या SearXNG मेरी खोजों को गुमनाम बनाता है?
यह उन सर्च इंजनों से आपकी पहचान छिपाता है जिनसे यह क्वेरी करता है, क्योंकि वे आपके ब्राउज़र के बजाय आपके सर्वर को अनुरोध करते हुए देखते हैं। यह आपके सर्वर से क्वेरी को नहीं छिपाता है, और यह आपके सर्वर को उनसे नहीं छिपाता है। सिंगल-यूज़र इंस्टेंस पर उस पते से आने वाला सारा ट्रैफ़िक आपका होता है, इसलिए वह पता ही आपकी पहचान बन जाता है। आपके ब्राउज़र और आपके इंस्टेंस के बीच का ट्रैफ़िक TLS certificate द्वारा सुरक्षित होता है। आपके ISP, पब्लिक इंस्टेंस के ऑपरेटर और स्वयं सर्च इंजनों के सामने आपकी स्थिति क्या है, इसे SearXNG वास्तव में क्या छिपाता है में विस्तार से समझाया गया है।
JSON अनुरोध 403 Forbidden क्यों देता है?
इसके दो कारण हैं, और दोनों कॉन्फ़िगरेशन से संबंधित हैं। या तो json, settings.yml में search: के अंतर्गत formats सूची से गायब है, जो कि डिफ़ॉल्ट स्थिति है, या लिमिटर चालू है और उसने आपकी स्क्रिप्ट को बॉट के रूप में वर्गीकृत कर दिया है। पहले फॉर्मेट जोड़ें, docker compose restart core के साथ रीस्टार्ट करें, फिर पुनः प्रयास करें। यदि यह अभी भी विफल रहता है, तो limiter: false सेट करें और रिवर्स प्रॉक्सी पर एक्सेस को नियंत्रित करें।
यदि मैं लिमिटर बंद रखूँ तो क्या मुझे Valkey कंटेनर की आवश्यकता है?
इसे चलते रहने दें। SearXNG इसके बिना काम करता है, लेकिन इसके बिना बाद में लिमिटर को चालू नहीं किया जा सकता है, और यह अन्य अल्पकालिक स्टेट (short-lived state) को भी सुरक्षित रखता है। कंटेनर छोटा है और केवल कैश किया गया डेटा स्टोर करता है, इसलिए इसे हटाने से बहुत कम बचत होती है और आप एक विकल्प खो देते हैं।
मैं SearXNG को अपडेट कैसे करूँ?
/opt/searxng में पहले docker compose pull और फिर docker compose up -d चलाएँ। Compose किसी भी ऐसे कंटेनर को फिर से बनाता है जिसकी इमेज बदल गई है और आपकी core-config/ डायरेक्टरी को सुरक्षित रखता है, इसलिए settings.yml बना रहता है। चूँकि use_default_settings: true आपकी कुंजियों को शिप किए गए डिफ़ॉल्ट के साथ मर्ज करता है, इसलिए अपस्ट्रीम में जोड़े गए विकल्प फ़ाइल को खराब करने के बजाय उचित मानों के साथ आते हैं।
क्या कई लोग एक इंस्टेंस साझा कर सकते हैं?
हाँ, और यही वह स्थिति है जहाँ आप लिमिटर को चालू करते हैं और public_instance: true सेट करते हैं। प्राथमिकताएँ प्रत्येक विज़िटर के अपने ब्राउज़र में संग्रहीत होती हैं, इसलिए प्रबंधित करने के लिए कोई अकाउंट नहीं होता है। इसे खोलने के बाद एक सप्ताह तक /stats पर नज़र रखें, क्योंकि अपस्ट्रीम इंजन आपके द्वारा परिणाम गायब होने का नोटिस लेने से बहुत पहले ही आपके सर्वर को रिजेक्ट करना शुरू कर देते हैं।