SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-09-05

自行代管 SearXNG:用 Docker Compose 建立私有搜尋

在自己的 VPS 上執行 SearXNG,涵蓋 settings.yml、limiter、nginx TLS 與 JSON 搜尋 API,讓自有指令碼不需 API key 或查詢配額即可呼叫。

你要建置的內容

自行代管 SearXNG 可提供在自有伺服器上運作的私有搜尋引擎。SearXNG 是中繼搜尋引擎:它會接收你的查詢,向 Google、Bing、DuckDuckGo 和 Wikipedia 等其他搜尋引擎發出請求,再將回傳結果合併到同一個結果頁面。系統不會建立使用者檔案,也不會設定追蹤 cookie,因為唯一保存查詢內容的機器就是你的伺服器。如果你找到只稱為 Searx 的舊指南,這就是 SearXNG 分支出來的專案,而且自 2023 年起就沒有新的 commit,因此請先確認兩者目前的狀態,再決定要依照哪一份指南操作

整個堆疊很精簡。只需要兩個容器、一個設定檔和一個反向代理。它可以穩定地與其他服務共用一台小型 VPS,但並非所有自架服務都如此:PhotoPrism 與 Immich 的比較中提到的相片資料庫,其最低 RAM 需求取決於索引器,而不是 Web 應用程式。真正需要決定的是執行個體要設為私有,亦即只有你和自己的指令碼能夠存取;還是設為公開,亦即網際網路上的任何人都能發出查詢。這項選擇會影響安全性設定,因此請在輸入任何內容前先決定。預設應選擇私有模式。

執行自己的 SearXNG 還有第二個理由。SearXNG 執行個體支援 JSON,因此你撰寫的任何指令碼或 AI agent 都能使用由你管理的搜尋 API,不需要 key、不會按查詢次數計費,也不會收到配額通知郵件。

使用 Docker Compose 安裝 SearXNG

此專案提供 container image 與 Compose 檔案。請將兩者下載到已安裝 Docker Engine 與 Compose plugin 的全新 Ubuntu 24.04 伺服器。如果你不熟悉 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 檔案定義了兩個服務。core 是 SearXNG 本身,valkey 是用於速率限制及短期狀態的記憶體內資料儲存。它會將 ./core-config/ 掛載到 container 內的 /etc/searxng/,因此你設定的所有內容都位於主機上的同一個目錄。

現在編輯 .env。隨附範例中的每一行都被註解,因此 container 會在所有位址上的 8080 port 啟動。取消註解並設定以下三項。

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1 是重要設定。它會讓發布的 port 使用 127.0.0.1:8080:8080,而不是 [::]:8080:8080,因此 container 只會在 loopback 位址上回應,網際網路無法直接連線。若略過此設定,container 一啟動就會暴露,因為已發布的 Docker port 會插入在防火牆規則之前。這個陷阱值得完整閱讀:已發布的 Docker port 會繞過 ufw

學習期間使用 SEARXNG_VERSION=latest 沒有問題。在重要的伺服器上,請固定 tag。截至 2026 年 7 月,release tag 以日期為基礎,格式類似 2026.3.25-541c6c3cb。如此一來,部署會在你決定時升級,而不是在 registry 變更時自行升級。對伺服器上其他需要長期運作的服務,採用相同的管理方式也很有幫助。因此,自架 RustDesk relay 也會固定 image tag:遠端存取服務若在無人管理時升級,往往會在最不適合的時刻暴露變更。

settings.yml:需要注意的部分

在第一次啟動前建立 core-config/settings.ymluse_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 會簽署工作階段與 token 資料。隨附的預設值是字串 ultrasecretkey;如果保留不變,任何知道這個預設值的人都能偽造這些 token。只替換一次,之後不要再變更:日後修改會丟失所有已儲存的偏好設定。

base_url 必須是公開的 HTTPS 位址,並包含結尾的斜線。SearXNG 會將它寫入產生的連結中。如果仍指向 localhost,遠端瀏覽器中的「下一頁」連結會指向讀者自己的電腦,因而失效。

formats 會決定 Web endpoint 可產生的輸出類型。json 不在預設清單中,因此加入它之前,JSON 請求會回傳 403。image_proxy: true 會透過您的伺服器轉送結果縮圖,因此託管這些圖片的網站不會看到訪客的位址。

valkey.url 使用主機名稱 valkey,因為這是 Compose 檔案中的服務名稱,而 Compose 會將兩個容器放在同一個 network,讓服務名稱可以解析。若將它指向 localhost,限流器會失效,因為在 core 容器內,localhost 指的是該容器本身。

secret 位於純文字檔案中,因此應保護包含它的目錄,而不是只保護檔案本身。chmod 750 /opt/searxng 可阻止主機上的其他使用者存取。不要將 core-config/settings.yml 的模式設為 600:容器會以自身的非特權使用者執行,而該使用者若無法讀取檔案,SearXNG 就完全無法啟動。

啟動 stack 並檢查狀態。

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

docker compose ps 應顯示兩個容器的狀態都是 runningcurl 應回應 HTTP/1.1 200 OK。如果沒有任何回應,請查看 docker compose logs core,因為 settings.yml 中的 YAML 錯誤會在其中顯示為指出行號的解析錯誤。

使用 nginx 搭配 TLS

容器只監聽 loopback,因此必須透過 nginx 讓外部連線;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 oktest is successful。Certbot 會改寫同一個檔案,讓服務使用憑證監聽 443,並將 80 連接埠重新導向至 HTTPS。search.example.com 的 DNS 記錄必須已指向這台伺服器,因為憑證授權單位會透過 HTTP 擷取檔案,以驗證網域擁有權。完整操作流程(包括續期)請參閱 Ubuntu 24.04 的 Certbot 與 nginx 指南

這兩個轉送標頭並非裝飾用途。若沒有 X-Forwarded-ForX-Real-IP,所有抵達 SearXNG 的請求都會帶有代理伺服器的位址,因此速率限制器會將所有流量視為由同一個用戶端發出,無法區分不同訪客。

為什麼指令碼與代理程式需要 JSON 搜尋 API

搭配 jsonformats 後,負責呈現頁面的相同端點也會回傳結構化資料。

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

您會取得一個物件,其中包含 results 陣列。每個項目都會帶有 urltitlecontent 及提供結果的搜尋引擎,以及 answersinfoboxessuggestions。這些資料足以提供給摘要工具、連結檢查器或研究迴圈使用。將這些結果交給語言模型比表面上更複雜,因為搜尋結果是不受信任的文字,可能自行攜帶指令;讓 AI 代理程式連線至您的 SearXNG 執行個體會詳細處理這個問題。

這對任何代理程式型工作流程都很重要。語言模型有訓練資料截止時間,因此需要即時搜尋才能回答目前的問題;商業搜尋 API 則會按查詢次數收費,並嚴格限制速率。本機執行個體只需佔用您已付費伺服器上的一個容器,查詢也不會離開該伺服器。如果您要將工具接入模型,同樣的考量也適用於在 VPS 上執行 MCP 伺服器;搜尋工具通常是人們加入的第一個工具。

使用 API 時請遵守兩項規則。請將執行個體設為私有:將 API 端繫結至 loopback 位址或私有網路,只允許您自己的主機存取。接著以適當頻率發出查詢。SearXNG 會將您的要求轉送至實際的搜尋引擎,因此每秒執行一百次查詢的指令碼等於要求 Google 封鎖您的伺服器。

限制器,以及公開執行個體的變更

限制器是 SearXNG 的機器人防禦機制。它會監控要求標頭、來源位址與要求速率,並捨棄看起來由自動化程式產生的網路流量。它需要 Valkey 儲存這些狀態,因此 Compose 檔案會一併部署 Valkey。

在私有執行個體上,請保留 limiter: false。你自己的指令碼本來就是自動化流量,因此限制器會封鎖你部署此執行個體所需的 JSON 呼叫。存取控制應由反向代理處理,例如 nginx location 中的 allowdeny 組合、HTTP 基本驗證,或只允許其他伺服器連入的防火牆。如果你需要從會在不同網路間切換的筆電連線到私有執行個體,也可以在其前方設定 v3 onion 位址,因為 Tor 會連線到相同的 loopback 埠,不會向網際網路暴露新的項目。

如果你要讓其他人使用此執行個體,請同時開啟這兩個開關。

server:
  limiter: true
  public_instance: true

更細緻的控制位於 core-config/limiter.toml,容器會從 /etc/searxng/limiter.toml 讀取設定。只需寫入要變更的鍵值。若服務位於代理伺服器後方,必須宣告該代理伺服器,否則限制器會將 nginx 位址視為唯一的濫用用戶端。

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

[botdetection.ip_limit]
link_token = true

link_token = true 會讓 SearXNG 發出只有真實瀏覽器工作階段才會取得的 token,能阻擋大多數簡單的擷取程式。預期公開執行個體在幾天內就會吸引這些程式。也要預期引擎錯誤,因為你轉送的流量越多,上游引擎就越快開始對你的伺服器位址回傳 CAPTCHA。維護公開 SearXNG 執行個體是持續性的工作。私有執行個體則不必如此,因此它會出現在大多數值得在 2026 年自行託管的項目短名單中。這些名單上的項目也不全都是基礎架構:將 Jellyfin 媒體庫重建成可步行瀏覽的 90 年代出租店,同樣只是位於相同 nginx 區塊後方的單一容器,只是其用途是營造夜晚的氛圍,而不是支援工作流程。

搜尋沒有傳回任何結果

在您的執行個體上開啟 /stats。其中列出每個引擎的錯誤率與回應時間。當搜尋結果過少時,應先查看這裡。

顯示「Access denied」或「CAPTCHA」錯誤的引擎,表示已封鎖您的伺服器位址。資料中心網段中的位址很常發生這種情況,因為搜尋引擎會推測這些位址屬於爬蟲。SearXNG 隨後會暫停發生錯誤的引擎一段時間,而不是重試。因此,某個遭封鎖的引擎會在不明顯的情況下停止提供結果。請在 settings.yml 中停用該引擎,或接受結果減少的情況。不過,處理方式不只有這兩種,因為部分 CAPTCHA 封鎖有可在重新啟動後持續生效的修正方式。其餘引擎仍會回應。429 是較難判斷的情況,因為它可能來自您自行設定的速率限制器,也可能來自拒絕您伺服器的上游引擎;在開始修改設定前,日誌行會指出您遇到的是哪一種情況

如果所有引擎同時失敗,表示容器沒有可用的對外名稱解析,或沒有通往網際網路的路由。請從容器內進行測試。

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

主機上沒有任何機制會通知您這項檢查何時開始失敗。因此,請從 cron 執行這項檢查,並讓失敗狀況透過您自己的 ntfy server 將警示推送到手機,不要等到發現搜尋結果變少時才處理。

FAQ

SearXNG 會讓我的搜尋匿名嗎?

它會對所查詢的搜尋引擎隱藏你的身分,因為搜尋引擎看到的是你的伺服器發出請求,而不是你的瀏覽器。它不會對你的伺服器隱藏查詢內容,也不會對搜尋引擎隱藏你的伺服器。在單一使用者的執行個體中,來自該位址的所有流量都屬於你,因此該位址本身會成為識別資訊。你的瀏覽器與執行個體之間的流量受 TLS 憑證保護。這對 ISP、公共執行個體的營運者及搜尋引擎本身代表什麼影響,詳見SearXNG 實際隱藏的內容

為什麼 JSON 請求會回傳 403 Forbidden?

原因有兩個,而且都與設定有關。第一種情況是 json 未列在 settings.ymlsearch: 底下的 formats 清單內,這是預設狀態。第二種情況是 limiter 已啟用,並將你的 script 判定為 bot。先加入該格式,再以 docker compose restart core 重新啟動,然後重試。如果仍然失敗,請設定 limiter: false,改由 reverse proxy 控制存取。

如果我關閉 limiter,還需要 Valkey container 嗎?

請讓它持續執行。SearXNG 不依賴它也能運作,但之後若沒有它就無法啟用 limiter,而且它也會保存其他短期狀態。此 container 很小,只會儲存快取資料,因此移除它節省的資源很少,卻會失去日後啟用 limiter 的選項。

如何更新 SearXNG?

/opt/searxng 中執行 docker compose pull,然後執行 docker compose up -d。Compose 會重新建立映像檔已變更的 container,並保留你的 core-config/ 目錄不變,因此 settings.yml 仍會保留。由於 use_default_settings: true 會將你的金鑰合併到隨附的預設值中,上游新增的選項會自動取得合理值,不會造成設定檔失效。

多人可以共用同一個執行個體嗎?

可以,而這正是應啟用 limiter 並設定 public_instance: true 的情況。偏好設定會儲存在每位訪客自己的瀏覽器中,因此不需要管理帳號。開放使用後,請持續監控 /stats 一週,因為上游搜尋引擎通常會在你注意到搜尋結果缺漏之前,就開始拒絕你的伺服器。