SearXNG元搜索引擎Docker部署与安全加固实战
2026/9/17 12:56:22 网站建设 项目流程

有朋友问我:现在谁还在自己搭搜索引擎?

这个问题我熟悉。去年我把 SearXNG 部署到云主机上的时候,身边同事的反应基本都是“白嫖 Google / Bing 不好吗”。但跑了大半年之后,我可以很负责任地说:这已经是我日常使用频率最高的自托管服务,没有之一。原因非常朴素:我不喜欢搜索结果里越来越重的广告和追踪参数,也想让“搜索”这个入口重新掌握在自己手里。SearXNG 是一个完全开源的元搜索引擎,本身不自带爬虫和索引库,而是聚合多个上游引擎的结果;配合 Docker,部署门槛被压得非常低,一台低配云主机就能跑得很好。

如果你手上有一台云主机,不想继续忍受导航页和广告堆砌出来的搜索体验,或者想给团队内部做一个统一的搜索入口,这篇实战记录应该能帮你少走不少弯路。我会从 SearXNG 的定位讲起,再把机器选型、Docker 部署、配置调优、公网加固、故障排查这几个环节完整过一遍,全程是可复现的操作。

1. SearXNG到底是个什么玩意

1.1 元搜索是怎么工作的

很多人第一次听说 SearXNG,会以为它又是一个“搜索引擎”。其实它的定位更准确的说法是搜索结果聚合器。它没有自己的爬虫系统,也不维护网页索引库。用户提交一个关键词后,SearXNG 会把这个关键词同时转发给多个上游搜索引擎——Google、Bing、Brave、Wikipedia、GitHub、Reddit 这些都在可选列表里——然后把这些来源的结果拉回到本地,经过解析、排序、去重之后,统一渲染成一个干净的页面。

这种设计带来的好处很直观:一个入口,能看到多个信息源的结果,而且页面里几乎没有广告。我日常查一个开源项目时,往往左边是普通网页结果,右边能看到 GitHub 和 Stack Overflow 的聚合条目,比来回切换标签页效率高很多。代价也同样明显,SearXNG 的搜索体验完全取决于上游引擎的稳定性和解析兼容性,上游接口结构一变,或者某个引擎开始限流,搜索质量就会波动。

用一句话总结:SearXNG 是“给搜索做聚合和过滤的前端”,它自己不生产内容,只决定你看到什么。

1.2 自托管 vs 公共实例

SearXNG 官方和社区维护了一批公共实例,网上随便一搜就能找到。公共实例的好处是开箱即用,不用自己维护服务器,但问题也不少:公共实例通常负载很高,时不时会挂掉;你不知道它有没有记日志,也没法确认服务方的隐私政策;管理员一旦调整引擎配置,你只能被动接受。

自托管的意义就在这里。部署在自己的云主机上,你可以关掉统计、限制日志留存、自由增删引擎、调整结果权重、决定是否开放给别人用。这些能力对普通用户来说可能只是“更安心”,但对经常写脚本、接 API 的开发者和喜欢自托管的爱好者来说,就是实打实的可定制性。

Docker 部署给自托管带来的另外一个关键好处是可复现。compose 文件加一个配置目录,整个服务就能在一台新机器上快速恢复。我后来给朋友部署第二台实例时,整个过程只花了一刻钟,大部分时间都在等镜像拉取。

1.3 它适合谁,又不适合谁

SearXNG 并不是搜索引擎的万能答案。如果你对搜索准确度极其敏感,希望每个关键词的第一条结果都精确命中,默认配置的 SearXNG 可能会让你失望——聚合结果的排序逻辑和单一搜索引擎的算法差距明显,需要花时间调引擎权重和语言偏好,才能接近“顺手”的状态。

它真正适合的人群是:注重搜索隐私、喜欢自托管、愿意花一点时间调教工具的人。对普通家用场景,它是个很好的默认搜索入口;对开发者,它是很干净的 JSON 搜索 API 来源;对团队,它可以作为内部知识检索的统一跳板。这些场景下,SearXNG 的性价比极高。

2. 部署前的准备:机器、系统与Docker环境

2.1 云主机怎么选

SearXNG 对硬件的要求不高,但这不代表可以随便拿一台最便宜的机器硬扛。我最初在一台 1 核 1G 的云主机上跑,单用户自己用没毛病,可一旦同时开多个引擎搜索,内存曲线会明显往上涨。如果有条件,推荐 2 核 2G 起步,这样即使并发几个请求,系统也不会进入频繁 swap 的状态。硬盘方面,镜像加配置和数据 20G 绰绰有余,不需要额外挂数据盘。

系统我建议用 Debian 12 或 Ubuntu 22.04 LTS 这类干净的 Linux 发行版。用过带面板的系统也没问题,但面板的防火墙和 Docker 网络策略偶尔会互相干扰,排查起来反而更累。虚拟化方面,优先选 KVM 架构的机器,OpenVZ 这类轻量容器虚拟化对 Docker 的内核功能限制比较多,跑起来容易碰壁。

2.2 Docker 的安装步骤

Docker 官方脚本是很多教程的首选,但我个人更推荐先配好 apt 源再安装,这样后续版本升级更可控。以 Debian 系系统为例,下面这组命令是我每次初始化新机器时都会用的:

sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | sudo tee /etc/apt/keyrings/docker.asc >/dev/null echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list >/dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl enable --now docker

装完之后用docker version确认客户端和引擎都正常。如果服务器到 Docker 官方仓库的拉取速度不理想,可以考虑给 Docker 配置镜像加速源,但这一步不是必须的,先跑通再说。

2.3 Compose 插件和用户权限

现在的 Docker 已经内置了 compose v2 子命令,也就是docker compose,不需要再单独安装docker-compose那个 Python 包。如果你执行docker compose version报错,多半是docker-compose-plugin没有装好,用 apt 装一下即可。

比较容易被新手忽略的是用户权限问题。刚装完 Docker,普通用户执行docker ps会提示权限不足,这是因为当前用户不在docker用户组里。把用户加进去再重新登录就好:

sudo usermod -aG docker $USER

重新登录后不需要每次都用sudo docker,操作会顺手很多。注意这个操作等效于把本用户提升到接近 root 的权限,只建议在你自己掌控的服务器上使用。

2.4 防火墙和基础端口

在开始部署前,先把防火墙规则想清楚,避免服务起来了却连不上,或者更糟——服务裸奔到公网。如果是云服务商,除了机器上的防火墙,还要同步检查安全组规则。我常用的ufw配置是这样的:

sudo apt install ufw sudo ufw allow OpenSSH sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable

这里我只放了 SSH、80 和 443。SearXNG 的 8080 端口先不放出去,后面我会用 Nginx 反向代理来对外提供访问,这样安全性和灵活性都更好。还有一个细节:Docker 默认会修改 iptables 规则,ufw的规则有时候会被 Docker 的端口映射绕过,所以最佳实践是强制所有外部流量都走 Nginx,而不是直接暴露容器端口。

3. 用docker-compose把SearXNG拉起来

3.1 目录规划和compose文件

SearXNG 容器本身是无状态的,但需要的持久化内容并不复杂,主要是配置文件和一个小的数据目录。我习惯把服务目录建在/opt/searxng下面,结构清晰,备份的时候打包整个目录就行。

sudo mkdir -p /opt/searxng cd /opt/searxng mkdir -p searxng

然后在/opt/searxng下创建docker-compose.yml。这是我最常用的最小可用版本:

services: searxng: container_name: searxng image: searxng/searxng:latest restart: unless-stopped ports: - "127.0.0.1:8080:8080" volumes: - ./searxng:/etc/searxng environment: - SEARXNG_BASE_URL=http://127.0.0.1:8080 - SEARXNG_SECRET=请替换成随机字符串

注意端口映射我写的是127.0.0.1:8080:8080,这样宿主机之外访问不到 8080 端口。你可能会好奇为什么不直接映射到公网,答案是:我用 Nginx 反向代理来对外服务,容器端口绑定在 loopback 上就多了一层安全边界。如果只是本地测试,这个配置也够用。

3.2 首次启动与配置生成

写好 compose 文件后,先启动一次容器,让镜像内部把默认配置生成出来:

docker compose up -d docker compose ps docker compose logs -f searxng

SearXNG 官方镜像的一个贴心设计是:如果挂载的/etc/searxng目录下没有settings.yml,容器启动时会把内置的默认配置复制进去。也就是说,第一次启动后,宿主机上的./searxng目录里会自动多出配置文件,可以直接编辑,不用自己去官网抄一份完整配置。

启动完成后,先在宿主机上验证一下页面是不是活着:

curl -I http://127.0.0.1:8080

如果看到 HTTP 200,说明基本通了。这里有个小坑:curl -I走的是 HEAD 请求,SearXNG 对某些路径可能返回 405 或 404,但只要返回的不是连接拒绝,基本就能说明服务进程是正常的。

3.3 secret_key 和 BASE_URL 为什么必须认真填

SEARXNG_SECRET是很多新手第一个踩坑的地方。SearXNG 默认配置里开启了 limiter(限流器),而 limiter 要求必须有一个有效的 secret_key 来签名会话数据。如果你既不设置环境变量,也不改配置文件,容器会一直报错或拒绝请求。

生成随机密钥用下面这条命令,比较省事:

openssl rand -hex 32

把输出替换到 compose 文件的SEARXNG_SECRET字段里。注意别把密钥提交到公开的 Git 仓库,有泄露风险。

SEARXNG_BASE_URL同样重要。它告诉 SearXNG 最终对外访问的地址是什么,影响页面里生成的链接和 API 返回的结构。如果你只是本机访问,http://127.0.0.1:8080没问题;一旦后面配置了域名和 HTTPS,记得把它改成https://search.example.com这种正式地址,否则浏览器里的静态资源和登录状态都可能出问题。

3.4 settings.yml 的结构和常用调整

容器首次启动后,编辑./searxng/settings.yml。这个文件是 YAML 格式,SearXNG 的设计很友好:你不需要维护一份完整配置,只要在最上面声明use_default_settings: true,然后在下面覆盖需要改的字段就行。

我的一份基础配置长这样:

use_default_settings: true server: port: 8080 bind_address: "0.0.0.0" secret_key: "这个值会被环境变量覆盖,留着也不影响" limiter: true search: safe_search: 0 autocomplete: "google" default_lang: "zh-CN"

改完配置后重启容器:

docker compose restart searxng

这里我要特别提醒:如果同时设置了SEARXNG_SECRET环境变量,它会覆盖 settings.yml 里的secret_key。我推荐的做法是密钥跟着环境变量走,配置文件里不要写真正的密钥,这样整个配置目录即便打包分发出去也不会泄露秘密。

3.5 什么时候需要加 Redis

官方 compose 示例里其实可以不加 Redis,单用户或者小团队场景完全没必要。Redis 在 SearXNG 里的作用主要是保存限流状态、缓存搜索结果和任务负载,只有公开实例或高并发集群才值得引入。

如果你确实要加,最简单的方式是在 compose 里加一个redis服务:

redis: image: redis:alpine restart: unless-stopped

然后在 settings.yml 里指定redis.url: redis://redis:6379/0。这样 SearXNG 的限流次数和搜索缓存就能跨实例共享,但代价是内存占用会继续上涨。对本文讨论的单机部署,我建议先跳过 Redis,把有限的内存留给搜索请求本身。

4. 把默认搜索结果调成顺手的样子

4.1 语言与区域的坑

如果你的用户主要是中文使用者,默认配置的第一感受可能是:英文结果太多。SearXNG 的search.default_lang可以设置默认语言zh-CN,但这只是一个偏好,不是强制过滤。真实世界的搜索引擎还是会根据关键词、用户 IP、请求来源来猜意图,所以不要指望设了一个zh-CN就只剩中文结果。

我实际用下来最顺手的组合是:default_lang设为zh-CN,但地区不锁定。因为中文技术搜索经常需要找英文原版文档,把地区锁死反而会把一些高质量英文结果过滤掉。搜索框旁边的地区下拉菜单可以随时切,缺省不锁是最灵活的方案。

4.2 引擎的启停与权重调整

SearXNG 默认启用的引擎很多,其中一些可能响应慢、结果重复严重,或者根本不是你需要的语言。在 settings.yml 的engines段可以精确控制。比如我想关掉某个质量差的引擎,同时让 Wikipedia 的权重高一点:

engines: - name: google disabled: false - name: wikipedia weight: 1.3 - name: some_unstable_engine disabled: true

我的经验是一次别开太多引擎。每多一个引擎,SearXNG 就要向外多发起一次请求,响应时间会相应变长。比较常见的结果是 Bing + Google + Brave 再加一个垂直站点就够了,搜索速度和结果丰富度能达到不错的平衡。

判断哪些引擎值得留,最好的办法不是猜,而是看数据。SearXNG 自带一个统计页面(通常在/stats),里面能看到每个引擎的请求成功率、平均响应时间和最近错误数。我调优时就是打开这个页面,把成功率低、响应慢的引擎逐个禁用,观察搜索结果的变化,几次迭代后整体体验会上一个档次。

4.3 结果数量与安全搜索

search.per_page控制每页显示的搜索结果数,默认一般是 20。对私人实例来说,20 合适;如果开放给公网,建议不要调太高,否则每次搜索都要聚合更多结果,既增加上游压力,也容易被爬虫盯上。

safe_search是一个三级设置,0 表示关闭,1 为中等过滤,2 为严格过滤。自己用设 0 没问题,但如果这台实例要分享给朋友或团队成员,设置成 2 能省掉很多不必要的麻烦。

4.4 UI 主题和隐私细节

SearXNG 新版的默认主题很简洁,没有大问题。但有两个和隐私有关的细节值得动手:一是自动补全,autocomplete: "google"会把用户输入的前几个字符发送到 Google 的补全接口,如果你在意“搜索词不离开自己的服务器”这件事,把它改成空字符串或者直接关闭;二是浏览器缓存和 cookie,SearXNG 默认不会保留太多用户状态,这点比很多商业搜索引擎克制得多。

另外建议在 settings.yml 里确认一下server.public_instance这个字段。如果这台机器只是自己或小范围使用,不要把它设成true。设为false时,SearXNG 的限流和验证逻辑会更严格,对防滥用很有帮助。

4.5 顺手接一个 JSON API

SearXNG 最被开发者称道的一点,是它能直接返回结构化 JSON 结果。只要在搜索 URL 后面加format=json,就能拿到干净的结果列表,字段包括标题、链接、摘要、来源引擎等。我团队里现在跑的很多内部脚本,都是用这个接口做批量关键词查询,比逐个请求上游搜索引擎稳定得多。

现在不少对话式工具也支持把 SearXNG 当作联网搜索后端,配置好地址后,让大模型在回答问题时能实时查资料。这个组合用途很广,而且配置方法非常简单,基本上填一个 URL 就能连通。

5. 从localhost到公网:安全加固才是重头戏

5.1 裸奔的教训

如果你只是给自己用,真的不建议直接把 8080 端口映射到公网后就开始访问。SearXNG 这类搜索代理是所有扫描器的重点关照对象,很多人搭好服务和被恶意刷量之间只隔了一个下午。

我自己的真实经历是:有一次图省事,把端口映射改成了0.0.0.0:8080:8080,又没加访问控制,结果部署完大概二十分钟,日志里就开始出现大量陌生 IP 的请求,有的在测路径,有的在刷搜索接口。虽然没有造成什么严重后果,但白白消耗了不少资源,事后清理和加固反而花了很多时间。所以这次教程里,我特意坚持先把容器绑在 127.0.0.1,然后再用反向代理对外提供服务。

5.2 Nginx 反向代理配置

安装 Nginx:

sudo apt install nginx

然后在/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; } }

启用这个站点并重载 Nginx:

sudo ln -s /etc/nginx/sites-available/searxng /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx

注意我把X-Forwarded-ForX-Forwarded-Proto都传给了后端的 SearXNG。这两个头对 SearXNG 判断客户端真实 IP 和请求协议非常关键,尤其是开了限流器之后,如果拿不到真实 IP,所有请求都会被视为来自 127.0.0.1,限流等于白开。

5.3 上 HTTPS,一次都别省

在搜索引擎这个场景里,不做 HTTPS 几乎等于把用户搜索词明文扔在公网上。安装证书用 certbot 非常顺手:

sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d search.example.com

certbot 会自动修改 Nginx 配置,把 80 端口的重定向和 443 的证书路径写进去,然后自动创建一个续期定时器。你基本不用再管证书续期的事。

证书安装完成之后,回到 compose 文件,把SEARXNG_BASE_URL改成https://search.example.com,然后重启容器:

docker compose up -d

这一步经常被忽略,但如果 BASE_URL 还是 http,页面上会混入 http 链接,浏览器地址栏的安全提示也会很别扭。

5.4 访问控制:自己用和别人访问,完全是两套策略

如果这台 SearXNG 只给你自己用,最简单的加固是在 Nginx 层加 HTTP Basic Auth,一行配置就能挡住绝大多数扫描器:

sudo apt install apache2-utils sudo htpasswd -c /etc/nginx/searxng.htpasswd admin

然后在 Nginx 的 location 里加两行:

auth_basic "SearXNG"; auth_basic_user_file /etc/nginx/searxng.htpasswd;

重载 Nginx 之后,没有用户名密码的人连搜索框都看不到。

如果想让团队小范围免密使用,那就得靠 SearXNG 自身的 limiter。开启limiter: true之后,SearXNG 会基于来源 IP 和 cookie 做请求频率限制,同时会在页面上要求通过一个简单的验证。此时必须保证 Nginx 把真实 IP 传给了后端,否则限流器形同虚设。

还可以在 Nginx 层加limit_req限制单个 IP 的请求速率,作为第二道防线。看到这里你应该已经明白,公网部署的核心思路不是“相信谁”,而是“默认不信任任何人”。

5.5 更新和备份策略

SearXNG 的用户数据很少,需要备份的核心其实就是配置目录。整个/opt/searxng打个包也就几 KB 到几十 KB,非常适合定时备份:

tar czf searxng-backup-$(date +%F).tar.gz /opt/searxng

把这个命令放进 crontab,并且把压缩包同步到其他机器或对象存储,就足够应付绝大多数意外了。升级镜像更简单:

docker compose pull searxng docker compose up -d searxng

SearXNG 的更新节奏比较稳定,但大版本升级后配置结构偶尔会变。升级完看一眼日志,如果某个配置字段失效,容器通常会很直白地报出来,按提示调整即可。

6. 真实运行中的故障和排查思路

6.1 容器起不来、反复重启

这是最常遇到的问题,我的排查顺序很固定:先docker compose ps看状态,再docker compose logs --tail=200 searxng看日志。

新手遇到最多的原因是 settings.yml 的 YAML 缩进错误。YAML 对缩进极其敏感,Tab 和空格混用、字段多缩进一格或少缩进一格,容器都可能直接启动失败。这时候日志里一般会给出 “could not parse settings.yml” 之类的提示。修改的时候记得用空格缩进,不要用 Tab。

另一个常见原因是端口被占。如果你在同一台机器上跑了其他服务占用了 8080,SearXNG 会报address already in use。解决办法很简单,把 compose 的端口映射改成其他端口,或者停掉那个占用端口的服务。

6.2 页面能打开,搜索却一直报错

能打开页面说明服务正常,搜索失败通常出在上游引擎侧。我先去/stats页面看引擎的成功率和响应时间,哪个引擎红得刺眼,就先把它禁用。

这类问题的本质是你所在网络到某些上游搜索服务的连通性不稳。搜索引擎服务商会根据请求频率和来源做限流,较频繁的搜索请求很容易触发临时封禁。我的处理方式是在 settings.yml 里把单引擎超时时间调短,比如 3 秒,避免某个慢引擎拖垮整个页面:

engines: - name: some_slow_engine timeout: 3.0

同时控制并发引擎数量,尽量保持在 4 到 6 个之间。这里我提醒一句:不要盲目追求“引擎越多越好”,你真正想保留的是“结果质量稳定”的源,而不是“偶尔能用”的源。

6.3 本地电脑部署的那些坑

如果你选择在本地 Windows 或 Mac 上用 Docker Desktop 先试试,可能会遇到两个高频问题。第一个是 Windows 下常见的 “virtualization support not detected” 之类报错,说明 BIOS 里的虚拟化没开,或者 WSL2 没正确启用。第二个是 Docker Desktop 本身偶发的网络状态异常,表现是 curl 能通,浏览器打不开,或者反过来。

本地体验一下没问题,但我还是建议:真正要长期用的服务,直接放到一台 Linux 云主机上。Docker Desktop 和 Linux 下的 Docker 引擎在行为细节上存在不少差异,生产环境部署换到 Linux 能少很多诡异问题。

6.4 内存和并发压力怎么处理

搜索请求的峰值内存比平时高,这是 SearXNG 的特性。如果你发现云主机经常吃满内存,优先做三件事:限制容器内存上限、降低 worker 数量、把上游引擎数量降下来。

compose 里可以这样限制:

mem_limit: 1g environment: - SEARXNG_WORKER_COUNT=2

worker 数量在 settings.yml 里对应的字段是server.workers。默认值可能是 CPU 核心数加一,对低配机器来说偏高;手动改成 2 或 3 通常就够日常使用了。同时检查一下search.per_page,如果之前调得过高,搜索请求的内存开销会明显增加。

6.5 健康检查:让机器自己报告身体情况

SearXNG 自带一个/healthz端点,返回 200 就代表服务存活。在 compose 里加上健康检查,能让系统自动帮你盯着服务状态:

healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/healthz"] interval: 30s timeout: 5s retries: 3

加了之后,docker compose ps会显示容器是否 healthy,如果有外部监控,也能直接调用/healthz做探活。这个小成本投入,对长期稳定运行非常值得。

最后说点个人体会。最早搭 SearXNG,我是抱着“去广告、去追踪”的心态,实际跑下来,它最大的价值不是替代谁,而是把所有我不满意的地方集中到一个自己能改的地方。Docker 部署这件事,最大好处不是“一键”,而是可复现:服务器搬家或重装,把 compose 文件和配置一拷,两条命令就能回来。

如果你也想动手,我的建议是先别急着追求复杂:一台最便宜的云主机、一个域名、一个干净的系统,从上面的 compose 开始,跑通再优化。部署 SearXNG 本身不会花很多时间,真正花时间的是理解和调试你自己的搜索需求。等用顺了,再把这个地址填进你常用的对话工具或者浏览器搜索引擎里,会越用越顺。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询