跳到主要内容

加固 OPL 数据空间

OPL 数据空间是一个自托管应用,它会给已认证用户暴露模型推理、工具执行、代码流水线等能力。和数据库、容器镜像仓库、CI 服务器一样,部署方需要自己负责环境、网络暴露面与配置策略。 OPL 数据空间提供本页提到的控制项,但如何组合使用,取决于你的部署环境、合规要求与威胁模型。

本页关注的是“有哪些可用于加固部署的配置项”,而不是替代完整安全方案。你最终仍然需要根据自己的环境来决定哪些项必须启用。

网络放置

提示

OPL 数据空间更适合部署在私有、可信网络里,类似数据库或内部 CI 服务。

更稳妥的生产部署通常会把它放在以下边界之后:

  • VPN(WireGuard、Tailscale)
  • 零信任访问代理(Cloudflare Access、Pomerium)
  • 带认证与 IP 白名单的反向代理

DDoS 防护、爆破防护、连接限速、fail2ban 这类能力,通常应该放在代理层或网络层,而不是依赖应用本身。

如果你是第一次部署 OPL 数据空间,建议先看本页最后的 Quick Reference,再按需逐节细化。

Secret Key

WEBUI_SECRET_KEY 用于:

  • 签发 JWT(登录 token)
  • 派生 OAuth 会话加密密钥

默认行为

当你通过 Docker 或 open-webui serve 启动时,如果没有显式设置 WEBUI_SECRET_KEY,应用会自动生成一个随机 key,并保存到数据目录中的 .webui_secret_key。后续重启会继续读取它。

因此,对单实例部署来说,通常不需要手工设置。

什么时候必须显式设置

如果你在负载均衡后运行多个 OPL 数据空间实例,它们必须共享同一个 key。否则:

  • 一个实例签发的 token
  • 会被另一个实例视为无效

从而导致登录失败或会话异常。

可用下面的方式生成:

openssl rand -base64 32

然后把同一个值传给所有副本。

轮换影响

修改 WEBUI_SECRET_KEY 会使所有现有会话失效,用户需要重新登录。

认证与注册

注册

默认情况下,注册入口只在首个用户注册之前开放。第一个注册用户会自动成为管理员,之后注册会自动关闭。

新账户的默认角色是 pending,这意味着即便管理员后来重新打开了注册入口(ENABLE_SIGNUP=true),新用户仍然需要管理员审批后才能真正使用系统。

DEFAULT_USER_ROLE=pending

密码校验

OPL 数据空间默认不强制密码复杂度。若要开启:

ENABLE_PASSWORD_VALIDATION=true
PASSWORD_VALIDATION_REGEX_PATTERN='^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$'
PASSWORD_VALIDATION_HINT='Minimum 8 characters with uppercase, lowercase, number, and special character.'

密码以 bcrypt 哈希存储,并受其 72 字节输入上限约束。

用环境变量初始化管理员账户

适合自动化部署:

WEBUI_ADMIN_EMAIL=admin@yourcompany.com
WEBUI_ADMIN_PASSWORD=your-strong-password
WEBUI_ADMIN_NAME=Admin

这一组配置只会在“数据库中尚无用户”时生效。

组织与作用域化管理

如果你的部署启用了组织,不要假设所有“管理员界面”都天然是全局的。审计员、经理、组织管理员、全局管理员在不同作用域下看到的数据与设置入口可能不同。

在加固部署中,建议明确记录:

  • 哪些角色能改租户内配置
  • 哪些设置只能由全局管理员控制
  • 团队如何确认当前选中的组织作用域

这能减少“改错租户”或“误以为某个功能实例级关闭,实际只是组织级关闭”的风险。

纯 SSO 环境

如果所有认证都由 OAuth/OIDC 提供方负责,可以隐藏本地登录表单:

ENABLE_LOGIN_FORM=false
ENABLE_PASSWORD_AUTH=false
ENABLE_PASSWORD_CHANGE_FORM=false

这适合 SSO-only 环境,避免向用户暴露不应使用的本地密码路径。

在 HTTPS 部署下,建议:

WEBUI_SESSION_COOKIE_SECURE=true
WEBUI_SESSION_COOKIE_SAME_SITE=strict
VariableDefault作用
WEBUI_SESSION_COOKIE_SECUREfalse只允许通过 HTTPS 发送 cookie
WEBUI_SESSION_COOKIE_SAME_SITElax控制 cookie 是否随跨站请求发送

同样规则也适用于 OAuth cookie,除非你单独设置了 WEBUI_AUTH_COOKIE_SECUREWEBUI_AUTH_COOKIE_SAME_SITE

Token 过期时间

默认 JWT 过期时间是 4w。可以改短:

JWT_EXPIRES_IN=24h

若设为 -1,则等于完全关闭过期机制, OPL 数据空间会打印警告。

Token 撤销

Token 撤销依赖 Redis

如果没有 Redis,用户登出后 token 仍然有效,直到它自然过期。这意味着:

  • 被泄露的 token 无法通过登出来失效
  • 改密码不会立刻踢掉旧会话
  • 管理员停用账号也不会即时生效

若配置了 Redis, OPL 数据空间才能维护 token 撤销列表,实现真正的生产级会话失效。

如果暂时无法部署 Redis,至少应缩短 JWT_EXPIRES_IN,例如 1h4h。Redis 配置可参考 Redis 教程

CORS

CORS_ALLOW_ORIGIN 决定哪些站点能从浏览器中向你的 OPL 数据空间 API 发起请求。

默认值是 *,代表允许任意来源,启动时 OPL 数据空间会对此发出警告。

生产环境建议收紧到自己的域名:

CORS_ALLOW_ORIGIN=https://chat.yourcompany.com

多个来源之间用分号分隔:

CORS_ALLOW_ORIGIN=https://chat.yourcompany.com;https://internal.yourcompany.com

如果你有桌面端自定义协议,也可补充:

CORS_ALLOW_CUSTOM_SCHEME=app

安全头

OPL 数据空间提供 SecurityHeadersMiddleware 注入 HTTP 安全头,但默认不会自动启用任何项,需要通过环境变量显式打开。

一个常见的起始配置如下:

HSTS=max-age=31536000;includeSubDomains
XFRAME_OPTIONS=DENY
XCONTENT_TYPE=nosniff
REFERRER_POLICY=strict-origin-when-cross-origin
PERMISSIONS_POLICY=camera=(),microphone=(),geolocation=()
CONTENT_SECURITY_POLICY=default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
CONTENT_SECURITY_POLICY_REPORT_ONLY=default-src 'self'; report-uri /csp-report
CROSS_ORIGIN_EMBEDDER_POLICY=require-corp
CROSS_ORIGIN_OPENER_POLICY=same-origin
CROSS_ORIGIN_RESOURCE_POLICY=same-origin
REPORTING_ENDPOINTS=default="https://your-report-collector.example/reports"
提示

如果你启用了 CSP,建议先从宽松策略开始,再逐步收紧。可以先用 CONTENT_SECURITY_POLICY_REPORT_ONLY 测试,避免一上来就把前端资源拦坏。

Cross-Origin Isolation

如果同时设置:

  • CROSS_ORIGIN_EMBEDDER_POLICY=require-corp
  • CROSS_ORIGIN_OPENER_POLICY=same-origin

就会启用跨源隔离。这可能导致外部图片、脚本或 iframe 无法加载,除非对方资源明确带有合适的 CORS 头。

HTTPS 与 TLS

OPL 数据空间本身不终止 TLS。推荐把它放在 Nginx、Caddy、HAProxy 等反向代理之后,由代理负责 HTTPS。具体配置见 HTTPS Reference

启用 HTTPS 后,通常至少再补:

WEBUI_SESSION_COOKIE_SECURE=true
HSTS=max-age=31536000;includeSubDomains