SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-10-21

איך להקים מנוע חיפוש פרטי עם SearXNG ו-Docker

למדו להריץ SearXNG על שרת VPS עם Docker Compose. המדריך כולל הגדרת settings.yml, ניהול limiter, הטמעת Nginx עם TLS ושימוש ב-API בפורמט JSON עבור הסקריפטים שלכם.

מה אתם בונים

אירוח עצמי של SearXNG מעניק לכם מנוע חיפוש פרטי שרץ על השרת שלכם. SearXNG הוא מנוע חיפוש משולב (metasearch): הוא מקבל את השאילתה שלכם, שולח אותה למנועים אחרים כמו Google, Bing, DuckDuckGo ו-Wikipedia, ואז מאחד את התוצאות המתקבלות לדף תוצאות אחד. לא נבנה פרופיל ולא מוגדר cookie למעקב, כיוון שהמכונה היחידה ששומרת את השאילתה שלכם היא שלכם. אם מצאתם מדריכים ישנים עבור פרויקט בשם Searx בלבד, זהו הפרויקט שממנו פוצל הנוכחי. הוא לא מתוחזק מאז ספטמבר 2023, כאשר המאגר שלו הכריז ש-Searx אינו מתוחזק עוד, וה-commit היחיד מאז, הערת תיעוד ממאי 2026, לא שינה זאת. לכן בדקו את המצב של שניהם לפני שתעקבו אחרי אחד מהם.

ה-stack קטן. שתי מכולות, קובץ הגדרות אחד, ו-reverse proxy אחד. הוא יחלוק VPS קטן בקלות, מה שלא נכון לכל שירות באירוח עצמי: ספריות התמונות שנשקלו ב-PhotoPrism מול Immich קובעות את רף ה-RAM שלהן לפי ה-indexer ולא לפי יישום ה-web. ההחלטה האמיתית היא האם המופע (instance) הוא פרטי, כלומר רק אתם והסקריפטים שלכם ניגשים אליו, או ציבורי, כלומר כל אחד באינטרנט יכול לבצע בו חיפוש. בחירה זו משנה את הגדרות האבטחה, לכן החליטו לפני שתקלידו דבר מה. ברירת המחדל היא פרטי.

יש סיבה שנייה להריץ מופע כזה. מופע SearXNG מדבר JSON, כך שכל סקריפט או סוכן AI שתכתבו יקבל API חיפוש שבבעלותכם, ללא מפתח, ללא חיוב לפי שאילתה וללא מכסות.

התקנת SearXNG באמצעות Docker Compose

הפרויקט מפיץ image של מכולה וקובץ Compose. משכו את שניהם לשרת Ubuntu 24.04 נקי שכבר מותקנים בו Docker Engine ותוסף ה-Compose. אם Docker חדש לכם, התחילו ב-יסודות Docker Compose ב-VPS וחזרו לכאן.

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 מגדיר שני שירותים. core הוא SearXNG עצמו, ו-valkey הוא מאגר נתונים בזיכרון המשמש להגבלת קצב (rate limiting) ולמצבים קצרי-טווח. הוא מבצע mount ל-./core-config/ בנתיב /etc/searxng/ בתוך המכולה, כך שכל מה שתגדירו יישמר בתיקייה אחת זו על המארח.

כעת ערכו את .env. כל שורה בדוגמה המופצת מוגדרת כהערה, וזו הסיבה שהמכולה עולה בפורט 8080 בכל כתובת. בטלו את ההערה והגדירו את שלושת הערכים הבאים.

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1 הוא החשוב מביניהם. הוא הופך את הפורט המפורסם ל-127.0.0.1:8080:8080 במקום ל-8080:8080 חשוף, ש-Docker מפרסם בכל כתובת, כך שהמכולה תענה רק בכתובת ה-loopback והאינטרנט לא יוכל להגיע אליה ישירות. דלגו על שלב זה והמכולה תיחשף ברגע שתעלה, כיוון שפורט Docker מפורסם מוזרק לפני חוקי ה-firewall שלכם. כדאי לקרוא את המלכודת הזו במלואה: פורטים מפורסמים של Docker עוקפים את ufw.

SEARXNG_VERSION=latest תקין כל עוד אתם לומדים. בשרת שחשוב לכם, קבעו גרסה (pin) ל-tag. נכון לאוקטובר 2026, ה-tags של הגרסאות מבוססים על תאריך ונראים כמו 2026.10.4-d48c4b555, כך שפריסה מקובעת משתדרגת כשאתם מחליטים, ולא כשה-registry משתנה מתחת לרגליכם. אותה משמעת משתלמת לכל שירות אחר בעל אורך חיים ארוך על השרת, וזו הסיבה ש-ממסר RustDesk בניהול עצמי מקבע גם הוא את ה-tags של ה-image שלו: שדרוג לא מבוקר של שירות גישה מרחוק עלול להשתבש ברגע הכי פחות מתאים.

settings.yml: החלקים החשובים

צרו את core-config/settings.yml לפני ההפעלה הראשונה. use_default_settings: true מורה ל-SearXNG לטעון את ברירות המחדל המובנות שלו ורק אז להחיל את המפתחות שכתבתם, כך שהקובץ נשאר קצר ושורד שדרוגים שמוסיפים אפשרויות חדשות.

צרו את ה-secret תחילה, כיוון שהערך מוזן ישירות לקובץ.

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. ברירת המחדל המובנית היא המחרוזת המילולית ultrasecretkey, והשארתה כפי שהיא מאפשרת לכל מי שמכיר את ברירת המחדל לזייף את ה-tokens הללו. החליפו אותה פעם אחת, ולאחר מכן אל תשנו אותה: שינוי מאוחר יותר יגרום לאובדן כל ההעדפות השמורות.

base_url חייב להיות כתובת ה-HTTPS הציבורית, עם לוכסן בסוף. זהו הערך ש-SearXNG כותב בתוך הקישורים שהוא מרנדר. השארתו מצביעה על localhost תגרום לקישור "הדף הבא" בדפדפן מרוחק להצביע על המחשב של הקורא ולהיכשל.

formats קובע אילו סוגי פלט יפיק ה-web endpoint. json אינו נמצא ברשימת ברירת המחדל, לכן בקשת JSON תחזיר שגיאת 403 עד שתוסיפו אותו. image_proxy: true מנתב תמונות ממוזערות של תוצאות דרך השרת שלכם, כך שהאתרים המארחים את התמונות הללו לעולם לא יראו את כתובות המבקרים שלכם.

ה-valkey.url משתמש ב-hostname valkey כיוון שזהו שם השירות בקובץ ה-Compose, ו-Compose מציב את שני ה-containers על רשת אחת שבה שמות שירותים ניתנים לפתרון (resolve). הצביעו עליו כ-localhost וה-limiter ייכשל, כיוון שבתוך ה-container של core, ה-localhost הוא ה-container עצמו.

ה-secret נמצא בקובץ טקסט פשוט, לכן הגנו גם על התיקייה שסביבו. chmod 750 /opt/searxng מונע ממשתמשים אחרים במארח גישה. ניתן גם להדק את core-config/settings.yml למצב 600 מבלי לשבור דבר: ה-entrypoint של ה-container הרשמי מתחיל כ-root, ועם FORCE_OWNERSHIP שנותר בברירת המחדל שלו true, הוא מעביר את תיקיית התצורה המעוגנת (mounted) למשתמש ה-searxng של ה-container לפני ש-SearXNG מתחיל, כך שהקובץ נשאר קריא עבורו. תופעת הלוואי מופיעה במארח: אותו שלב משנה את הבעלות על core-config/ ל-ID המשתמש של ה-container, לכן צפו לערוך את הקובץ עם sudo לאחר מכן.

הפעילו את ה-stack ובדקו אותו.

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

docker compose ps אמור להציג את שני ה-containers במצב running. ה-curl אמור להשיב HTTP/1.1 200 OK. אם הוא לא משיב דבר, קראו את docker compose logs core, כיוון ששגיאת YAML ב-settings.yml תופיע שם כשגיאת ניתוח (parse error) המציינת את מספר השורה.

הצבת השירות מאחורי nginx עם TLS

המכולה מאזינה ל-loopback בלבד, לכן nginx הוא הרכיב שהופך אותה לנגישה, והוא גם זה שמוסיף אבטחת שכבת תעבורה (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

nginx -t מדפיס את syntax is ok ואת test is successful לפני ביצוע ה-reload. הכלי Certbot משכתב את אותו הקובץ כדי להאזין בפורט 443 עם תעודה ומוסיף הפניה (redirect) מפורט 80. רשומת ה-DNS עבור search.example.com חייבת להצביע כבר עכשיו על שרת זה, כיוון שרשות התעודות מוודאת בעלות על ידי משיכת קובץ דרך HTTP. המדריך המלא, כולל חידוש תעודות, נמצא ב-מדריך Certbot ו-nginx עבור Ubuntu 24.04.

שני ה-headers של העברת התעבורה אינם קישוט. ללא X-Forwarded-For ו-X-Real-IP, כל בקשה שמגיעה ל-SearXNG נושאת את כתובת ה-proxy, כך שמגביל הקצב (rate limiter) רואה לקוח אחד שמייצר את כל התעבורה ואינו יכול להבדיל בין מבקרים שונים.

מדוע סקריפטים וסוכנים זקוקים ל-API חיפוש בפורמט JSON

בעזרת json ב-formats, אותו endpoint שמציג את הדף מחזיר גם נתונים מובנים.

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. זה מספיק כדי להזין כלי סיכום, בודק קישורים או לולאת מחקר. העברת התוצאות הללו למודל שפה היא צעד משמעותי יותר ממה שנראה לעין, שכן תוצאות חיפוש הן טקסט לא מהימן שעלול להכיל הוראות משלו, נושא שבו עוסק בהרחבה הפניית סוכן AI למופע SearXNG שלכם.

זה חשוב לכל מה שמוגדר כסוכן. למודל שפה יש תאריך ניתוק של נתוני אימון, לכן הוא זקוק לחיפוש חי כדי לענות על שאלות לגבי ההווה, בעוד ש-API של מנועי חיפוש מסחריים גובים תשלום לפי שאילתה ומטילים מגבלות קצב מחמירות. מופע מקומי עולה כמות של מכולה אחת על שרת שאתם כבר משלמים עליו, והשאילתות לעולם לא יוצאות ממנו. אם אתם מחברים כלים למודל, אותו היגיון מניע את הרצת שרתי MCP על גבי VPS, שם כלי חיפוש הוא בדרך כלל הראשון שאנשים מוסיפים.

שני כללים לשימוש ב-API. שמרו על המופע פרטי; הגדירו את צד ה-API להאזין לכתובת ה-loopback או לרשת פרטית ואפשרו רק למארחים שלכם לגשת אליו, בדומה לטיפול שנדרש עבור מעקב מיקום בשירות עצמי עבור ה-endpoint שאליו הטלפון שלכם מדווח על מיקומו. לאחר מכן, בצעו שאילתות במתינות. SearXNG מעביר את הבקשה שלכם למנועי חיפוש אמיתיים, כך שסקריפט שמריץ מאה שאילתות בשנייה גורם ל-Google לחסום את השרת שלכם.

המגביל (limiter), ומה משתנה במופע ציבורי

המגביל הוא מנגנון ההגנה של SearXNG מפני בוטים. הוא מנטר כותרות בקשות (request headers), כתובות וקצבי בקשות, וחוסם תעבורה שנראית אוטומטית. הוא זקוק ל־Valkey כדי לשמור את המצב הזה, וזו הסיבה שקובץ ה-Compose כולל אותו.

במופע פרטי, השאירו את limiter: false. הסקריפטים שלכם הם תעבורה אוטומטית מעצם הגדרתם, ולכן המגביל יחסום בדיוק את קריאות ה-JSON שעבורן הקמתם את המופע. בקרת גישה היא תפקידו של ה-reverse proxy במקום זאת: זוג allow ו-deny בתוך ה-location של nginx, אימות HTTP בסיסי, או firewall שמאפשר גישה רק לשרתים האחרים שלכם. אם אתם צריכים לגשת למופע פרטי ממחשב נייד שעובר בין רשתות, הצבת כתובת v3 onion לפניו היא אפשרות רביעית, כיוון ש-tor מתחבר לאותו פורט loopback מבלי לחשוף דבר חדש לאינטרנט.

אם אתם מפרסמים את המופע עבור אנשים אחרים, הפעילו את שני המתגים.

server:
  limiter: true
  public_instance: true

שליטה עדינה יותר נמצאת ב-core-config/limiter.toml, שהמכולה קוראת ב-/etc/searxng/limiter.toml. עליכם לכתוב רק את המפתחות שברצונכם לשנות. מאחורי proxy עליכם להצהיר על ה-proxy, אחרת המגביל יתייחס לכתובת ה-nginx שלכם כלקוח הפוגעני היחיד.

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

[botdetection.ip_limit]
link_token = true

link_token = true גורם ל-SearXNG להנפיק אסימון (token) שרק סשן דפדפן אמיתי ימשוך, מה שעוצר את רוב ה-scrapers הפשוטים. צפו לכך שמופע ציבורי ימשוך אותם בתוך ימים. צפו גם לשגיאות מנועים, כיוון שככל שתעבירו יותר תעבורה, כך מנועי החיפוש במעלה הזרם יתחילו להחזיר CAPTCHAs לכתובת השרת שלכם מהר יותר. מופע SearXNG ציבורי הוא עבודה מתמשכת. מופע פרטי אינו כזה, וזו הסיבה שהוא נמצא ברוב הרשימות הקצרות של דברים שכדאי לארח באופן עצמי ב-2026. לא כל פריט ברשימות האלה הוא תשתית: בנייה מחדש של ספריית Jellyfin כחנות השכרת סרטים משנות ה-90 שניתן להסתובב בה היא אותה מכולה מאחורי אותו בלוק nginx, המופנית לערב של פנאי במקום לזרימת עבודה.

מדוע חיפושים אינם מחזירים תוצאות

פתחו את /stats במופע שלכם. הוא מציג את כל מנועי החיפוש עם שיעור השגיאות וזמן התגובה שלהם, וזהו המקום הראשון לבדוק בו כאשר נראה שהתוצאות דלות.

מנוע שמופיע עם שגיאות "Access denied" או "CAPTCHA" חסם את כתובת השרת שלכם. זה נפוץ עבור כתובות בטווחים של מרכזי נתונים (data centers), כיוון שמנועי חיפוש מניחים שהן שייכות לבוטים של איסוף נתונים (scrapers). לאחר מכן, SearXNG משעה את המנוע שנכשל לפרק זמן מסוים במקום לנסות שוב, כך שמנוע חסום אחד פשוט נעלם מהתוצאות שלכם בשקט. השביתו אותו ב-settings.yml או השלימו עם אובדן התוצאות ממנו. אלו אינן שתי האפשרויות היחידות, כיוון ש-לחלק מחסימות ה-CAPTCHA יש פתרון שנשמר גם לאחר אתחול. המנועים הנותרים עדיין ישיבו. שגיאת 429 היא מקרה דו-משמעי, כיוון שהיא יכולה להגיע ממגביל התעבורה (limiter) שלכם או ממנוע חיצוני שמסרב לשרת שלכם, ו-שורת הלוג תבהיר לכם באיזה משני המקרים מדובר לפני שתתחילו לשנות הגדרות.

אם כל המנועים נכשלים בבת אחת, למכולה אין פתרון שמות (name resolution) תקין כלפי חוץ או שאין לה נתיב לאינטרנט. בדקו זאת מתוך המכולה.

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

שום דבר בשרת לא יתריע בפניכם כאשר הבדיקה הזו מתחילה להיכשל, לכן הריצו אותה מתוך cron ואפשרו לכשל לשלוח התראה לטלפון שלכם משרת ה-ntfy שלכם במקום להמתין עד שתבחינו שהתוצאות הפכו לדלות.

FAQ

האם SearXNG הופך את החיפושים שלי לאנונימיים?

הוא מסתיר את זהותך ממנועי החיפוש שאליהם הוא פונה, כיוון שהם רואים את השרת שלך מבצע את הבקשה במקום את הדפדפן שלך. הוא אינו מסתיר את השאילתה מהשרת שלך, והוא אינו מסתיר את השרת שלך מהם. במופע (instance) של משתמש יחיד, כל התעבורה מכתובת זו היא שלך, ולכן הכתובת עצמה הופכת למזהה. התעבורה בין הדפדפן שלך למופע שלך מאובטחת באמצעות תעודת TLS. המשמעות של מצב זה עבור ספק האינטרנט שלך, מפעיל המופע הציבורי ומנועי החיפוש עצמם מפורטת ב-מה SearXNG באמת מסתיר.

מדוע בקשת JSON מחזירה שגיאת 403 Forbidden?

יש לכך שתי סיבות, ושתיהן קשורות לתצורה. או ש-json חסר מרשימת formats תחת search: בקובץ settings.yml, שזהו מצב ברירת המחדל, או שמגביל התעבורה (limiter) פעיל וסיווג את הסקריפט שלך כבוט. הוסיפו את הפורמט תחילה, בצעו הפעלה מחדש עם docker compose restart core, ונסו שוב. אם השגיאה נמשכת, הגדירו את limiter: false ובצעו בקרת גישה ב-reverse proxy במקום זאת.

האם אני זקוק למכולת Valkey אם אני משאיר את המגביל כבוי?

השאירו אותה פועלת. SearXNG עובד בלעדיה, אך לא ניתן יהיה להפעיל את המגביל מאוחר יותר בלעדיה, והיא גם מחזיקה מצבים קצרי-טווח אחרים. המכולה קטנה ומאחסנת רק נתונים במטמון, לכן הסרתה חוסכת מעט מאוד משאבים ועולה באובדן האפשרות להשתמש במגביל.

כיצד מעדכנים את SearXNG?

הריצו את docker compose pull ולאחר מכן את docker compose up -d בתוך /opt/searxng. הכלי Compose יוצר מחדש כל מכולה שהתמונה (image) שלה השתנתה ומשאיר את ספריית ה-core-config/ שלכם ללא שינוי, כך ש-settings.yml נשמר. מכיוון ש-use_default_settings: true ממזג את המפתחות שלכם מעל ברירות המחדל שמגיעות עם התוכנה, אפשרויות שנוספו בעדכונים מגיעות עם ערכים הגיוניים במקום לשבור את הקובץ.

האם כמה אנשים יכולים לחלוק מופע אחד?

כן, וזהו המקרה שבו כדאי להפעיל את המגביל ולהגדיר את public_instance: true. העדפות נשמרות בדפדפן של כל מבקר, לכן אין צורך לנהל חשבונות משתמש. עקבו אחר /stats במשך שבוע לאחר פתיחת הגישה, כיוון שמנועי חיפוש חיצוניים מתחילים לחסום את השרת שלכם זמן רב לפני שתבחינו בחוסר בתוצאות.

האם המאמר הזה היה מועיל?