SSD Nodes Learn RAM 8GB — $66/ปี
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-08-01

ติดตั้ง SearXNG แบบส่วนตัวด้วย Docker Compose

โฮสต์ SearXNG บน VPS ของคุณด้วย Docker Compose พร้อม settings.yml, limiter, nginx และ TLS รวมถึง JSON search API สำหรับสคริปต์และ AI agent

สิ่งที่คุณกำลังสร้าง

การโฮสต์ SearXNG ด้วยตนเองจะทำให้คุณมีเครื่องมือค้นหาส่วนตัวที่ทำงานบนเซิร์ฟเวอร์ของคุณเอง SearXNG เป็นเครื่องมือค้นหาแบบเมตา โดยรับคำค้นหาของคุณ ส่งคำค้นหาไปยังเครื่องมือค้นหาอื่น เช่น Google, Bing, DuckDuckGo และ Wikipedia จากนั้นรวมผลลัพธ์ที่ได้รับกลับมาเป็นหน้าผลการค้นหาเดียว ระบบจะไม่สร้างโปรไฟล์และไม่ตั้งค่า tracking cookie เพราะมีเพียงเครื่องของคุณเท่านั้นที่เก็บคำค้นหาของคุณ

สแตกนี้มีขนาดเล็ก ประกอบด้วย container 2 รายการ ไฟล์การตั้งค่า 1 ไฟล์ และ reverse proxy 1 รายการ การตัดสินใจที่สำคัญคือจะตั้งค่าอินสแตนซ์ให้เป็นส่วนตัว ซึ่งหมายถึงมีเพียงคุณและสคริปต์ของคุณเองที่เข้าถึงได้ หรือเป็นสาธารณะ ซึ่งหมายถึงทุกคนบนอินเทอร์เน็ตสามารถส่งคำค้นหาได้ ตัวเลือกนี้จะเปลี่ยนการตั้งค่าความปลอดภัย ดังนั้นให้ตัดสินใจก่อนเริ่มพิมพ์คำสั่งใดๆ ค่าเริ่มต้นคือส่วนตัว

ยังมีเหตุผลอีกประการหนึ่งในการเรียกใช้ SearXNG อินสแตนซ์ SearXNG รองรับ JSON ดังนั้นสคริปต์หรือ AI agent ที่คุณเขียนจะมี search API ที่คุณควบคุมเอง โดยไม่ต้องใช้ key ไม่มีค่าบริการต่อคำค้นหา และไม่มีอีเมลแจ้งเตือนโควตา

ติดตั้ง SearXNG ด้วย Docker Compose

โครงการนี้เผยแพร่อิมเมจคอนเทนเนอร์และไฟล์ 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 กำหนดบริการไว้ 2 รายการ core คือ SearXNG และ valkey คือที่เก็บข้อมูลในหน่วยความจำที่ใช้จำกัดอัตราการใช้งานและเก็บสถานะชั่วคราว ไฟล์นี้เมานต์ ./core-config/ ไปยัง /etc/searxng/ ภายในคอนเทนเนอร์ ดังนั้นค่าที่คุณกำหนดทั้งหมดจะอยู่ในไดเรกทอรีเดียวกันบนโฮสต์

ตอนนี้แก้ไข .env ทุกบรรทัดในตัวอย่างที่เผยแพร่จะถูกใส่คอมเมนต์ไว้ ซึ่งเป็นสาเหตุให้คอนเทนเนอร์เริ่มทำงานที่พอร์ต 8080 บนทุกแอดเดรส ให้ยกเลิกคอมเมนต์และกำหนดค่า 3 รายการนี้

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 ดังนั้นคอนเทนเนอร์จะตอบสนองเฉพาะที่แอดเดรส loopback และอินเทอร์เน็ตจะไม่สามารถเข้าถึงโดยตรงได้ หากข้ามขั้นตอนนี้ คอนเทนเนอร์จะถูกเปิดเผยทันทีที่เริ่มทำงาน เนื่องจากพอร์ต Docker ที่เผยแพร่จะถูกแทรกไว้ก่อนกฎไฟร์วอลล์ของคุณ ควรอ่านรายละเอียดของปัญหานี้: พอร์ต Docker ที่เผยแพร่จะข้าม ufw

SEARXNG_VERSION=latest ใช้ได้ในระหว่างเรียนรู้ แต่บนเซิร์ฟเวอร์ที่มีความสำคัญ ควรระบุ tag แบบตายตัว ณ เดือน July 2026 tag ของรุ่นจะอ้างอิงตามวันที่และมีรูปแบบอย่าง 2026.3.25-541c6c3cb ดังนั้นการติดตั้งที่ระบุ tag แบบตายตัวจะอัปเกรดเมื่อคุณตัดสินใจ ไม่ใช่เมื่อรีจิสทรีเปลี่ยนแปลงเอง

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 ใช้ลงลายเซ็นข้อมูลเซสชันและโทเค็น ค่าเริ่มต้นที่มาพร้อมกับซอฟต์แวร์คือสตริงตามตัวอักษร ultrasecretkey หากปล่อยไว้ ผู้ใดก็ตามที่ทราบค่าเริ่มต้นนี้จะสามารถปลอมแปลงโทเค็นได้ เปลี่ยนค่านี้เพียงครั้งเดียว แล้วอย่าเปลี่ยนอีก เพราะการเปลี่ยนภายหลังจะลบการกำหนดลักษณะที่บันทึกไว้ทั้งหมด

base_url ต้องเป็นที่อยู่ HTTPS สาธารณะและต้องมีเครื่องหมายทับปิดท้าย SearXNG ใช้ค่านี้เขียนลงในลิงก์ที่แสดงผล หากปล่อยให้ชี้ไปที่ localhost ลิงก์ "หน้าถัดไป" ในเบราว์เซอร์ระยะไกลจะชี้ไปยังเครื่องของผู้อ่านเองและใช้งานไม่ได้

formats กำหนดประเภทผลลัพธ์ที่ web endpoint จะสร้าง json ไม่อยู่ในรายการค่าเริ่มต้น ดังนั้นคำขอ JSON จะตอบกลับด้วย 403 จนกว่าคุณจะเพิ่มค่านี้ image_proxy: true จะส่งภาพตัวอย่างผลลัพธ์ผ่านเซิร์ฟเวอร์ของคุณ ทำให้เว็บไซต์ที่โฮสต์ภาพเหล่านั้นไม่เห็นที่อยู่ของผู้เยี่ยมชม

valkey.url ใช้ชื่อโฮสต์ valkey เนื่องจากเป็นชื่อ service ในไฟล์ Compose และ Compose จะวาง container ทั้งสองไว้ใน network เดียวกัน ซึ่งสามารถแปลงชื่อ service ได้ ชี้ไปที่ localhost แล้วตัวจำกัดอัตราจะทำงานผิดพลาด เพราะภายใน container core ค่า localhost หมายถึง container นั้นเอง

secret อยู่ในไฟล์ธรรมดา ดังนั้นให้ป้องกัน directory ที่ครอบไฟล์แทนการป้องกันเฉพาะตัวไฟล์ chmod 750 /opt/searxng จะป้องกันไม่ให้ผู้ใช้อื่นบน host เข้าถึงได้ อย่าปรับ core-config/settings.yml ให้เป็น mode 600 เพราะ container ทำงานด้วยผู้ใช้ที่ไม่มีสิทธิ์ระดับสูงของตนเอง และหากผู้ใช้นั้นอ่านไฟล์ไม่ได้ SearXNG จะเริ่มทำงานไม่ได้เลย

เริ่ม stack แล้วตรวจสอบ

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

docker compose ps ควรแสดง container ทั้งสองรายการในสถานะ running ส่วน curl ควรตอบกลับด้วย HTTP/1.1 200 OK หากไม่มีการตอบกลับ ให้ตรวจสอบ docker compose logs core เนื่องจากข้อผิดพลาดของ YAML ใน settings.yml จะแสดงที่นั่นเป็นข้อผิดพลาดในการแยกวิเคราะห์ พร้อมระบุบรรทัดที่เกิดปัญหา

วางไว้ด้านหลัง 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 ก่อนที่คุณจะโหลดการตั้งค่าใหม่ Certbot จะเขียนไฟล์เดียวกันใหม่เพื่อให้รับการเชื่อมต่อบน 443 พร้อมใบรับรอง และเพิ่มการเปลี่ยนเส้นทางจากพอร์ต 80 ระเบียน DNS ของ search.example.com ต้องชี้มายังเซิร์ฟเวอร์นี้อยู่แล้ว เนื่องจากผู้ให้บริการออกใบรับรองจะพิสูจน์ความเป็นเจ้าของโดยเรียกไฟล์ผ่าน HTTP คู่มือฉบับเต็มซึ่งรวมการต่ออายุใบรับรองอยู่ใน คู่มือ Certbot และ nginx สำหรับ Ubuntu 24.04

ส่วนหัวสำหรับส่งต่อทั้งสองรายการไม่ใช่สิ่งตกแต่ง หากไม่มี X-Forwarded-For และ X-Real-IP ทุกคำขอที่มาถึง SearXNG จะมีที่อยู่ของพร็อกซี ทำให้ตัวจำกัดอัตรามองว่ามีไคลเอนต์เพียงรายเดียวที่สร้างทราฟฟิกทั้งหมด และไม่สามารถแยกผู้เยี่ยมชมออกจากกันได้

เหตุผลที่สคริปต์และเอเจนต์ต้องการ 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 และ engine ที่เป็นผู้จัดหา รวมถึง answers, infoboxes และ suggestions ข้อมูลนี้เพียงพอสำหรับส่งต่อให้เครื่องมือสรุปผล เครื่องมือตรวจสอบลิงก์ หรือกระบวนการวิจัยแบบวนซ้ำ

เรื่องนี้สำคัญสำหรับงานที่มีลักษณะเป็นเอเจนต์ โมเดลภาษาอาจมีข้อมูลการฝึกที่สิ้นสุด ณ ช่วงเวลาหนึ่ง จึงต้องใช้การค้นหาแบบเรียลไทม์เพื่อตอบคำถามเกี่ยวกับปัจจุบัน ส่วน API สำหรับการค้นหาเชิงพาณิชย์คิดค่าบริการตามจำนวนคำขอและจำกัดอัตราการใช้งานอย่างเข้มงวด อินสแตนซ์ภายในเครื่องใช้เพียง 1 container บน server ที่คุณจ่ายค่าใช้งานอยู่แล้ว และคำค้นจะไม่ออกนอกระบบ หากคุณกำลังเชื่อมต่อเครื่องมือเข้ากับโมเดล แนวคิดเดียวกันนี้นำไปสู่ การรัน MCP servers บน VPS โดยเครื่องมือค้นหามักเป็นเครื่องมือแรกที่ผู้ใช้เพิ่ม

การใช้ API มีหลัก 2 ข้อ ให้เก็บอินสแตนซ์ไว้เป็นส่วนตัว โดย bind ฝั่ง API กับ loopback address หรือ private network และอนุญาตเฉพาะ host ของคุณเองให้เข้าถึง จากนั้นส่งคำค้นอย่างเหมาะสม SearXNG จะส่งต่อคำขอของคุณไปยัง search engine จริง ดังนั้นสคริปต์ที่ส่งคำขอ 100 ครั้งต่อวินาทีอาจทำให้ Google บล็อก server ของคุณ

ตัวจำกัด และสิ่งที่เปลี่ยนแปลงสำหรับอินสแตนซ์สาธารณะ

ตัวจำกัดคือระบบป้องกันบอตของ SearXNG ระบบนี้ตรวจสอบส่วนหัวคำขอ ที่อยู่ และอัตราคำขอ จากนั้นจะทิ้งทราฟฟิกที่มีลักษณะเป็นการทำงานอัตโนมัติ ระบบต้องใช้ Valkey เพื่อเก็บสถานะดังกล่าว จึงมี Valkey อยู่ในไฟล์ Compose

สำหรับอินสแตนซ์ส่วนตัว ให้คง limiter: false ไว้ สคริปต์ของคุณเป็นทราฟฟิกอัตโนมัติตามนิยาม ดังนั้นตัวจำกัดจะบล็อกการเรียก JSON ที่คุณสร้างอินสแตนซ์นี้ขึ้นมาเพื่อใช้งาน การควบคุมการเข้าถึงจึงควรเป็นหน้าที่ของ reverse proxy แทน โดยใช้คู่ allow และ deny ใน nginx location, HTTP basic authentication หรือไฟร์วอลล์ที่อนุญาตเฉพาะเซิร์ฟเวอร์อื่นของคุณ

หากคุณเผยแพร่อินสแตนซ์ให้ผู้อื่นใช้งาน ให้เปิดสวิตช์ทั้งสองรายการ

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 ออกโทเค็นที่เซสชันเบราว์เซอร์จริงเท่านั้นที่จะดึงมาได้ จึงหยุด scraper แบบง่ายส่วนใหญ่ได้ คาดว่าอินสแตนซ์สาธารณะจะดึงดูด scraper เหล่านี้ภายในไม่กี่วัน และคาดว่าจะพบข้อผิดพลาดจาก engine ด้วย เพราะยิ่งคุณส่งต่อทราฟฟิกมาก engine upstream ก็จะเริ่มส่ง CAPTCHA กลับมายังที่อยู่เซิร์ฟเวอร์ของคุณเร็วขึ้น อินสแตนซ์ SearXNG สาธารณะต้องมีการดูแลอย่างต่อเนื่อง แต่อินสแตนซ์ส่วนตัวไม่ต้องดูแลในระดับเดียวกัน จึงเป็นเหตุผลที่อินสแตนซ์ส่วนตัวมักอยู่ในรายการสั้น ๆ ของ สิ่งที่ควรโฮสต์เองในปี 2026

เหตุใดการค้นหาจึงไม่แสดงผลลัพธ์

เปิด /stats บนอินสแตนซ์ของคุณ หน้านี้แสดง engine ทั้งหมดพร้อมอัตราข้อผิดพลาดและเวลาตอบสนอง และเป็นจุดแรกที่ควรตรวจสอบเมื่อผลลัพธ์มีจำนวนน้อย

engine ที่แสดงข้อผิดพลาด "Access denied" หรือ "CAPTCHA" ได้บล็อก address ของเซิร์ฟเวอร์ของคุณ เหตุการณ์นี้พบได้บ่อยกับ address ในช่วงของ data centre เนื่องจาก search engine มักถือว่า address เหล่านี้เป็นของ scraper จากนั้น SearXNG จะระงับ engine ที่ล้มเหลวไว้ระยะหนึ่งแทนการลองใหม่ ทำให้ engine ที่ถูกบล็อกหายไปจากผลลัพธ์ของคุณโดยไม่แสดงอาการ ปิดใช้งาน engine ดังกล่าวใน settings.yml หรือยอมรับการสูญเสียนี้ engine ที่เหลือยังคงตอบสนองได้

หาก engine ทุกตัวล้มเหลวพร้อมกัน container จะไม่มีการแปลงชื่อภายนอกที่ใช้งานได้ หรือไม่มีเส้นทางไปยังอินเทอร์เน็ต ให้ทดสอบจากภายใน container

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

FAQ

SearXNG ทำให้การค้นหาของฉันไม่เปิดเผยตัวตนหรือไม่

SearXNG ซ่อนตัวตนของคุณจากเอนจินที่ใช้ค้นหา เนื่องจากเอนจินเหล่านั้นเห็นว่าเซิร์ฟเวอร์ของคุณเป็นผู้ส่งคำขอ ไม่ใช่เบราว์เซอร์ของคุณ แต่ SearXNG ไม่ได้ซ่อนคำค้นหาจากเซิร์ฟเวอร์ของคุณ และไม่ได้ซ่อนเซิร์ฟเวอร์ของคุณจากเอนจินเหล่านั้น ในอินสแตนซ์ที่มีผู้ใช้เพียงรายเดียว ทราฟฟิกทั้งหมดจากที่อยู่นั้นเป็นของคุณ ดังนั้นที่อยู่นั้นเองจึงกลายเป็นตัวระบุ ทราฟฟิกระหว่างเบราว์เซอร์กับอินสแตนซ์ของคุณได้รับการป้องกันด้วยใบรับรอง TLS

เหตุใดคำขอ JSON จึงส่งผลลัพธ์เป็น 403 Forbidden

มีสาเหตุได้ 2 ประการ และทั้งสองประการเกี่ยวข้องกับการกำหนดค่า อาจไม่มี json อยู่ในรายการ formats ภายใต้ search: ใน settings.yml ซึ่งเป็นสถานะเริ่มต้น หรือ limiter อาจเปิดใช้งานอยู่และจัดสคริปต์ของคุณเป็น bot ให้เพิ่มรูปแบบดังกล่าวก่อน แล้วเริ่มการทำงานใหม่ด้วย docker compose restart core จากนั้นลองอีกครั้ง หากยังล้มเหลว ให้ตั้งค่า limiter: false และควบคุมการเข้าถึงที่ reverse proxy แทน

หากปิด limiter ไว้ จำเป็นต้องใช้คอนเทนเนอร์ Valkey หรือไม่

ควรปล่อยให้คอนเทนเนอร์ทำงานต่อไป SearXNG ทำงานได้โดยไม่ต้องใช้คอนเทนเนอร์นี้ แต่จะไม่สามารถเปิดใช้งาน limiter ภายหลังได้หากไม่มีคอนเทนเนอร์ดังกล่าว และคอนเทนเนอร์นี้ยังเก็บสถานะอื่นที่มีอายุสั้นด้วย คอนเทนเนอร์มีขนาดเล็กและจัดเก็บเฉพาะข้อมูลแคช ดังนั้นการลบออกจึงประหยัดทรัพยากรได้เพียงเล็กน้อย แต่ทำให้คุณเสียทางเลือกในการเปิดใช้งานฟังก์ชันดังกล่าว

จะอัปเดต SearXNG ได้อย่างไร

เรียกใช้ docker compose pull แล้วตามด้วย docker compose up -d ใน /opt/searxng Compose จะสร้างคอนเทนเนอร์ใหม่สำหรับอิมเมจที่มีการเปลี่ยนแปลง และจะไม่แก้ไขไดเรกทอรี core-config/ ของคุณ ดังนั้น settings.yml จึงยังคงอยู่ เนื่องจาก use_default_settings: true ผสานคีย์ของคุณเข้ากับค่าเริ่มต้นที่ซอฟต์แวร์จัดส่งมา ตัวเลือกที่เพิ่มเข้ามาจากโครงการต้นทางจึงได้รับค่าที่เหมาะสมแทนที่จะทำให้ไฟล์ใช้งานไม่ได้

สามารถให้หลายคนใช้อินสแตนซ์เดียวร่วมกันได้หรือไม่

ได้ และกรณีนี้เป็นกรณีที่คุณควรเปิดใช้งาน limiter และตั้งค่า public_instance: true ค่ากำหนดจะจัดเก็บไว้ในเบราว์เซอร์ของผู้เข้าชมแต่ละราย จึงไม่ต้องจัดการบัญชีผู้ใช้ หลังเปิดให้อินสแตนซ์เข้าถึงได้แล้ว ให้ตรวจสอบ /stats เป็นเวลา 1 สัปดาห์ เนื่องจากเอนจินต้นทางจะเริ่มปฏิเสธเซิร์ฟเวอร์ของคุณก่อนที่คุณจะสังเกตเห็นผลการค้นหาที่หายไปเป็นเวลานาน

#searxng#search#privacy#self-hosting#docker