Open WebUI 通过 frp 内网穿透对公网提供服务时,遇到静态资源 404、登录后立刻失效或 Cookie 作用域串到其他应用,通常不是 frp 转发本身的问题,而是应用感知的外部路径与浏览器实际访问路径不一致。frp 只做网络转发,不重写应用内部的资源路径和 Cookie 作用域,所以需要在应用或前端反代层处理。
建议优先使用独立子域名暴露 Open WebUI;若必须使用子路径,需要确认应用支持 base path 配置,并同时改写请求转发、静态资源引用和 Set-Cookie 的 Path。frp 配置本身不负责路径重写,Cookie 的 Secure/SameSite 需要与访问协议保持一致。
先分清两种暴露方式,再动手改配置
在 frp 服务端允许 HTTP 隧道时,访问方式有两种:一种是把 Open WebUI 挂在独立子域名,例如 openwebui.example.com;另一种是在已有域名下加子路径,例如 example.com/openwebui。两者的处理难度差别很大。子域名方式前端不需要改路径,应用仍然以根路径访问,只要 Cookie 作用域限定在当前子域即可;子路径方式则要求应用生成的页面、接口和 Cookie 都以 /openwebui/ 为根,这会牵涉很多内部逻辑。
子域名方案:frp 配置最省事
配置 frp 的 HTTP 隧道后,让 Open WebUI 直接通过子域名访问。frp 服务端需开启 vhost_http_port,然后定义一个 HTTP 代理,指向内网 Open WebUI 地址。下面是一段可参考的客户端配置:
[openwebui]
type = http
local_ip = 192.168.1.100
local_port = 8080
custom_domains = openwebui.example.com
如果 frp 服务端已经配置了泛解析,也可以改用 subdomain = openwebui,访问地址变成 openwebui.example.com。这种方式下,Open WebUI 本身不知道 frp 的存在,生成的页面链接都指向当前域名根路径,静态资源加载通常正常。需要注意,如果 Open WebUI 有“公开访问地址”或外部 URL 设置,应将其设置为实际访问地址,避免邮件或分享链接指向内网地址。
子路径方案:需要同时处理代理重写和 Cookie
如果必须用子路径,比较稳妥的做法是在 frp 之前或之后再加一个 nginx 反代。以下配置把公网 /openwebui/ 映射到内网 Open WebUI 的根路径:
location /openwebui/ {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Prefix /openwebui/;
proxy_cookie_path / /openwebui/;
# 需要时加上 websocket 升级
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
这个片段里,proxy_pass 末尾的 / 会把请求 URI 中的 /openwebui/ 前缀去掉,再转发给后端。proxy_cookie_path 会把后端返回的 Path=/ 改为 Path=/openwebui/,保证 Cookie 只在子路径下发送。这里隐藏的风险是:如果 Open WebUI 内部引用了以 / 开头的静态资源,浏览器会直接请求 /_next/static/... 而不是 /openwebui/_next/static/...,导致资源 404。如果后台设置中无法给应用配置 base path,子路径方案很难完整跑通。
Cookie 处理要点
无论哪种方式,最终都需要检查浏览器里的 Cookie 属性。子域名方式下,Cookie 的 Domain 一般继承当前域名,不会跨到其他子域;但如果 frp 暴露的是 HTTP,而你在浏览器里访问的是 HTTPS,Cookie 的 Secure 标记会被浏览器拒绝,登录状态会反复丢失。这时需要在 TLS 终结层正确传递 X-Forwarded-Proto,或把 Cookie 设置为 Secure 且域名匹配。
子路径方式下,除了 Path 要重写,还要注意 SameSite 属性。如果 Open WebUI 和前端反代在同一站点,SameSite=Lax 通常足够;如果嵌入到跨站 iframe 中,则需要设置 SameSite=None 并配合 Secure,但在 frp 场景下不建议让登录 Cookie 跨站暴露。
验证清单
- 用 curl 检查资源是否可达:例如访问
https://openwebui.example.com或https://example.com/openwebui/,看返回的状态码和 Location。 - 打开浏览器开发者工具,刷新页面后看 Network 面板,确认是否有静态资源请求指向了根路径。若出现
/_next/static/404,说明应用没有感知子路径。 - 检查 Application 面板中的 Cookie。子路径方式下,Cookie 的 Path 应该包含
/openwebui;子域名方式下,Domain 应该只覆盖当前子域。 - 登录后刷新页面,确认会话没有丢失。如果丢失,优先看协议是 HTTP 还是 HTTPS,以及 Secure 属性是否匹配。
实际处理时,优先选子域名,其次再考虑子路径。子路径不是不能做,但要求应用支持 base path,并且静态资源全部走相对路径或统一加前缀。若 Open WebUI 当前版本不支持,建议先在子域名下跑通,再逐步验证 Cookie 行为,避免把时间花在不可控的资源 404 追踪上。