本地 AI Agent 缺一个搜索入口?SearXNG 自托管跑通后,用 cpolar 给团队验收检索效果

SearXNG 自托管搜索入口:本地 AI Agent 通过可控搜索服务和 cpolar 临时 HTTPS 入口完成团队验收

本地 Agent 做到一半,经常会卡在同一个地方:模型会推理,工具也接上了,但一需要查外部资料,就开始依赖别人的搜索接口。

如果只是个人 Demo,临时拿一个在线搜索服务凑合也能跑。可一旦要给团队验收,问题就来了:搜索结果从哪里来、响应快不快、哪些搜索源稳定、接口会不会把内网东西暴露出去,这些都要提前讲清楚。

这篇就只做一件事:把 SearXNG 自托管起来,先在本地验证搜索质量和响应速度,再用 cpolar 开一个临时 HTTPS 入口,让同事远程验收检索效果。验收完关掉入口,不做长期公网开放。

1 什么是 SearXNG?这篇里它负责什么

SearXNG 是一个自托管的元搜索服务。简单说,它自己不生产搜索结果,而是把多个搜索源的结果聚合到一个页面和 API 里。

在本地 AI Agent 场景里,它适合当“可控搜索入口”:

  • 页面端:同事能直接输入关键词,看搜索结果是不是符合预期;
  • API 端:Agent 原型能请求 /search,拿到 JSON 结果;
  • 运维端:搜索源、输出格式、安全参数都放在自己的配置里,排查时不需要猜。

划重点:本文不写 Open WebUI、Dify、RAG 工作流,也不把 SearXNG 包装成万能知识库。它的角色很明确,就是团队验收前的自托管搜索服务。

2 环境准备:Docker、目录和端口先定好

这里用 Docker Compose 部署,端口固定为 8080。SearXNG 官方容器模板里,核心服务默认监听 8080,旁边还会带一个 Valkey 服务,用来支撑限流等能力。

准备一台已经安装 Docker 的机器,Linux、macOS、NAS 上的 Docker 环境都能照着做。本文命令默认在一个干净目录里执行:

mkdir -p ~/searxng-demo/core-config
cd ~/searxng-demo

拉取官方 Compose 模板和环境变量示例:

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

.env 改成只监听本机地址,避免一启动就暴露到整个局域网:

cat > .env <<'EOF'
SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080
EOF

这里别把 SEARXNG_HOST 写成 0.0.0.0。我们后面会用 cpolar 做临时 HTTPS 入口,本机阶段只让 127.0.0.1:8080 能访问,边界更清楚。

3 配置 SearXNG:安全参数和输出格式先补齐

SearXNG 的配置文件放在 core-config/settings.yml,容器内对应 /etc/searxng/settings.yml。官方文档建议用 use_default_settings: true 继承默认配置,再覆盖自己关心的部分。

先生成一个随机密钥:

python3 - <<'PY'
import secrets
print(secrets.token_urlsafe(48))
PY

复制输出结果,写入下面的 secret_key。不要直接照抄示例里的密钥,团队验收环境也要换成自己的值。

cat > core-config/settings.yml <<'EOF'
use_default_settings: true

server:
  secret_key: "把这里替换成刚才生成的随机密钥"
  limiter: true
  public_instance: false
  image_proxy: false
  method: "POST"
  default_http_headers:
    X-Content-Type-Options: nosniff
    X-Download-Options: noopen
    X-Robots-Tag: noindex, nofollow
    Referrer-Policy: no-referrer

search:
  safe_search: 1
  formats:
    - html
    - json

valkey:
  url: valkey://valkey:6379/0

engines:
  - name: bing
    disabled: false
  - name: wikipedia
    disabled: false
EOF

这份配置只开 htmljson 两种输出。html 给同事页面验收,json 给 Agent 原型联调。public_instance: false 保持私有实例口径;limiter: true 配合 Valkey 做请求限制;X-Robots-Tag: noindex, nofollow 明确告诉搜索引擎不要索引这个临时入口。

这里还有一个小提醒:不要把 core-config 目录映射成文件下载目录,也不要把 Docker 宿主机上的项目目录挂进 SearXNG。SearXNG 只需要自己的配置和缓存,没必要接触你的代码仓库、日志目录和密钥文件。

4 启动服务:先在本机跑通页面

配置写好后,启动容器:

docker compose up -d

查看状态:

docker compose ps

正常会看到 searxng-coresearxng-valkey 都是 Up,端口映射里有 127.0.0.1:8080->8080/tcp。如果 core 反复重启,先看日志,不要急着改搜索源:

docker compose logs -f core

本机打开页面:

open http://127.0.0.1:8080

Linux 服务器没有桌面时,用这条命令确认 HTTP 状态:

curl -I http://127.0.0.1:8080

返回 HTTP/1.1 200 OK 或者同等的 200 状态,就说明页面服务已经起来。

本机阶段启动并验证 SearXNG:Docker Compose、127.0.0.1:8080 和 settings.yml 安全配置连通

图里适合放 SearXNG 首页。看到搜索框就够了,这一步不是为了看界面漂不漂亮,而是确认容器、配置文件、端口映射这三件事已经连起来。

5 本地验证:搜索质量、响应速度、搜索源可用性

团队验收前,自己先跑一轮。别拿敏感项目名、客户名称、内网域名去搜,统一用公开关键词。

我建议准备三类测试词:

  • 工具类:SearXNG DockerValkey Redis difference
  • 技术类:Python async retry backoffDocker compose healthcheck
  • 中文类:本地搜索 服务 Docker自托管 搜索 引擎

页面端先搜一次 SearXNG Docker。结果页出来后,点右上角的“首选项”或页面里的偏好设置入口,检查启用的搜索源。这里不要一口气全开,先保留少量稳定搜索源,后面排错轻松很多。

API 端用 JSON 验证:

curl -sG 'http://127.0.0.1:8080/search' \
  --data-urlencode 'q=SearXNG Docker' \
  --data-urlencode 'format=json' \
  | python3 -c 'import sys,json; d=json.load(sys.stdin); print("results=", len(d.get("results", []))); [print(i+1, r.get("title", ""), r.get("engines", [])) for i,r in enumerate(d.get("results", [])[:5])]'

这条命令会打印结果数量、前 5 条标题和来源引擎。results 大于 0,说明 JSON 输出可用;标题和关键词相关,说明搜索质量过关;来源引擎列表里有内容,后面排查搜索源时有依据。

再测响应时间:

curl -o /dev/null -s -w 'status=%{http_code} time=%{time_total}s\n' -G \
  'http://127.0.0.1:8080/search' \
  --data-urlencode 'q=Docker compose healthcheck' \
  --data-urlencode 'format=json'

验收时不用追求毫秒级速度,重点看三件事:HTTP 状态是 200,单次搜索时间在团队能接受的范围内,同一个关键词重复搜索不会频繁报错。

如果结果为空,优先检查 search.formats 里有没有 json。如果页面能搜、API 返回 403,基本就是 JSON 格式没有启用。要是页面和 API 都没有结果,再看 docker compose logs -f core,里面会写出具体搜索源的错误。

6 用 cpolar 开临时 HTTPS 入口给团队验收

本机验证没问题后,再给同事一个临时入口。这里用 cpolar 的目的很单纯:短时间把 127.0.0.1:8080 映射成 HTTPS 地址,让团队远程打开页面验收检索效果。

如果机器还没安装 cpolar,按系统选择一条即可。

Linux:

curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash

macOS:

brew tap probezy/core && brew install cpolar

安装后需要登录账号并绑定 authtoken。已经登录过的机器,直接确认本地控制台能打开:

curl -s http://127.0.0.1:9200 || echo "cpolar 服务未启动"

开临时 HTTP 隧道:

cpolar http 8080

终端输出里会出现 https:// 开头的公网地址。把这个地址发给团队,只用于打开 SearXNG 页面,测试约定关键词和响应速度。

cpolar 临时 HTTPS 隧道给团队验收 SearXNG 页面、搜索相关性和响应速度

这张图适合放 cpolar 终端输出或本地 Web UI 的在线隧道页面。截图里保留 HTTPS 地址和本地端口对应关系即可,不要把账号信息、token、其他隧道列表截进去。

验收话术可以直接这样写:

这是 SearXNG 临时验收入口:
https://你的临时地址

请只测试下面关键词:
1. SearXNG Docker
2. Python async retry backoff
3. 本地搜索 服务 Docker

验收点:
- 页面是否能打开
- 搜索结果是否相关
- 单次搜索等待时间是否能接受
- 搜索源是否有明显不可用报错

7 验收边界:哪些东西不能开放

临时入口最怕“顺手多开一点”。这次只开放 SearXNG 页面,不开放 Docker、SSH、NAS 文件目录、代码仓库和任何管理员配置文件。

边界按下面几条执行:

  • 不把 core-config/settings.yml.env、日志目录放到 Web 可访问路径;
  • 不给同事发送 cpolar 本地控制台 9200 地址;
  • 不在测试关键词里放客户名、内部项目代号、内网域名;
  • 不把临时 HTTPS 地址贴到公开群、论坛和文章评论区;
  • 验收结束立刻关闭 cpolar 进程。

关闭方式很简单,运行 cpolar http 8080 的终端里按 Ctrl + C。如果你用的是 cpolar Web UI 或后台隧道,验收结束后到 http://127.0.0.1:9200 停止对应隧道。

再把 SearXNG 也停掉:

cd ~/searxng-demo
docker compose down

如果团队后续要长期使用,建议重新走正式部署:固定域名、访问控制、反向代理、日志策略、搜索源策略都要单独评审。不要把这次临时验收入口直接当生产入口。

8 总结

到这里,我们已经把 SearXNG 跑成了一个可验收的本地搜索服务:Docker Compose 负责启动核心容器和 Valkey,settings.yml 负责安全参数、JSON 输出和基础搜索源,本地命令负责验证搜索质量、响应速度和搜索源返回情况,cpolar 负责提供短时间 HTTPS 入口。

关键步骤就三块:

  • 先把 SearXNG 绑定在 127.0.0.1:8080,本机确认页面和 JSON API 都能用;
  • 再用公开关键词测试结果相关性、响应时间和搜索源可用性;
  • 验收阶段只用 cpolar 临时开放页面,结束后关闭隧道和容器。

我个人更推荐把这套流程当成“团队验收模板”,而不是一次性部署脚本。搜索入口看起来只是 Agent 的一个小组件,但它直接影响后续答案来源、可追溯性和安全边界。先把 SearXNG 这层验收清楚,后面再接 Agent、工作流或知识库,排错会省很多时间。

更多推荐