跳到主要内容

WebUI 部署

OxiDNS WebUI 是独立构建的前端静态产物,不会编译进 Rust 后端二进制。部署时有两种推荐方式:

  • 后端同端口托管:由 OxiDNS 管理 HTTP 服务直接托管 WebUI 静态目录,适合裸机、NAS、小型服务器等不想额外配置 nginx 的环境。
  • nginx 独立部署:nginx 服务 WebUI 静态文件,并把 /api/* 反向代理到 OxiDNS 后端,适合已有域名、HTTPS、网关或多服务统一入口的环境。

无论哪种方式,WebUI 默认使用相对后端地址 /api。只要 WebUI 页面和 /api/* 位于同一个站点 origin 下,浏览器就不需要跨域配置。

使用 Release 包内置 WebUI

官方 release 压缩包会包含已经构建好的 webui/ 目录:

oxidns
config.yaml
LICENSE
webui/

如果直接在解压目录运行 OxiDNS,默认配置中的 webui.root: "./webui" 就可以直接使用。Docker 镜像也会把同一份 WebUI 静态文件放到 /etc/oxidns/webui

Debian 包默认服务使用 -c /etc/oxidns/config.yaml -d /var/lib/oxidns。因此默认配置里的 webui.root: "./webui" 表示 /var/lib/oxidns/webui,安装脚本会把它软链接到 /usr/share/oxidns/webui

只有从源码构建、二次开发 WebUI,或需要自行发布静态文件到 nginx/caddy 时,才需要手动构建 WebUI。

手动构建 WebUI

WebUI 位于仓库的 webui/ 目录。生产构建输出为静态目录 webui/out

cd webui
pnpm install --frozen-lockfile
pnpm build

构建完成后,将 out/ 目录发布到服务器上的某个目录,例如:

sudo mkdir -p /etc/oxidns/webui
sudo rsync -a --delete out/ /etc/oxidns/webui/

后续文档都以 /etc/oxidns/webui 作为示例静态目录。

方式一:后端同端口托管

这种方式只需要 OxiDNS 自己启动一个管理 HTTP 端口。WebUI 挂载在 /,管理 API 统一挂载在 /api/*

api:
http:
listen: "0.0.0.0:9199"
auth:
type: basic
username: "admin"
password: "secret"
webui:
root: "/etc/oxidns/webui"
index: "index.html"

启用后访问:

http://服务器IP:9199/

WebUI 会请求同源的 /api/health/api/config/api/plugins/... 等接口。静态文件本身不受 Basic Auth 保护;所有 /api/* 请求仍按管理 API 的认证、CORS、TLS 规则处理。

字段说明:

  • api.http.webui.root
    • WebUI 静态文件目录,必须使用 api.http 详写形式配置。
    • 相对路径以 OxiDNS 的 -d/--working-dir 为基准,不以配置文件所在目录为基准。
    • api.http: "ip:port" 简写只表示监听地址,不能挂载 WebUI。
  • api.http.webui.index
    • 首页文件名,默认 index.html
    • /、目录路径、以及前端路由深链未命中时都会回退到这个文件。

静态服务行为:

  • /api/api/* 永远进入管理 API,不会回退到 WebUI。
  • /apiGET/HEAD 请求会查找静态文件。
  • 未命中的非 /api 路径会返回 index.html,因此刷新 /settings 这类前端路由可以正常工作。
  • 后端会拒绝 ..、绝对路径、非法 percent decode 等路径穿越请求。

方式二:nginx 独立部署

这种方式中,OxiDNS 只在本机监听管理 API,nginx 对外提供 WebUI 和 /api 反代。

OxiDNS 配置可以保持简单:

api:
http:
listen: "127.0.0.1:9199"
auth:
type: basic
username: "admin"
password: "secret"

nginx 示例:

server {
listen 80;
server_name oxidns.example.com;

root /etc/oxidns/webui;
index index.html;

location = /api {
proxy_pass http://127.0.0.1:9199;
proxy_http_version 1.1;
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;
}

location /api/ {
proxy_pass http://127.0.0.1:9199;
proxy_http_version 1.1;
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;
}

location / {
try_files $uri $uri/ /index.html;
}
}

这里 proxy_pass http://127.0.0.1:9199; 会把浏览器请求的 /api/health 原样转发给后端,因此不要把它写成会剥离 /api 前缀的形式。OxiDNS 后端只接受 /api/* API 路由。

如果 nginx 负责 HTTPS,只需要把 listen 443 ssl、证书和 80 到 443 跳转加在 nginx 上即可;OxiDNS 后端仍可只监听 127.0.0.1:9199 明文端口,因为它不直接暴露到公网。

WebUI 后端地址

WebUI 设置页里的后端地址推荐保持默认:

/api

适用场景:

  • 后端同端口托管 WebUI。
  • nginx/caddy/网关把 /api/* 反代到 OxiDNS。
  • Docker Compose 中通过统一入口容器暴露 WebUI 和 API。

只有在开发环境或临时调试时,才需要填写绝对地址,例如:

http://192.168.1.10:9199/api

使用绝对地址时浏览器会进入跨域访问,需要后端 CORS 允许该 WebUI origin。默认 CORS 推导规则如下:

  • listen: "0.0.0.0:9199"listen: "[::]:9199" 会允许任意 origin。
  • 监听具体 IP 时,会允许同一 host 的任意 WebUI 端口。
  • 显式配置 api.http.cors.allowed_origins 后,按浏览器 Origin 精确匹配。

使用在线 Console 直连本地服务

也可以打开 https://console.oxidns.org,在 WebUI 设置页把后端地址改成本机或局域网中的 OxiDNS 管理 API:

http://127.0.0.1:9199/api

如果浏览器和 OxiDNS 不在同一台机器上,请改成实际可访问的地址,例如:

http://192.168.1.10:9199/api

这种方式不作为推荐部署方式。在线 Console 页面和本地 API 不同源,浏览器会执行 CORS 检查;同时你需要让管理 API 可以被当前浏览器访问。更推荐使用“后端同端口托管 WebUI”或 nginx/caddy 反向代理,让 WebUI 和 /api/* 保持同源。

如果确实要临时使用在线 Console,请至少显式允许 Console 的 origin:

api:
http:
listen: "127.0.0.1:9199"
cors:
allowed_origins:
- "https://console.oxidns.org"

当需要从其它设备访问 OxiDNS 管理 API 时,还必须把 listen 改成局域网 IP 或 0.0.0.0:9199,并结合防火墙、反向代理认证或网络访问控制限制来源。不要把未受保护的管理 API 直接暴露到公网。

常见检查

  • 打开 http://服务器:9199/ 或 nginx 域名能看到 WebUI。
  • 浏览器 Network 中 /api/health 返回 200,而不是请求到静态文件。
  • 如果启用了 Basic Auth,WebUI 设置页中需要填写对应用户名和密码。
  • 如果刷新 /settings/plugins 后出现 404,说明静态服务缺少 index.html fallback;nginx 部署时确认 try_files $uri $uri/ /index.html; 已配置。
  • 如果 nginx 反代后 /api/health 返回 404,检查 proxy_pass 是否错误剥离了 /api 前缀。