历史条目的图标原先写死 fas fa-globe,整栏都是地球图标。 - 新增 history-server/favicon.go:后台抓取每个 host 的 favicon 并缓存到 data/item-icons/,命中后 conf.yml 写本地文件名,与手工图标同一套解析。 抓取顺序 <host>/favicon.ico → 首页 <link rel=icon>;3 个 worker, 失败 6 小时后再试;完成后合并触发一次 conf.yml 重建。 - 只缓存 Dashy 能渲染的格式:其 isImage() 白名单是 [svg,png,jpg], 写 .ico 进去完全渲染不出来。因此 .ico 先抽内嵌 PNG,若是传统 BMP/DIB 编码则解码后转 PNG(Google 这类站点只给老式 .ico)。 - 内网地址用 host:port 区分(不同端口的服务不再共用一个图标),且只直连; 外网站点直连失败时自动复用 SearXNG outgoing.proxies 的代理, 也可用 NAVI_FAVICON_PROXY 覆盖。 - 修掉一个真实缺陷:导航项都没有访问数据时,原来会提前 return 并把 「历史访问」清成只剩安装入口 —— 只浏览站外站点时真实历史会整个消失。 现在只冻结「常用服务」,历史照常生成。 - Dockerfile 去掉 # syntax=docker/dockerfile:1:该指令会让 BuildKit 去 pull docker/dockerfile 前端镜像,无外网环境直接构建失败;本文件未用 BuildKit 语法。 实测:6/6 站点(含 google.com 的 DIB 型 ico、github.com、docker.com、 news.ycombinator.com 与两个内网服务)均得到真实图标,页面 naturalWidth>0。
556 lines
18 KiB
Markdown
556 lines
18 KiB
Markdown
# HomeDash — 自托管内网导航门户
|
||
|
||
将 **Dashy + SearXNG + 浏览器历史同步 + 管理后台**整合在单个 Docker 容器中,并附带**完整的内网服务发布方案**(带统一认证的反向代理 + webui4frpc 内网穿透),让外网通过域名安全访问内网服务。
|
||
|
||
## 架构总览(生产全链路)
|
||
|
||
```
|
||
公网用户
|
||
│
|
||
▼
|
||
阿里云 VPS (frps 服务端, <vps-public-ip>:7000/8080/443)
|
||
│ frps: vhost 端口 + tcp 隧道
|
||
▼
|
||
frpc (由 webui4frpc 在内网主机上管理, WebUI :7500)
|
||
│ configs/*.json → 定义各隧道
|
||
▼
|
||
portal-nginx (统一认证反向代理, 容器)
|
||
│ auth_request → portal-auth(:4001) 统一登录
|
||
│ map $host → 按子域名分流
|
||
▼
|
||
navi 单容器 (Dashy+SearXNG+历史+管理, :3003)
|
||
│ 内层 nginx :8080 按路径分流
|
||
▼
|
||
Dashy / SearXNG(→Clash 代理出网) / 历史 API / 管理 UI
|
||
```
|
||
|
||
### navi 容器内部
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ nginx (:8080) — 统一入口,同域名同端口 │
|
||
│ ├─ / → Dashy 静态仪表盘 │
|
||
│ ├─ /search → SearXNG 搜索 (:8888) │
|
||
│ ├─ /static/ → SearXNG 静态资源 (:8888) │
|
||
│ ├─ /api/history/ → 历史同步 API (:3004) │
|
||
│ ├─ /admin/ → 管理后台 WebUI (:3005) │
|
||
│ ├─ /conf.yml → 运行时导航配置(数据卷) │
|
||
│ └─ /item-icons/ → 自定义图标 (数据卷) │
|
||
└─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**技术栈**:Go(历史 API + 管理 API)· SearXNG(Python) · Dashy/Vue · Nginx · Supervisord · frp/webui4frpc
|
||
|
||
## 快速开始
|
||
|
||
### 前置条件
|
||
|
||
- Docker 20+ 与 Docker Compose v2
|
||
- 可选:公网域名 + 反向代理,用于外网访问(见下文「生产部署」)
|
||
|
||
### 方式 A:从本仓库拉取源码构建(推荐)
|
||
|
||
```bash
|
||
# 1. 拉取仓库(把 <your-gitea> 换成你自己的 Git 托管地址)
|
||
git clone <repo-url> HomeDash
|
||
cd HomeDash
|
||
|
||
# 2. 配置环境变量
|
||
cp .env.example .env
|
||
# 编辑 .env:
|
||
# - NAVI_SYNC_TOKEN / NAVI_ADMIN_TOKEN:鉴权令牌,openssl rand -hex 24 生成
|
||
# - SEARXNG_BASE_URL:对外访问地址(有域名填 https://nav.example.com)
|
||
# - NAVI_PORT:对外端口(默认 3003)
|
||
|
||
# 3. 首次启动(会拉取 golang/dashy/searxng 基础镜像并编译)
|
||
docker compose up -d --build
|
||
|
||
# 4. 访问
|
||
echo "打开 http://<ip>:3003"
|
||
```
|
||
|
||
### 方式 B:直接构建镜像运行
|
||
|
||
```bash
|
||
docker build -t jianf-navi .
|
||
docker run -d --name jianf-navi -p 3003:8080 \
|
||
-e SEARXNG_BASE_URL=https://nav.example.com \
|
||
-e NAVI_SYNC_TOKEN=<random> \
|
||
-e NAVI_ADMIN_TOKEN=<random> \
|
||
-v $PWD/data:/app/data \
|
||
jianf-navi
|
||
```
|
||
|
||
### 首次配置导航项
|
||
|
||
容器启动后按需编辑 `data/conf.yml`(sections 列表),或直接用管理后台添加:
|
||
|
||
```bash
|
||
# 先让 conf.yml 从模板生成
|
||
docker compose restart
|
||
# 或用管理 WebUI 在浏览器添加:http://<ip>:3003/admin/
|
||
```
|
||
|
||
> 首次没有 data/ 目录时,容器会用内置 `conf.example.yml` 生成一份最小配置。
|
||
|
||
## 配置说明
|
||
|
||
### conf.yml 核心字段
|
||
|
||
```yaml
|
||
appConfig:
|
||
theme: default
|
||
webSearch:
|
||
searchEngine: custom
|
||
customSearchEngine: /search?q= # 同域名反代到 SearXNG
|
||
openingMethod: newtab
|
||
|
||
sections:
|
||
- name: 常用服务 # 按访问频次自动排序
|
||
icon: fas fa-star
|
||
collapsed: false
|
||
items:
|
||
- title: Gitea
|
||
icon: fas fa-code-branch
|
||
url: http://192.168.1.100:3000
|
||
statusCheck: true
|
||
```
|
||
|
||
### 图标
|
||
|
||
放入 `data/item-icons/`,conf.yml 引用文件名:
|
||
|
||
```yaml
|
||
icon: my-icon.png # 本地图标
|
||
icon: fas fa-star # Font Awesome
|
||
```
|
||
|
||
### 环境变量
|
||
|
||
| 变量 | 说明 | 默认 |
|
||
|------|------|------|
|
||
| `NAVI_SYNC_TOKEN` | 浏览器扩展同步历史令牌 | 空(不鉴权) |
|
||
| `NAVI_ADMIN_TOKEN` | 管理后台/API 写操作令牌 | 空(不鉴权) |
|
||
| `SEARXNG_BASE_URL` | 对外访问地址,影响搜索结果链接 | `http://localhost:3003` |
|
||
| `NAVI_PORT` | compose 对外端口 | `3003` |
|
||
|
||
## 浏览器扩展
|
||
|
||
### 安装(两种方式)
|
||
|
||
**方式 1:导航页内一键引导(推荐)**
|
||
|
||
导航页会自动检测插件是否已安装:
|
||
|
||
- 未安装时,「历史访问」**第一条**固定显示「安装浏览历史插件」入口;
|
||
- 点击后打开 `/extension/install.html`,**自动识别浏览器**并给出对应安装步骤与安装包;
|
||
- 已安装时,`/navi.js` 读到插件写入的 `data-navi-ext` 标记,把该入口自动隐藏。
|
||
|
||
检测原理:插件设置里填了服务地址后,会向**该站点的域名**动态注册一个 content script
|
||
(Chrome 用 `chrome.scripting.registerContentScripts`,Firefox 用 `browser.contentScripts.register`),
|
||
在 `document_start` 给 `<html>` 打上 `data-navi-ext`。不会在其他站点上运行。
|
||
|
||
> Chrome / Edge **不允许**从网站直接安装非商店扩展,所以这一步只能下载后手动加载;
|
||
> 若你已把扩展发布到商店,把链接写进 `.env` 或 data 卷的 `extension-store.json`,
|
||
> 安装页就会出现真正的「从商店一键安装」按钮:
|
||
>
|
||
> ```json
|
||
> { "chrome": "https://chrome.google.com/webstore/detail/<id>",
|
||
> "firefox": "https://addons.mozilla.org/firefox/addon/<slug>/" }
|
||
> ```
|
||
>
|
||
> 放到 `data/extension-store.json` 即可,无需重建镜像。
|
||
|
||
**方式 2:手动加载源码目录**
|
||
|
||
**Chrome / Edge**:`chrome://extensions/` → 开发者模式 → 加载 `extension/chrome/`
|
||
|
||
**Firefox**:`about:debugging#/runtime/this-firefox` → 临时加载 `extension/firefox/manifest.json`
|
||
|
||
> 扩展的「同步令牌」需填服务端 `.env` 里 `NAVI_SYNC_TOKEN` 的**同一个值**,否则同步被拒(401)。
|
||
|
||
### 配置
|
||
|
||
| 字段 | 示例 |
|
||
|------|------|
|
||
| 服务地址 | `https://nav.example.com` |
|
||
| 同步令牌 | `.env` 中的 `NAVI_SYNC_TOKEN` |
|
||
| 设备名称 | `desktop-chrome` |
|
||
|
||
### 行为
|
||
|
||
- 每 30 秒检查本地队列,**仅在有新数据时 POST**
|
||
- 搜索引擎 URL 在本地过滤,不上传
|
||
- 「常用服务」和「历史访问」按总访问频次自动排序
|
||
- 历史条目的图标由服务端自动抓取并缓存(见下)
|
||
|
||
### 历史条目的站点图标
|
||
|
||
history 里的站点不可能像手工导航项那样预先配好图标,所以服务端会**后台抓取每个
|
||
host 的 favicon** 并缓存到 `data/item-icons/favicon-<host>.png`,缓存命中后
|
||
conf.yml 里写的是本地文件名,与手工图标走同一套解析。
|
||
|
||
- 抓取顺序:`<host>/favicon.ico` → 首页 `<link rel="icon">`
|
||
- `.ico` 会先尝试抽出内嵌 PNG;若是传统 BMP/DIB 编码,则服务端解码并转成 PNG
|
||
(Dashy 的 `isImage()` 只认 `svg/png/jpg`,直接写 `.ico` 是渲染不出来的)
|
||
- 内网地址(含端口,如 `192.168.1.10:3000`)只走直连;外网站点先直连,
|
||
失败时自动复用 SearXNG `outgoing.proxies` 的代理(也可用 `NAVI_FAVICON_PROXY` 单独指定)
|
||
- 抓不到就保持 `fas fa-globe`,6 小时后再试;缓存文件持久化在 data 卷
|
||
|
||
## 管理后台
|
||
|
||
访问 `http://<your-ip>:3003/admin/` 可视化管理导航项。
|
||
|
||
API(需 `NAVI_ADMIN_TOKEN`):
|
||
|
||
```bash
|
||
# 查看
|
||
curl -H "Authorization: Bearer <token>" http://<ip>:3003/admin/api/sections
|
||
|
||
# 添加
|
||
curl -H "Authorization: Bearer <token>" -X POST -H 'Content-Type: application/json' \
|
||
-d '{"sectionIndex":0,"item":{"title":"New","url":"https://example.com"}}' \
|
||
http://<ip>:3003/admin/api/item
|
||
|
||
# 删除
|
||
curl -H "Authorization: Bearer <token>" -X DELETE -H 'Content-Type: application/json' \
|
||
-d '{"sectionIndex":0,"itemIndex":2}' \
|
||
http://<ip>:3003/admin/api/item/delete
|
||
```
|
||
|
||
## 历史同步 API
|
||
|
||
| 端点 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/api/history/sync` | POST | 批量同步浏览记录 |
|
||
| `/api/history/` | GET | 获取历史(按频次排序) |
|
||
| `/api/history/` | DELETE | 清空全部历史 |
|
||
| `/api/history/stats` | GET | 统计信息 |
|
||
|
||
```json
|
||
// POST /api/history/sync
|
||
{
|
||
"items": [{
|
||
"url": "https://example.com/page",
|
||
"title": "Page Title",
|
||
"device": "desktop-chrome",
|
||
"timestamp": 1725800000,
|
||
"visit_count": 3
|
||
}]
|
||
}
|
||
```
|
||
|
||
## 生产部署:外层统一认证反向代理
|
||
|
||
> 内网门户通常不直接暴露 3003 端口,而是放在一个**带统一登录认证的反向代理**后面,
|
||
> 所有子域名共用一个登录入口。下面是本项目参考的 portal-nginx 方案。
|
||
|
||
### portal-nginx(统一入口容器)
|
||
|
||
结构:一个 nginx 容器负责所有 `*.example.com` 的 TLS 终止 + 按域名分流 + 统一认证。
|
||
|
||
```nginx
|
||
# 按域名映射到内网后端
|
||
map $host $backend {
|
||
hostnames;
|
||
default "";
|
||
navi.example.com http://127.0.0.1:3003; # 本导航容器
|
||
gitea.example.com http://127.0.0.1:3000;
|
||
blog.example.com http://127.0.0.1:8080;
|
||
}
|
||
|
||
# 需登录的域名统一走 auth_request
|
||
server {
|
||
listen 443 ssl;
|
||
http2 on;
|
||
server_name navi.example.com gitea.example.com blog.example.com;
|
||
|
||
auth_request /_auth; # 先问认证服务
|
||
error_page 401 = @login; # 未登录 → 跳登录页
|
||
|
||
location /_auth {
|
||
internal;
|
||
proxy_pass http://127.0.0.1:4001; # portal-auth 认证服务
|
||
proxy_pass_request_body off;
|
||
proxy_set_header Content-Length "";
|
||
proxy_set_header Cookie $http_cookie;
|
||
}
|
||
location @login {
|
||
return 302 https://login.example.com/login?redirect=$scheme://$host$request_uri;
|
||
}
|
||
location / {
|
||
if ($backend = "") { return 404; }
|
||
proxy_pass $backend;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
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;
|
||
}
|
||
}
|
||
```
|
||
|
||
### portal-auth(统一认证服务)
|
||
|
||
一个极简 HTTP 认证服务(:4001),只做两件事:
|
||
|
||
1. `GET/POST /login` — 校验用户名密码,签发 `portal_session` cookie
|
||
2. `/_auth` 被 nginx `auth_request` 调用 — 校验 cookie 是否有效(200=通过,401=拒绝)
|
||
|
||
```python
|
||
# app.py(示意)
|
||
USERNAME = os.environ['PORTAL_USERNAME'] # admin
|
||
PASSWORD = os.environ['PORTAL_PASSWORD'] # 强密码
|
||
sessions = {} # token -> 过期时间
|
||
|
||
# /login 成功 → uuid token 写入 sessions + Set-Cookie
|
||
# /_auth 读 Cookie → 校验存在且未过期 → 200/401
|
||
```
|
||
|
||
部署:
|
||
|
||
```bash
|
||
docker run -d --name portal-auth \
|
||
-p 4001:4001 \
|
||
-e PORTAL_USERNAME=admin \
|
||
-e PORTAL_PASSWORD=change-me \
|
||
-v /path/auth/app.py:/app/app.py:ro \
|
||
python:3.11-slim
|
||
```
|
||
|
||
### 让搜索/管理子路径免登录(可选)
|
||
|
||
Dashy 域名整体在认证后,登录用户能正常搜索。若希望搜索页**免登录公开访问**,在对应 server 块加:
|
||
|
||
```nginx
|
||
location /search { auth_request off; proxy_pass $backend; }
|
||
```
|
||
|
||
> ⚠️ 管理后台 `/admin/` 与历史 API `/api/` **不应**免认证——
|
||
> 它们能修改导航与数据,建议保留登录墙,或改用 **Bearer Token**(见下文鉴权章节)。
|
||
|
||
## 内网穿透:webui4frpc + frp
|
||
|
||
> [webui4frpc](https://gitcode.com/JianFeeeee/webui4frpc) — 基于 Go 与 Web 的可视化 frpc 配置管理工具,
|
||
> 提供 WebUI 创建/启停 frpc 隧道,无需手写 frpc.toml。
|
||
> 也可不用它,直接用原生 frpc(见文末「原生 frpc 方式」)。
|
||
|
||
### 为什么要穿透
|
||
|
||
本导航容器跑在**内网**(如 192.168.x.x:3003)。要让**外网通过域名访问**,需要:
|
||
|
||
```
|
||
外网用户
|
||
→ 公网 VPS(有公网IP) 上的 frps [frp 服务端,监听控制端口 + 域名端口]
|
||
→ frpc(内网运行,webui4frpc 管理或原生)
|
||
→ 你内网的 portal-nginx / navi [把域名流量转发进来]
|
||
```
|
||
|
||
### 第 1 步:公网 VPS 部署 frps
|
||
|
||
下载 frp 服务端二进制并写配置:
|
||
|
||
```toml
|
||
# frps.toml
|
||
bindPort = 7000 # frpc 连接 frps 的控制端口
|
||
vhostHTTPPort = 8080 # HTTP 类型代理的入口端口(雷池/WAF 也走它)
|
||
|
||
auth.method = "token"
|
||
auth.token = "<长随机token>" # frpc 必须带相同 token 才能连
|
||
|
||
tls.enable = true # frpc↔frps 加密
|
||
|
||
# 用 systemd 启动,或直接:
|
||
# ./frps -c frps.toml
|
||
```
|
||
|
||
VPS 安全组/防火墙需放行:`7000`(frpc连接)、`8080`(http域名)、`443/80`(若 https 由 frps 终结)。
|
||
|
||
### 第 2 步:内网主机部署 webui4frpc(可视化)
|
||
|
||
从 [webui4frpc](https://gitcode.com/JianFeeeee/webui4frpc) 下载二进制,启动:
|
||
|
||
```bash
|
||
/opt/webui4frpc/webui4frpc \
|
||
-addr 0.0.0.0:7500 \
|
||
-user admin -password '<强密码>' \
|
||
-workdir /opt/webui4frpc/data
|
||
# 打开 http://<内网IP>:7500 进入 WebUI
|
||
```
|
||
|
||
### 第 3 步:在 WebUI 建「portal」隧道
|
||
|
||
在 WebUI 里新建配置,指向公网 frps,并添加代理。等价配置文件存于 `configs/*.json`:
|
||
|
||
```json
|
||
{
|
||
"serverAddr": "<vps-public-ip>",
|
||
"serverPort": 7000,
|
||
"auth": { "method": "token", "token": "<frp-token>" },
|
||
"proxies": [
|
||
{
|
||
"name": "portal_https",
|
||
"type": "https",
|
||
"localIP": "<内网portal-nginx主机IP>",
|
||
"localPort": 3080,
|
||
"customDomains": ["*.nav.example.com", "nav.example.com"]
|
||
},
|
||
{
|
||
"name": "portal_http",
|
||
"type": "tcp",
|
||
"localIP": "<内网portal-nginx主机IP>",
|
||
"localPort": 3081,
|
||
"remotePort": 8080
|
||
},
|
||
{
|
||
"name": "navi_ssh",
|
||
"type": "tcp",
|
||
"localIP": "<内网目标主机IP>",
|
||
"localPort": 22,
|
||
"remotePort": 220
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
webui4frpc 会自动下载并启动 `frpc`(存 `data/bin/`),配置变更即热加载。
|
||
|
||
### 第 4 步:DNS 解析
|
||
|
||
把 `nav.example.com`、`*.nav.example.com` 的 DNS 指向**公网 VPS IP**。
|
||
|
||
- `type: https` 代理:frps 把域名 443 流量转发内网 portal-nginx:3080,**TLS 证书由你内网管理**
|
||
- `type: tcp`(portal_http):把外网 8080 → 内网 3081(HTTP→HTTPS 跳转或备用入口)
|
||
|
||
### 原生 frpc 方式(不用 webui4frpc)
|
||
|
||
```toml
|
||
# frpc.toml
|
||
serverAddr = "<vps-public-ip>"
|
||
serverPort = 7000
|
||
|
||
auth.method = "token"
|
||
auth.token = "<frp-token>"
|
||
|
||
[[proxies]]
|
||
name = "portal_https"
|
||
type = "https"
|
||
localIP = "192.168.1.100"
|
||
localPort = 3080
|
||
customDomains = ["nav.example.com", "*.nav.example.com"]
|
||
|
||
[[proxies]]
|
||
name = "portal_http"
|
||
type = "tcp"
|
||
localIP = "192.168.1.100"
|
||
localPort = 3081
|
||
remotePort = 8080
|
||
```
|
||
|
||
```bash
|
||
./frpc -c frpc.toml
|
||
```
|
||
|
||
### 隧道规划对照
|
||
|
||
| 代理名 | type | 本地 | 远端 | 用途 |
|
||
|--------|------|------|------|------|
|
||
| portal_https | https | 内网:3080 | 443域名 | 统一反代 HTTPS 入口 |
|
||
| portal_http | tcp | 内网:3081 | 8080 | HTTP 跳 HTTPS / 备用 |
|
||
| gitea_ssh | tcp | 内网:22 | 220 | Git SSH |
|
||
|
||
## 鉴权(历史同步 + 管理 API)
|
||
|
||
导航门户的 `/api/` 和 `/admin/api/` 能读写数据,**不应裸奔**。推荐两层:
|
||
|
||
1. **外层**:portal-nginx 保留登录墙(`/admin/` 页面需登录)
|
||
2. **内层**:Go 服务校验 `Authorization: Bearer <token>`
|
||
|
||
部署时通过环境变量注入令牌:
|
||
|
||
```bash
|
||
docker run -d ... \
|
||
-e NAVI_SYNC_TOKEN=<长随机串> \ # 浏览器扩展同步用
|
||
-e NAVI_ADMIN_TOKEN=<长随机串> \ # 管理 API 写操作用
|
||
jianf-navi:latest
|
||
```
|
||
|
||
浏览器扩展在设置里填同一个 `NAVI_SYNC_TOKEN`,每次同步请求带 `Authorization: Bearer <token>`。
|
||
|
||
```bash
|
||
# 管理 API 示例(写操作必须带 admin token)
|
||
curl -H "Authorization: Bearer <NAVI_ADMIN_TOKEN>" \
|
||
-X POST -H 'Content-Type: application/json' \
|
||
-d '{"sectionIndex":0,"item":{"title":"New","url":"https://example.com"}}' \
|
||
http://<ip>:3003/admin/api/item
|
||
```
|
||
|
||
> 实现参考:`history-server` 的 `/sync` 校验 `NAVI_SYNC_TOKEN`,
|
||
> `admin-server` 的写操作校验 `NAVI_ADMIN_TOKEN`。
|
||
|
||
## 数据备份
|
||
|
||
```
|
||
data/
|
||
├── conf.yml # 导航配置
|
||
├── history.json # 浏览历史
|
||
└── item-icons/ # 自定义图标
|
||
```
|
||
|
||
```bash
|
||
# 自动备份
|
||
0 2 * * * docker exec navi tar czf /tmp/bak.tar.gz -C /app/data . && \
|
||
docker cp navi:/tmp/bak.tar.gz /backup/navi-$(date +\%Y\%m\%d).tar.gz
|
||
```
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
├── history-server/ # Go 历史同步 API (:3004)
|
||
├── admin-server/ # Go 管理后台 API (:3005)
|
||
├── admin/ # 管理后台前端
|
||
├── web/ # Dashy 注入脚本 + 扩展安装引导页
|
||
├── extension/ # 浏览器扩展 (Chrome/Firefox)
|
||
├── nginx.conf # 容器内统一反代
|
||
├── supervisord.conf # 进程管理
|
||
├── conf.example.yml # 脱敏示例配置
|
||
├── searxng-settings.yml
|
||
├── docker-compose.yml
|
||
├── Dockerfile
|
||
└── .env.example
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
**搜索无结果**:确认容器能访问搜索引擎。
|
||
|
||
- 国内服务器通常需要代理才能出网:SearXNG 不读 `http_proxy` 环境变量,
|
||
必须在 `searxng-settings.yml` 的 `outgoing.proxies` 里配置(见文件内注释)。
|
||
- **Bing 结果异常少**:`www.bing.com` 会 302 跳到 `cn.bing.com`,而 SearXNG
|
||
引擎请求不跟随重定向,只会解析跳转页得到 0 条且不报错。已在默认配置里把
|
||
bing 的 `base_url` 指向 `https://cn.bing.com` 绕开该重定向。
|
||
- **引擎大面积超时**:`outgoing.max_request_timeout` 会覆盖每个引擎自己的
|
||
`timeout`。默认配置已放宽到 `request_timeout: 8.0` / `max_request_timeout: 15.0`,
|
||
经代理访问时不要再调回 3/4 秒。
|
||
- 百度与搜狗会返回 302 验证页(并触发引擎 1 小时封禁),默认已关闭。
|
||
|
||
**管理后台 401**:设置了 `NAVI_ADMIN_TOKEN` 时需携带 Bearer token。
|
||
|
||
**历史不显示**:检查扩展配置中的服务地址和同步令牌。
|
||
|
||
**「安装浏览历史插件」入口不消失**:该入口由插件写入的 `data-navi-ext` 标记驱动隐藏。
|
||
|
||
- 确认扩展已启用,且设置里的服务地址**主机名**与当前访问地址一致
|
||
(例如填 `https://nav.example.com`、却用 `http://192.168.1.100:3003` 访问,就检测不到)。
|
||
- 改完设置请刷新页面。Chrome 若因新增 `scripting` 权限把扩展置为待确认,
|
||
需在 `chrome://extensions` 重新启用。
|
||
- 检测失败只会多显示一个入口,不影响同步功能。
|
||
|
||
**内存占用**:正常约 100MB。
|
||
|
||
## 许可
|
||
|
||
MIT
|