Open WebUI 安全加固
Open WebUI 是一个自托管应用程序,可为经过身份验证的用户提供模型推理、工具执行、代码 Pipeline 等功能的访问权限。与其他自托管基础设施(数据库、容器镜像仓库、CI 服务器)类似,部署组织负责管理自己的环境、网络暴露和配置。Open WebUI 提供了本指南中所描述的控制措施;如何配置这些措施取决于您的环境和威胁模型。
本指南涵盖了可用于加固部署的配置选项。每个部分都解释了设置的作用、默认值以及如何更改它。这并不是一份详尽的安全指南,确保部署安全最终是您的责任。您的环境、合规性要求和威胁模型将决定哪些设置与您相关。
网络部署
Open WebUI 是为私有、受信任的网络构建的,类似于其他自托管基础设施,如数据库、容器镜像仓库和 CI 服务器。大多数部署都运行在公司防火墙、VPN 或其他将访问限制在已知用户的网络边界之后。
对于将安全放在首位的组织,推荐的部署方式是将 Open WebUI 部署在以下一个或多个组件之后:
- VPN (WireGuard, Tailscale)
- 零信任访问代理 (Cloudflare Access, Pomerium)
- 具有身份验证和 IP 白名单的反向代理
DDoS 防护和暴力破解防范(限流、连接节流、fail2ban)应在代理或网络层进行处理。
如果您是首次部署 Open WebUI,请从页面底部的快速参考开始,获取按优先级排列的摘要,然后阅读与您的设置相关的章节。
密钥(Secret Key)
WEBUI_SECRET_KEY 用于对 JWT(登录 Token)进行签名,并派生 OAuth 会话数据的加密密钥。
默认机制:
当通过 Docker (start.sh) 或 open-webui serve 运行时,应用程序会检查是否设置了 WEBUI_SECRET_KEY 环境变量。如果未设置,系统会自动生成一个随机密钥,并将其保存到数据目录内的 .webui_secret_key 中。在随后的重启中,保存的密钥将被重新加载。这意味着对于单实例部署,不需要手动配置。
何时需要显式设置:
如果您在负载均衡器后面运行多个 Open WebUI 实例,则每个实例必须共享相同的密钥。否则,由一个实例签名的 Token 将被另一个实例拒绝,从而导致登录失败。使用 openssl rand -base64 32 生成一个密钥,并将其作为环境变量传递给所有副本。
轮换: 更改密钥会使所有现有会话失效。用户将需要重新登录。
身份验证与注册
注册
注册仅开放到第一个用户注册为止,该用户将自动成为管理员。在此之后,注册将自动禁用。此行为不需要手动配置。
新账号的默认角色为 pending(待定),这需要 管理员批准后用户才能访问任何功能。如果管理员选择重新启用注册(ENABLE_SIGNUP=true),pending 默认值可确保新账号在被显式批准前仍无法访问系统。
# 新用户将被置于 "pending" 状态,直到管理员批准(这是默认设置)
DEFAULT_USER_ROLE=pending密码校验
Open WebUI 默认不强制要求密码复杂度。要启用它:
ENABLE_PASSWORD_VALIDATION=true
PASSWORD_VALIDATION_REGEX_PATTERN='^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$'
PASSWORD_VALIDATION_HINT='最少 8 个字符,且必须包含大写字母、小写字母、数字和特殊字符。'密码在存储前会使用 bcrypt 进行哈希处理。Bcrypt 会截断超过 72 字节的输入,Open WebUI 会强制执行此限制。
从环境变量创建管理员账户
对于自动化部署,您可以在启动时创建管理员账户:
WEBUI_ADMIN_EMAIL=admin@yourcompany.com
WEBUI_ADMIN_PASSWORD=your-strong-password
WEBUI_ADMIN_NAME=Admin这仅在数据库中不存在任何用户时生效。一旦创建了管理员,注册就会自动禁用。
仅限 SSO 的环境
如果所有身 份验证都由 OAuth/OIDC 提供商处理,您可以完全隐藏本地登录表单:
ENABLE_LOGIN_FORM=false这会从 UI 中移除邮箱/密码表单,引导所有用户通过您的 SSO 流程。您还可以在后端层面禁用本地密码身份验证:
ENABLE_PASSWORD_AUTH=false如果您希望将登录表单行为与账户页面密码更新分开,可以在 设置 > 账户 中隐藏修改密码表单:
ENABLE_PASSWORD_CHANGE_FORM=false这对于以 SSO 为主的部署非常有用,因为在此类部署中,不应向用户提供本地密码修改功能。
会话与 Cookie 安全
Cookie 设置
当通过 HTTPS 服务 Open WebUI 时(请参阅 HTTPS 配置),请相应地配置 Cookie:
WEBUI_SESSION_COOKIE_SECURE=true
WEBUI_SESSION_COOKIE_SAME_SITE=strict| 变量 | 默认值 | 作用 |
|---|---|---|
WEBUI_SESSION_COOKIE_SECURE | false | 当为 true 时,Cookie 仅通过 HTTPS 连接发送。 |
WEBUI_SESSION_COOKIE_SAME_SITE | lax | 控制 Cookie 是否随跨站请求一起发送。strict 提供了最强的保护。 |
这些设置也适用于 OAuth Cookie,除非被 WEBUI_AUTH_COOKIE_SECURE 和 WEBUI_AUTH_COOKIE_SAME_SITE 覆盖。
Token 有效期
JWT 决定了用户保持登录状态的时间。默认值为 4w(4 周)。您可以将其缩短:
JWT_EXPIRES_IN=24h设置 JWT_EXPIRES_IN=-1 会完全禁用 Token 过期。如果设置了此值,Open WebUI 将记录一条警告。
Token 撤销
如果没有 Redis,退出登录不会使用户的 Token 失效。该 Token 在自然过期之前(默认值:4 周)将一直有效且可用。这意味着:
- 丢失或泄露的 Token 无法通过退出登录来撤销
- 修改用户密码不会使其现有的会话失效
- 管理员发起的账户停用不会立即阻止其访问
- OIDC 后端通道退出(back-channel logout)无法撤销 Token
配置 Redis 后,Open WebUI 支持单 Token 撤销。当用户退出登录、修改密码或被管理员停用时,他们的 Token 将被添加到一个自动过期的撤销列表中。这是生产环境推荐的行为。
如果您无法部署 Redis,请缩短 JWT_EXPIRES_IN(例如 1h 或 4h)以限制暴露时间窗口。有关设置说明,请参阅 Redis 教程。
CORS
跨源资源共享(CORS)控制哪些网站可以从浏览器向您的 Open WebUI API 发送请求。例如,如果您的 Open WebUI 实例位于 https://chat.yourcompany.com,CORS 将决定在不同域名上运行的脚本是否可以与其进行交互。
默认的 CORS_ALLOW_ORIGIN 是 *,允许任何源。在这种情况下,Open WebUI 会在启动时记录一条警告。
要将其限制为您的域名:
CORS_ALLOW_ORIGIN=https://chat.yourcompany.com多个源之间用分号分隔:
CORS_ALLOW_ORIGIN=https://chat.yourcompany.com;https://internal.yourcompany.com如果您使用带有自定义 URL 协议(Scheme)的桌面应用,请通 过以下方式添加:
CORS_ALLOW_CUSTOM_SCHEME=app安全响应头(Security Headers)
Open WebUI 包含一个 SecurityHeadersMiddleware,用于在响应中注入 HTTP 安全头。默认情况下未设置任何安全头,因此您需要通过环境变量手动启用每一个。
以下是针对生产部署推荐的初始配置:
# HTTP Strict Transport Security: 告知浏览器仅使用 HTTPS
HSTS=max-age=31536000;includeSubDomains
# 防止页面被嵌入到其他网站的 iframe 中
XFRAME_OPTIONS=DENY
# 防止浏览器进行 MIME 类型嗅探
XCONTENT_TYPE=nosniff
# 控制请求中发送多少 Referrer 信息
REFERRER_POLICY=strict-origin-when-cross-origin
# 限制对浏览器功能的访问
PERMISSIONS_POLICY=camera=(),microphone=(),geolocation=()
# 内容安全策略 (CSP)
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 # 选项: unsafe-none, require-corp, credentialless
CROSS_ORIGIN_OPENER_POLICY=same-origin # 选项: unsafe-none, same-origin-allow-popups, same-origin
CROSS_ORIGIN_RESOURCE_POLICY=same-origin # 选项: same-site, same-origin, cross-origin
# 报告 API 端点配置
REPORTING_ENDPOINTS=default="https://your-report-collector.example/reports"如果您设置了内容安全策略(CSP),请从宽松的策略开始,逐步收紧。过于严格的 CSP 会破坏前端。在强制执行之前,使用 CONTENT_SECURITY_POLICY_REPORT_ONLY 测试策略。浏览器开发人员工具将向您显示哪些资源被阻止了。
同时设置 CROSS_ORIGIN_EMBEDDER_POLICY=require-corp 和 CROSS_ORIGIN_OPENER_POLICY=same-origin 将启用跨源隔离。这可能会破坏从第三方源加载的资源(例如外部图片、脚本或 iframe),除非这些资源显式设置了适当的 CORS 头。在部署前请进行彻底测试。
HTTPS 与 TLS
Open WebUI 自身不终止 TLS。请将其置于处理 HTTPS 的反向代理(Nginx, Caddy, HAProxy)之后。步骤分步代理配置请参阅 HTTPS 参考。
一旦启用了 HTTPS:
WEBUI_SESSION_COOKIE_SECURE=true
HSTS=max-age=31536000;includeSubDomains受信任的代理 IP
Open WebUI 使用 --forwarded-allow-ips 来确定哪些代理可以被信任并发送 X-Forwarded-For 头。默认情况下,这设置为 *(信任所有代理),这在 Open WebUI 处于单个反向代理后面的隔离网络中是合适的。如果您的网络拓扑更为复杂,请将其限制为您代理的 IP:
FORWARDED_ALLOW_IPS=192.168.1.100OAuth 与 SSO
如果您使用 OAuth/OIDC 提供商进行身份验证,可以通过几个选项来控制访问权限。
域名与群组限制
# 仅允许使用特定域名邮箱地址的用户登录
OAUTH_ALLOWED_DOMAINS=yourcompany.com
# 阻止特定的 IdP 群组
OAUTH_BLOCKED_GROUPS='["contractors-external", "temp-accounts"]'角色映射
将 IdP 角色映射到 Open WebUI 角色,以便在身份提供商处直接管理访问权限:
ENABLE_OAUTH_ROLE_MANAGEMENT=true
OAUTH_ROLES_CLAIM=roles
OAUTH_ADMIN_ROLES=admin,superadmin
OAUTH_ALLOWED_ROLES=user,admin,superadmin账号合并
OAUTH_MERGE_ACCOUNTS_BY_EMAIL=false启用后,如果 OAuth 登录的邮箱与现有本地账号匹配,则会将两者合并。不建议这样做。 这取决于您的 OAuth 提供商能够可靠地验证邮箱地址。如果您的提供商不能保证邮箱验证,控制了匹配邮箱的用户就可以获得现有账号的访问权限——实际上这是一种账号劫持。除非您已验证您的提供商强制执行邮箱 验证,否则请将此值保持为 false。
会话限制
# 每个用户每个提供商的最大并发 OAuth 会话数 (默认: 10)
OAUTH_MAX_SESSIONS_PER_USER=5
# 启用由 IdP 发起的后端通道退出(需要 Redis)
ENABLE_OAUTH_BACKCHANNEL_LOGOUT=true受信任的请求头身份验证
如果您的反向代理处理身份验证(Authelia, Authentik, oauth2-proxy),您可以通过 HTTP 头将已验证的身份传递给 Open WebUI。根据您的设置,这可行但存在风险——配置不当允许任何客户端通过伪造请求头来伪装成任意用户进行身份验证:
WEBUI_AUTH_TRUSTED_EMAIL_HEADER=X-Forwarded-Email
WEBUI_AUTH_TRUSTED_NAME_HEADER=X-Forwarded-Name使用受信任请求头时,您的反向代理必须在注入自己的值之前,从传入的客户端请求中清除这些请求头。如果代理没有清除它们,任何客户端都可以发送伪造的请求头并伪装成任意用户进行身份验证。这是受信任请求头身份验证中最常见的错误配置。请查阅您的反向代理文档,了解如何清除上游请求头。
LDAP
使用 LDAP 进行身份验证时,请启用 TLS 以保护传输中的凭据:
ENABLE_LDAP=true
LDAP_USE_TLS=true
LDAP_VALIDATE_CERT=true
LDAP_CA_CERT_FILE=/path/to/ca-cert.pem如果不使用 TLS,LDAP 凭据将以明文形式传输。如果需要,您可以通过 LDAP_CIPHERS 限制密码套件。
数据库
PostgreSQL
对于生产部署,PostgreSQL 比默认的 SQLite 提供了更好的并发性和可靠性:
DATABASE_URL=postgresql://user:password@db-host:5432/openwebui迁移详情请参阅 扩展指南。使用强且唯一的凭据,并将数据库保持在内部网络中。
SQLCipher
对于需要静态加密的 SQLite 部署,Open WebUI 支持 SQLCipher:
DATABASE_TYPE=sqlite+sqlcipher连接池调优
对于 PostgreSQL,调优连接池以匹配您的使用情况:
DATABASE_POOL_SIZE=15
DATABASE_POOL_MAX_OVERFLOW=20
DATABASE_POOL_TIMEOUT=30
DATABASE_POOL_RECYCLE=3600整个部署中的总连接数 = 连接池大小 x 实例数量。请将此值保持在您的 PostgreSQL max_connections 限制(默认 100)以下。
API Key
API Key 为程序提供了与创建该 Key 的用户具有相同权限的 Open WebUI 访问权限。
# 启用 API Key 创建 (默认:非管理员用户禁用)
ENABLE_API_KEYS=true端点限制
您可以限制 API Key 允许调用的 API 路由:
ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS=true
API_KEYS_ALLOWED_ENDPOINTS=/api/chat/completions,/api/v1/models这在将 Key 分发给外部服务或自动化系统时非常有用,因为您希望在 Key 泄露时限制其访问范围。
用户权限
默认情况下,只有管理员才能创建 API Key。要允许普通用户创建:
USER_PERMISSIONS_FEATURES_API_KEYS=true访问控制
Open WebUI 使用分层的权限系统,包含角色、群组和基于单资源的访问授权。
角色
| 角色 | 权限 |
|---|---|
admin | 完全系统访问权限、用户管理、所有配置 |
user | 对话访问权限、许可的模型和资源 |
pending | 无访问权限,直到被管理员批准 |
关键设置
# 新用户的默认角色 (默认: pending)
DEFAULT_USER_ROLE=pending
# 管理员是否绕过资源层级的访问控制 (默认: true)
BYPASS_ADMIN_ACCESS_CONTROL=true
# 管理员是否可以查看所有用户对话 (默认: true)
ENABLE_ADMIN_CHAT_ACCESS=true
# 所有用户是否可以无视群组限制访问所有模型 (默认: false)
BYPASS_MODEL_ACCESS_CONTROL=falseOpenAI API 直通(Passthrough)
ENABLE_OPENAI_API_PASSTHROUGH=falseOpenAI 路由包含一个全匹配的代理端点 (/{path:path}),可使用管理员配置的 API Key 将任何请求转发到上游的 OpenAI 兼容 API。这在默认情况下是禁用的,且应保持禁用状态。 启用后,任何经过身份验证的用户都可以使用管理员的凭据,绕过模型层级的访问控制,直接访问任何上游端点——包括 Open WebUI 原生未处理的端点。只有在您明确需要直接直通到上游 API 端点且了解其安全影响时,才启用此项。
数据共享与导出
有几项功能可以控制如何共享或导出数据:
# 允许用户与其他经过身份验证的用户共享对话 (默认: true)
ENABLE_COMMUNITY_SHARING=true
# 允许管理员从数据库批量导出所有用户对话 (默认: true)
ENABLE_ADMIN_EXPORT=true
# 允许用户使用自己的 API Key 在浏览器中直接连接模型提供商,
# 绕过服务器端的代理 (默认: false)
ENABLE_DIRECT_CONNECTIONS=falseENABLE_COMMUNITY_SHARING 允许用户为对话生成共享链接。任何获得链接的经过身份验证的用户都可以查看该对话。如果您的部署中包含敏感对话,请考虑将此项设置为 false。
ENABLE_DIRECT_CONNECTIONS 启用后,允许用户在浏览器中配置自己的 API Key 和模型端点。这些连接是由后端建立的,因此用户的 API Key 会被发送到 Open WebUI 服务器。这在默认情况下是关闭的。
工作区(Workspace)权限
这些 设置控制普通用户在共享工作区中可以执行的操作:
USER_PERMISSIONS_WORKSPACE_MODELS_ACCESS=false
USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ACCESS=false
USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS=false
USER_PERMISSIONS_WORKSPACE_PROMPTS_ACCESS=false全部默认为 false。群组层级的覆盖可以为特定的用户群组启用特定的权限。
审计日志(Audit Logging)
审计日志记录 API 活动,用于合规、调试和使用分析。默认情况下是禁用的。
AUDIT_LOG_LEVEL=METADATA| 级别 | 记录的内容 |
|---|---|
NONE | 不记录 (默认) |
METADATA | 用户、IP、User-Agent、方法、URL、时间戳 |
REQUEST | 元数据加上请求体 |
REQUEST_RESPONSE | 元数据加上请求和响应体 |
输出配置
# 写入到文件 (默认路径: /app/backend/data/audit.log)
ENABLE_AUDIT_LOGS_FILE=true
AUDIT_LOGS_FILE_PATH=/app/backend/data/audit.log
AUDIT_LOG_FILE_ROTATION_SIZE=10MB
# 同时发送到 stdout,对日志收集器很有用
ENABLE_AUDIT_STDOUT=true
# 每个请求/响应体捕获的最大字节数 (默认: 2048)
MAX_BODY_LOG_SIZE=2048路径过滤
# 仅审计特定路径 (白名单模式)
AUDIT_INCLUDED_PATHS=auths,users,configs
# 排除特定路径 (黑名单模式,默认)
AUDIT_EXCLUDED_PATHS=/chats,/chat,/folders身份验证端点(登录、退出登录、注册)始终会被审计,无论路径是否被排除。请求体中的密码会自动被遮蔽。
网络与出站请求
出站 TLS
Open WebUI 向模型 API、向量化(Embedding)提供商、Tool 服务器和网络搜索服务发起出站 HTTPS 请求。证书校验在默认情况下是开启的:
REQUESTS_VERIFY=true
AIOHTTP_CLIENT_SESSION_SSL=true
AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL=true
ENABLE_WEB_LOADER_SSL_VERIFICATION=true离线模式
对于物理隔离(Air-gapped)的环境:
OFFLINE_MODE=true这会禁用 HuggingFace Hub 下载、版本更新检查和其他出站调用。模型和向量化模型必须在本地可用。
SSRF 防范
RAG Web 加载器(Web Loader)可以从 URL 获取内容。默认情况下,它无法访问本地网络地址:
ENABLE_RAG_LOCAL_WEB_FETCH=false将此项设置为 true 会允许 Web 加载器从私有 IP 范围获取内容,这在某些环境中可能是必要的,但会带来 SSRF 风险。
Open WebUI 默认还会阻止云服务商的元数据端点(AWS 169.254.169.254、GCP metadata.google.internal、Azure metadata.azure.com 以及阿里云 100.100.100.200)。您可以使用其他域名或 IP 扩展此阻止列表:
WEB_FETCH_FILTER_LIST=!internal.yourcompany.com,!10.0.0.0/8在条目前加上 ! 以阻止它们。
出站 HTTP 请求默认也不会重定向(3xx)。如果没有这种限制,攻击者提供的 URL 可以通过对最初提交的主机的白名单检查,然后通过 302 重定向到内网地址(RFC 1918、127.0.0.1、云服务商元数据 IP),而无需重新校验。默认设置在 RAG Web 加载器、图像加载、OAuth 预检、代码解释器登录和 Tool 服务器执行中关闭了这种绕过方式。除非您有特定需求(例如短链接 URL)且已部署其他 SSRF 保护措施,否则请保持默认设置:
AIOHTTP_CLIENT_ALLOW_REDIRECTS=false头像 URL 转发
用户和模型头像的端点可以发起 302 Found 重定向到存储在 profile_image_url 中的任何源,以便在 UI 中显示外部托管的头像(例如通过上游身份提供商的 Gravatar)。该重定向会导致用户的浏览器直接向外部源发起请求,从而泄漏客户端 IP、User-Agent 和 Referer 响应头——如果某个账号的 profile_image_url 被设置为攻击者控制的主机,攻击者就可 以利用这一点去匿名化任何渲染了该头像的人。
要完全压制此类重定向并改为提供捆绑的默认图像:
ENABLE_PROFILE_IMAGE_URL_FORWARDING=false默认值为 true,以确保依赖外部头像的现有部署正常工作。Base64 格式的 Data URI、同源或静态图片不受此标志影响——它们继续正常渲染。
存储为 Base64 data: URI 的头像还受到 MIME 类型白名单的限制。默认值为 image/png,image/jpeg,image/gif,image/webp;SVG 被故意排除在外,因为它可能携带内联 <script>。响应还会设置 X-Content-Type-Options: nosniff,以便浏览器无法将非图片载荷嗅探为可执行类型。如需进一步缩小范围(例如仅限 PNG/JPEG),请设置:
PROFILE_IMAGE_ALLOWED_MIME_TYPES=image/png,image/jpegiframe 内容安全策略(CSP)
对于 Artifacts、代码/HTML 预览、文件预览和引用模态 框,Open WebUI 会在 srcdoc iframe 中渲染 LLM 生成的以及用户上传的 HTML。这些 iframe 上的 sandbox 属性提供了基础隔离。对于希望对所渲染 HTML 的行为(尤其是出站网络请求)进行更强限制的部署,可以设置注入到每个 iframe 文档中的 CSP:
IFRAME_CSP=default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; connect-src 'none'上述示例允许内联脚本在沙箱内运行(这是大多数 Artifacts 所需的),但阻止了所有的 fetch/XMLHttpRequest/WebSocket 流量——当您不希望模型能够通过生成的 Artifact 外泄会话数据时,这非常有用。您可以根据需要进行收紧或放宽;过于严格的策略将破坏合法的 Artifacts。
文件上传限制
默认情况下,对上传的文件没有大小或数量限制。要防止存储耗尽:
# 单文件最大大小 (单位: MB, 默认无限制)
RAG_FILE_MAX_SIZE=50
# 单次上传操作的最大文件数量 (默认无限制)
RAG_FILE_MAX_COUNT=10
# 限制允许的文件扩展名 (留空 = 允许所有)
RAG_ALLOWED_FILE_EXTENSIONS=.pdf,.txt,.md,.docx,.csvTool、Function 与 Pipeline
Tool(工具)和 Function(函数)在您的服务器上运行任意 Python 代码,其访问权限与 Open WebUI 进程相同。这是它们工作原理的核心,这意味着它们可以读取文件、发起网络请求、访问环境变量以及与数据库进行交互。
有关安全模型的详细信息,请参阅 安全政策。
由于 Tool 和 Function 执行服务器端代码,因此任何拥有创建或导入权限的用户实际上都拥有与 Open WebUI 进程本身相同的访问级别。这是可扩展性工作原理所固有的。默认情况下,只有管理员可以创建和导入 Tool 和 Function。以下设置控制这些权限。
代码执行
Open WebUI 默认启用了两项代码执行功能:
# 允许执行对话回复中的代码块 (默认: true, 引擎: pyodide)
ENABLE_CODE_EXECUTION=true
CODE_EXECUTION_ENGINE=pyodide
# 允许模型将运行代码作为其推理的一部分 (默认: true, 引擎: pyodide)
ENABLE_CODE_INTERPRETER=true
CODE_INTERPRETER_ENGINE=pyodide默认引擎为 pyodide,它通过 WebAssembly 在浏览器中运行 Python,不会在服务器上执行代码。如果您切换到 Jupyter (jupyter),代码将在 Jupyter 服务器上运行,该服务器具有服务器端访问权限。如果使用此引擎,请相应地保护 Jupyter 实例的安全。
安全模式(Safe Mode)
如果某个 Function 在启动时引发问题,您可以通过在安全模式下启动来停用所有 Function:
SAFE_MODE=true这使您能够访问管理员面板并禁用有问题的 Function。
依赖安装
Tool 和 Function 可以在其 Frontmatter 中声明 Python 依赖。默认情况下,这些依赖会通过 pip 自动安装:
# 设置为 false 以阻止从 tool/function 的 frontmatter 自动进行 pip 安装
ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS=false禁用此项可防止上传的 Tool 在运行时拉取任意依赖包。在生产部署中,特别是那些允许非管理员用户创建 Tool 的部署中,此项应设置为 false。
工作区访问
控制谁可以创建、导入和共享 Tool 与 Function:
USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS=false
USER_PERMISSIONS_WORKSPACE_TOOLS_IMPORT=false
USER_PERMISSIONS_WORKSPACE_SKILLS_ACCESS=false全部默认为 false,这意味着只有管理员才能管理 Tool 和 Function。除非您有特定需求且信任被授予访问权限的用户,否则请 保持这些限制。
容器加固
基础镜像
默认的 Dockerfile 使用 python:3.11-slim-bookworm。如果您的组织需要加固或经过批准的基础镜像,您可以通过修改 Dockerfile 中的 FROM 行来替换它。这在强制使用最小化、经过漏洞扫描的基础镜像的企业环境中非常常见。
非 root 用户执行
Dockerfile 支持作为非 root 用户运行:
docker build --build-arg UID=1000 --build-arg GID=1000 .OpenShift 兼容性
对于以任意 UID 运行容器的环境(如 OpenShift):
docker build --build-arg USE_PERMISSION_HARDENING=true .数据目录
数据目录(/app/backend/data)包含数据库、上传的文件、缓存的插件以及自动生成的密钥。请使用适当的文件系统权限保护此目录,并将其纳入您的备份策略中。
开发功能
Docker 镜像默认设置 ENV=prod,这将禁用位于 /docs 的 Swagger/OpenAPI 文档 UI。如果手动运行,请设置 ENV=prod 以确保这些端点不会暴露。
可观测性
结构化日志
LOG_FORMAT=json
GLOBAL_LOG_LEVEL=INFOJSON 日志是为 ELK、Datadog 或 Splunk 等日志收集器设计的。
OpenTelemetry
ENABLE_OTEL=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://your-collector:4317
OTEL_SERVICE_NAME=open-webui有关完整设置,请参阅 监控 和 Open WebUI 日志记录。
SCIM 自动配置(Provisioning)
SCIM 2.0 允许您的身份提供商自动管理用户账户:
ENABLE_SCIM=true
SCIM_TOKEN=your-bearer-token
SCIM_AUTH_PROVIDER=oidcSCIM Token 是一个静态 Bearer Token,它授予完全的用户管理访问权限。请像对待管理员凭据一样对待它,定期轮换,且仅通过 HTTPS 传输。
保持 Open WebUI 更新
运行最新版本的 Open WebUI 有助于让您的部署与最新的安全补丁和 修复保持同步。检查 变更日志 (Changelog) 获取安全相关的更新并及时应用。
对于 Docker 部署,拉取最新镜像并重新创建容器:
docker pull ghcr.io/open-webui/open-webui:main对于多副本部署,请遵循 滚动更新流程 以避免停机。
快速参考
下表总结了本指南中涵盖的关键加固行动。每一行都链接到相关章节以获取详细信息。
| 行动 | 默认值 | 生产环境推荐 |
|---|---|---|
| 保持在私有网络中 | 无限制 | VPN、防火墙或零信任代理 |
| 通过 HTTPS 服务 | HTTP | 通过反向代理启用 HTTPS |
设置 WEBUI_SECRET_KEY (多副本) | 自动生成 | 显式共享密钥 |
| 审查注册政策 | 首个用户注册后禁用 | 保持禁用或使用 pending 角色 |
| 启用密码验证 | 禁用 | ENABLE_PASSWORD_VALIDATION=true |
| 安全 Cookie | Secure=false, SameSite=lax | Secure=true, SameSite=strict |
| 启用 Token 撤销 | 无撤销 (无 Redis) | 配置 Redis 或缩短 JWT_EXPIRES_IN |
| 限制 CORS | * | 您的特定域名 |
| 设置安全响应头 | 无 | HSTS、X-Frame-Options、CSP、跨源策略 |
| 限制 OAuth 域名 | 允许所有 | OAUTH_ALLOWED_DOMAINS=yourdomain.com |
| 启用审计日志 | NONE | METADATA 或更高 |
| 限制 API Key 端点 | 所有端点 | ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS=true |
| 保持 API 直通禁用 | 禁用 | 保持 ENABLE_OPENAI_API_PASSTHROUGH=false |
| 禁用自动 pip 安装 | 启用 | ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS=false |
| 审查社区共享 | true | 若涉及敏感数据则禁用 |
| 审查直接连接 | false | 除非需要,否则保持禁用 |
| 使用 PostgreSQL | SQLite | PostgreSQL |
| 验证出站 TLS | 启用 | 保持启用 |
| 启用离线模式 | 禁 用 | 物理隔离环境使用 OFFLINE_MODE=true |
| 结构化日志 | 文本 | LOG_FORMAT=json |
| 保持更新 | 无 | 最新稳定版本 |
安全至上的部署实践
对于将安全放在首位的组织,以下实践定义了推荐的部署基线。每一项都针对部署的不同层级,共同提供深度防御。每一项都链接到上文的相关章节以获取详细配置。
网络与传输
-
将 Open WebUI 部署在具有限流和 IP 白名单的 VPN、反向代理或零信任访问层之后。 Open WebUI 是为私有、受信任的网络构建的。在没有额外访问控制层保护的情况下,切勿将其直接暴露在公网上。配置您的反向代理以限制连接速率、限制重复的身份验证尝试、限制对已知 IP 范围的访问,并使用 fail2ban 等工具阻止恶意源。将
--forwarded-allow-ips限制为您代理的 IP,以防止请求头伪造。详情 -
通过 HTTPS 传输所有流量并启用所有安全响应头。 使用终止 TLS 的反向代理。配置会话 Cookie 属性为
Secure=true和SameSite=strict。切勿在生产环境里通过纯 HTTP 协议服务 Open WebUI。启用 HSTS、内容安 全策略 (CSP)、X-Frame-Options、X-Content-Type-Options、Referrer-Policy 和 Permissions-Policy。不要将 CORS 保持为*,请将其限制在需要访问的精确域名上。详情
身份验证与访问控制
-
保持注册功能关闭。 Open WebUI 会在首个用户注册后自动关闭注册。任何新账号的默认角色为
pending,这需要管理员显式批准才能访问任何功能。在受信任网络之外可访问的实例上,切勿重新开启开放注册。详情 -
与您的身份提供商使用 SSO 并禁用本地身份验证。 与您组织的 OAuth/OIDC 或 LDAP 提供商集成。限制对特定邮箱域名和 IdP 群组的访问,将 IdP 角色映射到 Open WebUI 角色,并完全禁用本地登录表单和密码身份验证。限制每个用户的并发会话,使用 Redis 启用后端通道退出,以便在用户停用时立即撤销会话,且除非您的提供商保证邮箱验证,否则不要启用 OAuth 账号合并。详情
-
强制执行密码复杂度并缩短会话生命周期。 如果使用本地账号,请启用密码验证。将默认的 JWT 有效期从 4 周缩短为适合您环境的更短持续时间(例如 8 至 24 小时)。切勿在生产环境里禁用 Token 过期。详情
-
定期审查用户账号和权限。 移除不活跃账号,审计群组成员关系,并验证工作区权限是否保持合适。使用 SCIM 自动配置来通过您的身份提供商自动化账号生命周期管理。详情
Tool、Function 与扩展
-
将 Tool 和 Function 的创建权限限制为仅限管理员,并在导入前审查所有代码。 默认情况下,只有管理员才能创建、导入和管理 Tool 和 Function。不要向不受信任的用户授予工作区权限。像对待运行在您基础设施上的任何代码一样审慎对待第三方 Tool。切勿在未经源代码审查前导入 Tool。详情
-
禁用自动依赖项安装,并在不需要时禁用代码执行。 设置
ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS=false以防止 Tool 在运行时拉取任意包。如果您的部署不需要在对话中执行代码,请完全禁用它。如果需要,请保持默认的pyodide引擎,它是在浏览器中运行的,而不是在服务器上。切勿在未对 Jupyter 实例进行安全保护的情况下切换到 Jupyter 引擎。保持直接连接和直接 Tool 服务器禁用。详情
数据保护
-
限制数据共享、文件上传和 API Key 访问。 设置最大文件大小、文件数量限制,并限制允许的文件扩展名。如果业务上不需要,请禁用社区共享 (
ENABLE_COMMUNITY_SHARING=false) 和管理员批量导出 (ENABLE_ADMIN_EXPORT=false)。保持 API Key 的创建限制为仅限管理员,并启用端点限制以限制每个 Key 可以访问的路由。详情 -
对静态数据进行加密并保持定期备份。 对于 SQLite,请使用 SQLCipher。对于 PostgreSQL,请使用磁盘级或透明数据加密(TDE)。保持定期备份,将它们存储在独立的安全域中,并定期测试您的还原流程。详情
出站网络控制
- 保持 SSRF 保护、出站 TLS 校验和网络限制开启。 不要启用本地网页获取(Local Web Fetch)。默认配置会阻止访问私有 IP 范围和云服务商元数据端点;请将阻止列表扩展到包含您环境特有的内部域名。切勿禁用出站连接的证书校验。对于物理隔离的环境,启用离线模式以禁用所有出站调用。详情
供应链与变更管理
-
使用官方容器镜像,或从源码构建。 从 Docker Hub 上的
ghcr.io/open-webui/open-webui或openwebui/open-webui拉取镜像。为了完全控制供应链,请使用提供的 Dockerfile 直接从源码进行构建。切勿使用非官方或第三方镜像。详情 -
固定到特定的发布版本,并在部署前验证更新。 使用带标签的 Release 版本,而不是
:main或:latest。在升级前审查变更日志。在将新版本推广到生产环境前,先在预发(Staging)环境中进行验证,并保持回滚能力。切勿自动更新生产部署。详情
容器与基础设施
- 在分段网络上以非 root 用户和最小权限运行。 使用非 root UID/GID,尽可能使用只读文件系统挂载,丢弃所有不必要的 Linux 功能,并设置
--security-opt=no-new-privileges。对数据目录应用限制性权限(例如0700)。在独立的网络段上使用具有强凭据的 PostgreSQL,不可从公网访问。详情