SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-09-05

নিজের VPS-এ SearXNG private search চালানোর পদ্ধতি

Docker Compose দিয়ে নিজের VPS-এ SearXNG চালান। settings.yml, limiter, nginx TLS এবং script থেকে ব্যবহারযোগ্য JSON search API কনফিগার করার ধাপ দেখুন।

আপনি যা তৈরি করছেন

SearXNG self-host করলে আপনি নিজের সার্ভারে চলা একটি private search engine পান। SearXNG একটি metasearch engine। এটি আপনার query নিয়ে Google, Bing, DuckDuckGo এবং Wikipedia-এর মতো অন্য engine-এ পাঠায়। এরপর প্রাপ্ত ফল একত্র করে একটি result page তৈরি করে। কোনো profile তৈরি হয় না এবং কোনো tracking cookie সেট করা হয় না। কারণ আপনার query সংরক্ষণ করে একমাত্র আপনার নিজের machine। শুধু Searx নামে পরিচিত পুরোনো guide পেয়ে থাকলে জেনে রাখুন, এই project সেই project থেকেই fork করা হয়েছে। সেখানে 2023-এর পর আর কোনো commit হয়নি। তাই একটি অনুসরণ করার আগে উভয়টির অবস্থা যাচাই করুন

এই stack ছোট। এতে দুটি container, একটি settings file এবং একটি reverse proxy থাকে। এটি একটি ছোট VPS-এ সহজেই চলবে। তবে সব self-hosted service-এর ক্ষেত্রে এমন নয়। PhotoPrism ও Immich-এর তুলনায় photo library-গুলোর RAM-এর ন্যূনতম চাহিদা web app নয়, indexer নির্ধারণ করে। আসল সিদ্ধান্ত হলো instance-টি private হবে, অর্থাৎ শুধু আপনি এবং আপনার নিজের script এতে পৌঁছাতে পারবে, নাকি public হবে, অর্থাৎ Internet-এর যেকেউ এতে query পাঠাতে পারবে। এই সিদ্ধান্ত security setting পরিবর্তন করে। তাই কোনো command টাইপ করার আগে সিদ্ধান্ত নিন। ডিফল্টভাবে private রাখুন।

এটি চালানোর আরেকটি কারণ আছে। একটি SearXNG instance JSON ব্যবহার করে। ফলে আপনার লেখা যেকোনো script বা AI agent একটি নিজস্ব search API পায়। এতে কোনো key, প্রতি-query billing বা quota-সংক্রান্ত email লাগে না।

Docker Compose দিয়ে SearXNG ইনস্টল করুন

প্রকল্পটি একটি container image এবং একটি Compose file প্রকাশ করে। আগে থেকেই Docker Engine এবং Compose plugin ইনস্টল করা একটি নতুন Ubuntu 24.04 server-এ দুটিই pull করুন। 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 .env

Compose file-এ দুটি service সংজ্ঞায়িত করা আছে। core হলো SearXNG নিজেই, আর valkey হলো rate limiting এবং স্বল্পস্থায়ী state ব্যবহারের জন্য একটি in-memory data store। এটি ./core-config/-কে container-এর ভিতরে /etc/searxng/-এ mount করে। তাই আপনি যা configure করবেন, সবকিছু host-এর ওই একটি directory-তেই থাকবে।

এখন .env edit করুন। সরবরাহ করা example-এর প্রতিটি line comment করা আছে। এ কারণেই container-টি প্রতিটি address-এ port 8080-এ start হয়। এই তিনটি line uncomment করে মান নির্ধারণ করুন।

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1-ই গুরুত্বপূর্ণ। এটি published port-কে 127.0.0.1:8080:8080 করে, [::]:8080:8080 নয়। ফলে container-টি শুধু loopback address-এ উত্তর দেয় এবং Internet সরাসরি এতে পৌঁছাতে পারে না। এটি বাদ দিলে container start হওয়ার সঙ্গে সঙ্গেই exposed হয়ে যায়, কারণ published Docker port আপনার firewall rule-এর আগে কার্যকর হয়। এই ঝুঁকিটি পুরোপুরি পড়া উচিত: published Docker port ufw এড়িয়ে যায়

শেখার সময় SEARXNG_VERSION=latest ব্যবহার করা ঠিক আছে। গুরুত্বপূর্ণ server-এ tag নির্দিষ্ট করে দিন। July 2026 অনুযায়ী release tag-গুলো date ভিত্তিক এবং 2026.3.25-541c6c3cb-এর মতো দেখতে। তাই registry-তে পরিবর্তন হলে নয়, আপনি সিদ্ধান্ত নিলে pinned deployment upgrade হবে। Server-এ দীর্ঘ সময় চলবে এমন অন্য কিছুর ক্ষেত্রেও একই নিয়ম উপকারী। এই কারণেই self-hosted RustDesk relay-ও তার image tag নির্দিষ্ট করে: remote access service-এ unattended upgrade হলে সবচেয়ে অনুপযুক্ত সময়ে তার প্রভাব দেখা দিতে পারে।

settings.yml: গুরুত্বপূর্ণ অংশ

প্রথমবার start করার আগে core-config/settings.yml তৈরি করুন। use_default_settings: true SearXNG-কে আগে তার নিজস্ব shipped defaults load করতে এবং এরপর আপনার লেখা key-গুলোই apply করতে বলে। তাই file-টি ছোট থাকে এবং নতুন option যোগ করা upgrade-এর পরেও এটি কার্যকর থাকে।

আগে secret generate করুন, কারণ value-টি সরাসরি 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 session ও token data-তে sign করে। shipped default হলো literal string ultrasecretkey। এটি রেখে দিলে সেই default জানা যে কেউ ওই token forge করতে পারে। একবার এটি replace করুন, তারপর আর পরিবর্তন করবেন না। পরে পরিবর্তন করলে সংরক্ষিত সব preference মুছে যাবে।

base_url-এ trailing slash-সহ public HTTPS address দিতে হবে। SearXNG rendered link-এ এই address লেখে। এটিকে localhost-এ রেখে দিলে remote browser-এ "next page" link পাঠকের নিজের machine-এ নির্দেশ করবে এবং কাজ করবে না।

formats web endpoint কোন output type তৈরি করবে তা নির্ধারণ করে। json default list-এ নেই। তাই এটি যোগ না করা পর্যন্ত JSON request 403 ফেরত দেবে। image_proxy: true result thumbnail আপনার server-এর মাধ্যমে পাঠায়। ফলে image host করা site-গুলো আপনার visitor-দের address দেখতে পায় না।

valkey.url hostname হিসেবে valkey ব্যবহার করে, কারণ Compose file-এ এটিই service name। Compose উভয় container-কে একই network-এ রাখে, যেখানে service name resolve হয়। এটিকে localhost-এ point করলে limiter ব্যর্থ হবে, কারণ core container-এর ভেতরে localhost বলতে ওই container-কেই বোঝায়।

secret একটি plain file-এ থাকে। তাই file-টির বদলে এর চারপাশের directory সুরক্ষিত করুন। chmod 750 /opt/searxng অন্য host user-দের প্রবেশ বন্ধ রাখে। core-config/settings.yml-কে mode 600 করা উচিত নয়। Container নিজস্ব unprivileged user হিসেবে চলে, এবং যে file এটি read করতে পারে না সেটির কারণে SearXNG সম্পূর্ণভাবে start হতে ব্যর্থ হবে।

Stack start করুন এবং এটি পরীক্ষা করুন।

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

docker compose ps-এ উভয় container-এর state running দেখা উচিত। curl-এর response HTTP/1.1 200 OK হওয়া উচিত। কোনো response না পেলে docker compose logs core পড়ুন। settings.yml-এ YAML-এর ভুল থাকলে সেখানে সাধারণত line উল্লেখ করা parse error দেখা যায়।

TLS-সহ nginx-এর পেছনে চালান

Container-টি শুধু loopback-এ listen করে। তাই nginx-এর মাধ্যমে এটিকে পৌঁছানো যায় এবং 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.com

Reload করার আগে nginx -t, syntax is ok এবং test is successful প্রিন্ট করে। Certbot একই file নতুন করে লিখে certificate-সহ 443 port-এ listen করায় এবং port 80 থেকে redirect যোগ করে। search.example.com-এর DNS record আগে থেকেই এই server-এ নির্দেশ করতে হবে, কারণ certificate authority HTTP-এর মাধ্যমে একটি file fetch করে ownership যাচাই করে। Renewal-সহ সম্পূর্ণ নির্দেশিকা Ubuntu 24.04-এর জন্য Certbot এবং nginx নির্দেশিকায় রয়েছে।

এই দুই forwarding header শুধু দেখানোর জন্য নয়। X-Forwarded-For এবং X-Real-IP না থাকলে SearXNG-এ আসা প্রতিটি request proxy address বহন করে। ফলে rate limiter মনে করে একজন client-ই সব traffic পাঠাচ্ছে এবং visitors-দের আলাদা করতে পারে না।

কেন script এবং agent একটি JSON search API চায়

json-কে formats-এ ব্যবহার করলে page render করা একই endpoint structured data-ও ফেরত দেয়।

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

আপনি একটি results array-সহ object পান। এর প্রতিটি entry-তে url, title, content এবং ফলাফল সরবরাহকারী engine থাকে। এর সঙ্গে answers, infoboxes এবং suggestions-ও থাকে। এগুলো একটি summariser, link checker বা research loop-এ দেওয়ার জন্য যথেষ্ট। এই ফলাফলগুলো language model-এ পাঠানো যতটা সহজ মনে হয়, আসলে তার চেয়ে বড় পদক্ষেপ। কারণ search result হলো untrusted text, যার মধ্যে নিজস্ব instruction থাকতে পারে। আপনার SearXNG instance-এ AI agent নির্দেশ করা-তে এই বিষয়টি বিস্তারিতভাবে ব্যাখ্যা করা হয়েছে।

Agent-ভিত্তিক যেকোনো কাজের ক্ষেত্রে এটি গুরুত্বপূর্ণ। একটি language model-এর training cutoff থাকে। তাই বর্তমান সময়ের প্রশ্নের উত্তর দিতে তার live search প্রয়োজন। অন্যদিকে, commercial search API প্রতি query-র জন্য charge করে এবং rate limit কঠোরভাবে প্রয়োগ করে। আপনি ইতিমধ্যে যার জন্য অর্থ দিচ্ছেন, সেই server-এ একটি local instance চালাতে মাত্র একটি container লাগে। Query-গুলোও server-এর বাইরে যায় না। কোনো model-এ tool যুক্ত করলে একই যুক্তিতে VPS-এ MCP server চালানো প্রাসঙ্গিক হয়। সাধারণত search tool-ই মানুষ প্রথমে যুক্ত করে।

API ব্যবহারের জন্য দুটি নিয়ম মানুন। Instance-টি private রাখুন। API side-কে loopback address বা private network-এ bind করুন, যাতে কেবল আপনার নিজস্ব host-গুলো এতে পৌঁছাতে পারে। এরপর ধীরে ধীরে query পাঠান। SearXNG আপনার request প্রকৃত search engine-গুলোতে forward করে। তাই প্রতি সেকেন্ডে একশোটি query চালানো script আপনার server-কে block করার জন্য Google-কে অনুরোধ করার মতো।

লিমিটার, এবং public instance-এর ক্ষেত্রে কী পরিবর্তন হবে

লিমিটার হলো SearXNG-এর bot প্রতিরোধ ব্যবস্থা। এটি request header, address এবং request rate পর্যবেক্ষণ করে এবং automated traffic-এর মতো দেখালে সেই traffic বাতিল করে। এই state সংরক্ষণের জন্য এর Valkey প্রয়োজন। তাই Compose file-এ Valkey অন্তর্ভুক্ত থাকে।

Private instance-এ limiter: false রাখুন। আপনার নিজের script স্বভাবতই automated traffic, তাই limiter ঠিক সেই JSON call-গুলো block করবে, যেগুলোর জন্য আপনি instance তৈরি করেছেন। এর পরিবর্তে access control reverse proxy-এর কাজ: nginx location-এ একটি allowdeny জোড়া, HTTP basic authentication, অথবা এমন firewall যা শুধু আপনার অন্য server-গুলোকে অনুমতি দেয়। Network পরিবর্তন করে এমন laptop থেকে private instance-এ পৌঁছাতে হলে এর সামনে একটি v3 onion address বসানো চতুর্থ বিকল্প। কারণ Tor নতুন করে Internet-এ কিছু expose না করেই একই loopback port-এ সংযোগ করতে পারে।

অন্যদের জন্য instance publish করলে দুটি switch-ই চালু করুন।

server:
  limiter: true
  public_instance: true

আরও সূক্ষ্ম নিয়ন্ত্রণ core-config/limiter.toml-এ থাকে, যা container /etc/searxng/limiter.toml থেকে পড়ে। শুধু যে key-গুলো পরিবর্তন করতে চান, সেগুলোই লিখুন। Proxy-এর পেছনে থাকলে proxy ঘোষণা করতেই হবে। তা না হলে limiter আপনার nginx address-কে একমাত্র abusive client হিসেবে ধরে নেবে।

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

[botdetection.ip_limit]
link_token = true

link_token = true SearXNG-কে এমন একটি token দিতে বাধ্য করে, যা শুধু প্রকৃত browser session fetch করবে। এতে অধিকাংশ সাধারণ scraper বন্ধ হয়। Public instance চালু করার কয়েক দিনের মধ্যেই scraper আসবে বলে ধরে নিন। Engine error-এর জন্যও প্রস্তুত থাকুন। আপনি যত বেশি traffic forward করবেন, upstream engine-গুলো তত দ্রুত আপনার server address-এ CAPTCHA পাঠানো শুরু করবে। Public SearXNG instance পরিচালনা করা চলমান কাজ। Private instance-এর ক্ষেত্রে তা নয়। তাই 2026 সালে self-host করার মতো গুরুত্বপূর্ণ বিষয়গুলোর সংক্ষিপ্ত তালিকায় এটি সাধারণত থাকে। ওই তালিকার প্রতিটি বিষয় অবশ্য infrastructure নয়: Jellyfin library-কে হাঁটাচলা করা 90s rental store হিসেবে পুনর্নির্মাণ করা একই nginx block-এর পেছনে থাকা একই container, শুধু workflow-এর বদলে একটি সন্ধ্যার দিকে নির্দেশ করে।

অনুসন্ধানে কোনো ফলাফল না আসার কারণ

আপনার instance-এ /stats খুলুন। এখানে প্রতিটি engine-এর error rate এবং response time তালিকাভুক্ত থাকে। ফলাফল কম মনে হলে এটিই প্রথমে পরীক্ষা করুন।

"Access denied" বা "CAPTCHA" ত্রুটি দেখানো কোনো engine আপনার server address ব্লক করেছে। Data centre range-এর address-এর ক্ষেত্রে এটি সাধারণ ঘটনা, কারণ search engine-গুলো ধরে নেয় যে এগুলো scraper-এর। এরপর SearXNG ব্যর্থ engine-টিতে বারবার retry না করে নির্দিষ্ট সময়ের জন্য সেটিকে suspend করে। ফলে একটি ব্লক হওয়া engine নীরবে আপনার ফলাফল থেকে বাদ পড়ে। এটি settings.yml-এ disable করুন, অথবা এই ঘাটতি মেনে নিন। তবে কেবল এই দুটি পদক্ষেপই একমাত্র বিকল্প নয়, কারণ কিছু CAPTCHA block-এর এমন সমাধান আছে যা restart-এর পরও কার্যকর থাকে। বাকি engine-গুলো উত্তর দিতে থাকে। 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 ok

এই পরীক্ষা ব্যর্থ হওয়া শুরু করলে আপনার system-এর কোনো অংশ আপনাকে জানাবে না। তাই cron থেকে এটি চালান এবং ফলাফল কমে যাওয়া টের পাওয়ার অপেক্ষা না করে আপনার নিজের ntfy server থেকে আপনার phone-এ alert পাঠান

FAQ

SearXNG কি আমার অনুসন্ধানকে anonymous করে?

আপনি যে engine-গুলিতে অনুসন্ধান পাঠান, তাদের কাছ থেকে এটি আপনার পরিচয় আড়াল করে। কারণ তারা আপনার browser-এর বদলে আপনার server-কে অনুরোধ পাঠাতে দেখে। তবে এটি আপনার server-এর কাছ থেকে query আড়াল করে না। একইভাবে, engine-গুলোর কাছ থেকেও আপনার server আড়াল করে না। একটি single-user instance-এ ওই address থেকে আসা সব traffic আপনার হয়। তাই address-টিই identifier হয়ে যায়। আপনার browser এবং instance-এর মধ্যকার traffic TLS certificate দ্বারা সুরক্ষিত থাকে। আপনার ISP, public instance-এর operator এবং engine-গুলোর দৃষ্টিতে এর প্রভাব কী, তা SearXNG আসলে কী আড়াল করে অংশে ব্যাখ্যা করা হয়েছে।

JSON request 403 Forbidden ফেরত দেয় কেন?

এর দুটি কারণ আছে, এবং দুটিই configuration-সংক্রান্ত। হয় settings.yml-এর search:-এর অধীনে থাকা formats list-এ json অনুপস্থিত। এটিই default state। অথবা limiter চালু আছে এবং আপনার script-কে bot হিসেবে শনাক্ত করেছে। প্রথমে format যোগ করুন। docker compose restart core দিয়ে restart করুন। তারপর আবার চেষ্টা করুন। তবুও ব্যর্থ হলে limiter: false সেট করুন এবং reverse proxy-তে access নিয়ন্ত্রণ করুন।

limiter বন্ধ রাখলে কি Valkey container প্রয়োজন?

এটি চালু রাখুন। SearXNG এটি ছাড়াও কাজ করে। তবে এটি ছাড়া পরে limiter চালু করা যাবে না। এছাড়া এটি অন্যান্য স্বল্পস্থায়ী state-ও সংরক্ষণ করে। Container-টি ছোট এবং শুধু cached data সংরক্ষণ করে। তাই এটি সরিয়ে খুব সামান্যই সাশ্রয় হবে। এর বিনিময়ে আপনি ভবিষ্যতে limiter চালু করার সুবিধা হারাবেন।

SearXNG কীভাবে update করব?

/opt/searxng-এ প্রথমে docker compose pull, তারপর docker compose up -d চালান। Image পরিবর্তিত হলে Compose সংশ্লিষ্ট container পুনরায় তৈরি করে। আপনার core-config/ directory অপরিবর্তিত থাকে। ফলে settings.yml টিকে থাকে। use_default_settings: true shipped defaults-এর ওপর আপনার key-গুলো merge করে। তাই upstream-এ যোগ হওয়া option-গুলো file নষ্ট না করে উপযুক্ত value নিয়ে যুক্ত হয়।

একাধিক ব্যক্তি কি একই instance ব্যবহার করতে পারেন?

হ্যাঁ। এই পরিস্থিতিতেই limiter চালু করে public_instance: true সেট করবেন। প্রত্যেক visitor-এর নিজের browser-এ preference সংরক্ষিত হয়। তাই account পরিচালনার প্রয়োজন নেই। Instance সবার জন্য উন্মুক্ত করার পর এক সপ্তাহ /stats monitor করুন। কারণ আপনি ফলাফল অনুপস্থিত দেখতে পাওয়ার অনেক আগেই upstream engine-গুলো আপনার server-এর request প্রত্যাখ্যান করা শুরু করতে পারে।