# OpenWebUI 二次开发指南

## 📖 目录
- [数据库配置](#-数据库配置)
  - [连接参数配置](#连接参数配置)
- [开发模式启动](#-开发模式启动)
  - [系统要求](#系统要求)
  - [安装ollama](#安装ollama)
  - [克隆项目](#克隆项目)
  - [前端配置](#前端配置)
  - [后端配置](#后端配置)
- [生产环境部署](#-生产环境部署)
  - [编译前端](#编译前端)
  - [反向代理配置（windows）](#反向代理配置windows)

---

## 📦 数据库配置

### 连接参数配置
该项目原本只支持Sqlite，postgresql，如需支持其他库，要修改挺多代码的，不过不复杂，可以研究。
- 在 .env文件中加上一下内容
```bash
# 不配置postgresql，默认会使用Sqlite
# 配置postgresql只需要在环境变量中申明
# 数据库中可以没有任何信息，项目启动的时候自己会建表
DATABASE_URL="postgresql://myuser:mysecretpassword@localhost:5432/mydatabase"
```
- 配置系统环境变量
```bash
export DATABASE_URL="postgresql://myuser:mysecretpassword@localhost:5432/mydatabase"
```

当前测试postgresql是用一下docker命令搭建的
```bash
sudo docker pull postgres
sudo docker run -d \
  --name my-postgres \
  --restart unless-stopped \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydatabase \
  -p 5432:5432 \
  -v postgres_data:/var/lib/postgresql/data \
  postgres:latest
```



---

## ⚙️ 开发模式启动

### 系统要求
**最低运行环境需求**：
- **操作系统**：Linux（或 Windows 的 WSL）/macOS
- **Python 版本**：3.11+ 
- **Node.js 版本**：22.10+
- **内存**：建议 4GB 以上
- **磁盘空间**：至少 2GB 可用空间

### 安装ollama
```bash
# docker 下载镜像
sudo docker pull ollama/ollama
# 创建本地存储目录
mkdir -p ~/ollama-data

# 运行容器并挂载目录
sudo docker run -d -p 11434:11434 -v ~/ollama-data:/root/.ollama --restart unless-stopped --network host --name ollama olla
ma/ollama
```

### 克隆项目
```bash
git clone https://XXXXXXXX/open-webui.git
cd open-webui
```

### 前端配置
- 创建 .env 文件:
```bash
# linux/Unix
cp -RPp .env.example .env
# windows
Copy-Item -Path .env.example -Destination .env -Force
```
- 安装依赖
```bash
npm install
```


- 启动前端服务
```bash
npm run dev
```

### 后端配置
- 进入后端目录
```bash
cd backend
```
- 安装虚拟环境
```bash
conda create --name open-webui python=3.11
conda activate open-webui
```
- 安装依赖
```bash
pip install -r requirements.txt -U -i https://pypi.tuna.tsinghua.edu.cn/simple
```
- 启动后端
这种启动后端遇到跨域问题没法解决，开发模式暂时用生产环境部署方式进行开发
```bash
sh dev.sh
```
- hugging face模型下载失败的问题，配置环境
```bash
import os

# 在导入任何 huggingface_hub 模块前设置环境变量
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

from huggingface_hub import snapshot_download
from sentence_transformers import SentenceTransformer

# 示例：下载模型
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
```

---
## 二次开发修改的地方

### 静态资源

---

## 🚀 生产环境部署

### 编译前端
```bash
npm run build
#如果运到内存不足，请使用
NODE_OPTIONS="--max-old-space-size=4096" npm run build
```

### 数据库配置
```bash
# windows 上配置环境变量
# 密码含特殊字符：将password中的@ $等字符替换为%40 %24
DATABASE_URL="postgresql://myuser:mysecretpassword@localhost:5432/mydatabase"
```### 反向代理配置（windows）
```nginx
# nginx-1.26.3（windows）
#user  nobody;
worker_processes  1;

error_log  logs/error.log debug;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    # 全局优化
    client_max_body_size 100M; # 允许大文件上传

    # 压缩传输
    gzip on;

    server {
        listen       3443;
        server_name  localhost;
        # 指向构建后的静态文件目录（使用相对路径）
        location / {
            proxy_pass http://localhost:8080;
            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;
        }

        # 从 /auth 页面提取参数到变量
        location /auth {
            add_header Set-Cookie "auth_token=$arg_token; Path=/api/; HttpOnly";
            # 存储参数到变量（需确保前端页面和 API 在同一个请求会话中）
            set $auth_token $arg_token;
            proxy_pass http://localhost:8080/auth;
        }

        # 代理后端API请求（关键配置）
        location /api/ {
            proxy_pass http://localhost:8080/api/;  # 后端服务地址
            # 连接后端超时（默认60秒）
            proxy_connect_timeout 60s;
            # 发送请求到后端的超时（默认60秒）
            proxy_send_timeout 600s;
            # 从后端读取响应的超时（默认60秒）
            proxy_read_timeout 600s;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # 将 Cookie 值作为请求头或查询参数传递
            proxy_set_header X-Trusted-Token $cookie_auth_token;
        }
        # 处理/ws路径的Socket.IO连接（需添加协议升级头）
        location /ws/ {
            proxy_pass http://localhost:8080;
            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_read_timeout 86400; # 保持长连接
        }

        # 其他路由代理（根据FastAPI挂载路径）
        location ~ ^/(ollama|openai|users|chats|models|files|retrieval)/ {
            proxy_pass http://localhost:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        # 若静态文件通过FastAPI服务（如/static和/cache路径）
        location /static/ {
            proxy_pass http://localhost:8080/static/;
            expires 30d; # 缓存优化
        }

        location /cache/ {
            proxy_pass http://localhost:8080/cache/;
            expires 1h;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
```

### 单点登录环境变量配置
```bash
# 信任邮箱和密码一定要配置，具体值是多少无所谓，可以拷贝
WEBUI_AUTH_TRUSTED_EMAIL_HEADER=X-Trusted-Email
WEBUI_AUTH_TRUSTED_NAME_HEADER=X-Trusted-Name
# 信任的token键值都是固定的，和nginx中配置一致
WEBUI_AUTH_TRUSTED_TOKEN_HEADER=X-Trusted-Token
```

### 单点登录使用
- 先生成token，最好带时间，保证token值变动，生成的例子看backend\open_webui\test\token_for_signin.py
- 然后直接跳转：
```bash
# localhost 改成具体的IP值
http://localhost:3443/auth?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20iLCJuYW1lIjoiVGVzdCBVc2VyIiwiZXhwIjoxNzQyNTQxNTQwfQ.vcSVmvGazhahzN7azwxiGF8v9v8iolNF3dF8g4Sl5Zc
```




