# Collabora 正确配置全流程

## 1. 文档目标

本文档用于沉淀 LeAudit 当前 Collabora 集成的**正确配置全流程**，便于：

- 本机继续维护
- 迁移到新服务器
- 上线前后按清单验收
- 遇到故障时快速排查

本文档同时包含两类信息：

- 当前环境已经验证可用的实际配置
- 可迁移到其他服务器的模板化配置说明

当前已验证可用的主链路为：

```text
http://172.16.0.59:5173
```

注意：

**浏览器入口、前端生成的 WOPI 地址、Collabora iframe 地址、nginx 转发头、Collabora 白名单、CSP 的 host 必须完全一致。**

如果后续要改成域名方案，必须整套一起切换，不要域名/IP 混用。

---

## 2. 参数模板

迁移到新服务器时，建议先把下面这些参数定义清楚，再开始修改配置：

```text
<PROJECT_ROOT>              LeAudit 项目根目录
<COLLABORA_DEPLOY_ROOT>     Collabora 部署目录
<APP_HOST>                  浏览器实际访问的主机名或 IP
<APP_PORT>                  前端代理入口端口，默认 5173
<FRONTEND_DEV_PORT>         Next 开发服务端口，默认 5193
<BACKEND_PORT>              后端服务端口，默认 8096
<COLLABORA_PORT>            Collabora 容器端口，默认 9980
<DOCUMENT_BASE_URL>         文档读写后端基础地址
```

当前环境对应值：

```text
<PROJECT_ROOT>          = /home/wren-dev/Porject/leaudit-platform
<COLLABORA_DEPLOY_ROOT> = /home/wren-dev/Porject/collabora-backup
<APP_HOST>              = 172.16.0.59
<APP_PORT>              = 5173
<FRONTEND_DEV_PORT>     = 5193
<BACKEND_PORT>          = 8096
<COLLABORA_PORT>        = 9980
<DOCUMENT_BASE_URL>     = http://172.16.0.59:8096/docauditai/
```

---

## 3. 当前架构

当前链路如下：

1. 浏览器访问前端入口：`http://172.16.0.59:5173`
2. `5173` 上运行 nginx 代理
3. nginx 将普通前端请求转发到 Next：`127.0.0.1:5193`
4. nginx 将 Collabora 请求转发到容器：`127.0.0.1:9980`
5. 前端通过 `/api/collabora/config` 生成：
   - `iframeUrl`
   - `WOPISrc`
6. Collabora 再通过 `/wopi/files/...` 回调前端获取文件信息与文件内容

简化后的链路：

```text
Browser
  -> 172.16.0.59:5173
    -> nginx proxy
      -> 127.0.0.1:5193   (Next 前端)
      -> 127.0.0.1:9980   (Collabora)
```

---

## 4. 关键目录与文件

### 4.1 项目目录

```text
<PROJECT_ROOT>
```

当前实际值：

```text
/home/wren-dev/Porject/leaudit-platform
```

### 4.2 Collabora 部署目录

```text
<COLLABORA_DEPLOY_ROOT>
```

当前实际值：

```text
/home/wren-dev/Porject/collabora-backup
```

### 4.3 本次关键文件

- 前端环境变量
  - `legal-platform-frontend/.env`
- Collabora iframe 配置生成
  - `legal-platform-frontend/lib/services/collabora.config.server.ts`
- nginx 代理配置
  - `deploy/collabora-proxy/conf.d/collabora.conf`
- Collabora compose 配置
  - `/home/wren-dev/Porject/collabora-backup/docker-compose.yml`
- Collabora 主配置
  - `/home/wren-dev/Porject/collabora-backup/coolwsd-config/coolwsd.xml`

---

## 5. 前置要求

开始前请确认：

- Docker 可用
- Docker Compose 可用
- 前端、后端可正常启动
- 目标服务器开放需要的端口
- Collabora 镜像已准备好

如需重新导入镜像：

```bash
docker load -i <COLLABORA_DEPLOY_ROOT>/collabora-image-v5.tar
```

当前环境示例：

```bash
docker load -i /home/wren-dev/Porject/collabora-backup/collabora-image-v5.tar
```

需要重点确认的端口：

- `<APP_PORT>`
- `<BACKEND_PORT>`
- `<COLLABORA_PORT>`

---

## 6. 前端正确配置

文件：`legal-platform-frontend/.env`

### 6.1 当前已验证可用配置

```env
API_BACKEND_TARGET=http://172.16.0.59:8096
APP_URL=http://172.16.0.59:5173
DOCUMENT_URL=http://172.16.0.59:8096/docauditai/
COLLABORA_URL=http://172.16.0.59:5173
```

### 6.2 模板写法

迁移到新服务器时，替换为：

```env
API_BACKEND_TARGET=http://<APP_HOST>:<BACKEND_PORT>
APP_URL=http://<APP_HOST>:<APP_PORT>
DOCUMENT_URL=http://<APP_HOST>:<BACKEND_PORT>/docauditai/
COLLABORA_URL=http://<APP_HOST>:<APP_PORT>
```

### 6.3 每个变量的作用

- `APP_URL`
  - 决定 `WOPISrc`
  - 必须与浏览器实际访问入口一致
- `COLLABORA_URL`
  - 决定 iframe 中 `cool.html` 的主机与端口
- `API_BACKEND_TARGET`
  - 前端调用后端 API 的入口
- `DOCUMENT_URL`
  - WOPI 获取文件、写回文件时使用的后端文档基础地址

### 6.4 为什么必须统一

如果浏览器入口是：

- `http://172.16.0.59:5173`

但前端却生成：

- `http://nas.7bm.co:5173/wopi/files/...`
- `http://nas.7bm.co:5173/browser/dist/cool.html`

就会出现：

- 父页面是 IP
- iframe 是域名
- WOPI 又是另一个 host
- 浏览器按跨源处理
- 最终触发 iframe 拒绝加载、CSP 冲突、`chrome-error://chromewebdata/`

所以前端配置必须与最终入口完全一致。

---

## 7. Collabora iframe 参数生成

文件：`legal-platform-frontend/lib/services/collabora.config.server.ts`

### 7.1 当前逻辑

- `WOPISrc = ${APP_URL}/wopi/files/${encodeURIComponent(fileId)}`
- `cool.html = ${COLLABORA_URL}/browser/dist/cool.html?...`

### 7.2 当前建议保留的 UI 默认项

```ts
const uiDefaults = [
  "UIMode=compact",
  "TextRuler=false",
  "TextStatusbar=false",
  "TextSidebar=false",
].join(";")
```

### 7.3 已移除的项

- `SavedUIState=false`

原因：

- Collabora 会输出：
  - `unknown UI default's component SavedUIState`
- 该项不是必须项，移除后可减少无关噪音日志

---

## 8. nginx 代理正确配置

文件：`deploy/collabora-proxy/conf.d/collabora.conf`

### 8.1 必须代理的路径

以下路径必须明确代理：

- `/wopi/`
- `/browser/`
- `/cool/`
- `/coolws/`
- `/hosting/`
- `/loleaflet/`
- `/`

### 8.2 路径作用

- `/wopi/`
  - 前端本地 WOPI 接口
- `/browser/`
  - Collabora 页面与静态资源
- `/cool/`
  - 文档会话相关路径
- `/coolws/`
  - websocket 子通道
- `/hosting/`
  - discovery 接口
- `/loleaflet/`
  - Collabora 相关资源
- `/`
  - 普通前端页面与 API

### 8.3 Collabora 相关转发头

对 Collabora 相关 location，必须统一：

```nginx
proxy_set_header Host <APP_HOST>:<APP_PORT>;
proxy_set_header X-Forwarded-Host <APP_HOST>:<APP_PORT>;
proxy_set_header X-Forwarded-Proto $scheme;
```

当前环境实际值：

```nginx
proxy_set_header Host 172.16.0.59:5173;
proxy_set_header X-Forwarded-Host 172.16.0.59:5173;
proxy_set_header X-Forwarded-Proto $scheme;
```

### 8.4 前端主路由需要补的头

```nginx
proxy_set_header X-Forwarded-Port $server_port;
```

### 8.5 为什么 `/coolws/` 不能漏

如果遗漏 `/coolws/`，就会出现：

- `WOPI` 文件接口已经返回 `200`
- `cool.html` 也能打开
- 但 websocket 子通道建立失败
- 文档仍无法进入编辑状态

本次修复中，`/coolws/` 是一个关键缺失点。

### 8.6 错误跳转修复

针对 Next 开发环境错误返回的绝对地址，需要增加：

```nginx
proxy_redirect http://127.0.0.1:<FRONTEND_DEV_PORT>/ http://<APP_HOST>:<APP_PORT>/;
proxy_redirect http://localhost:<FRONTEND_DEV_PORT>/ http://<APP_HOST>:<APP_PORT>/;
```

当前环境实际值：

```nginx
proxy_redirect http://127.0.0.1:5193/ http://172.16.0.59:5173/;
proxy_redirect http://localhost:5193/ http://172.16.0.59:5173/;
```

否则可能出现：

- 浏览器跳到 `localhost:5193/login?...`
- 远端用户直接无法访问

### 8.7 迁移到新服务器时要替换的项

- `listen 5173;`
- `proxy_pass http://127.0.0.1:5193`
- `proxy_pass http://127.0.0.1:9980`
- 所有 `Host <APP_HOST>:<APP_PORT>`
- 所有 `X-Forwarded-Host <APP_HOST>:<APP_PORT>`
- 所有 `proxy_redirect`

---

## 9. Collabora Docker Compose 正确配置

文件：`<COLLABORA_DEPLOY_ROOT>/docker-compose.yml`

### 9.1 当前关键配置

```yaml
services:
  collabora:
    image: docker-collabora:v5
    container_name: collabora_code
    privileged: true
    ports:
      - "9980:9980"
    environment:
      - "domain=.*"
      - "extra_params=--o:ssl.enable=false --o:ssl.termination=false --o:logging.level=warning --o:security.seccomp=false"
```

### 9.2 不要再保留旧参数

不要再使用：

```text
--o:net.frame_ancestors=http://*
```

原因：

- 这是过时配置
- 会污染最终 `Content-Security-Policy`
- 会让 `frame-ancestors` 混乱
- 浏览器会直接拦 iframe

### 9.3 当前正确做法

- 删除 `net.frame_ancestors`
- 在 `coolwsd.xml` 中显式设置 `content_security_policy`

### 9.4 新服务器迁移要点

迁移时需要确认：

- 镜像已导入
- `docker-compose.yml` 中挂载目录存在
- 插件目录存在：
  - `mycustom_collabora_plugins`
- 脚本目录存在：
  - `custom_python_scripts`
- `<COLLABORA_PORT>` 未被占用

---

## 10. Collabora 主配置正确写法

文件：`<COLLABORA_DEPLOY_ROOT>/coolwsd-config/coolwsd.xml`

### 10.1 WOPI 白名单

模板写法：

```xml
<alias_groups mode="groups">
    <group>
        <host desc="Frontend Host" allow="true">http://<APP_HOST_REGEX>:<APP_PORT></host>
    </group>
</alias_groups>
```

当前环境实际值：

```xml
<alias_groups mode="groups">
    <group>
        <host desc="LAN Frontend" allow="true">http://172\.16\.0\.59:5173</host>
    </group>
</alias_groups>
```

### 10.2 CSP 配置

模板写法：

```xml
<content_security_policy>frame-ancestors http://<APP_HOST>:<APP_PORT>;</content_security_policy>
```

当前环境实际值：

```xml
<content_security_policy>frame-ancestors http://172.16.0.59:5173;</content_security_policy>
```

### 10.3 不推荐写法

不要再使用复杂 alias 正则，例如：

```xml
http://172\.16\.0\.[0-9]{1,3}(:[0-9]{1,5})?
```

这在当前环境中已经实测触发过：

- `Invalid regular expression for allowed host`
- `Bad URI syntax`

因此当前方案统一改为显式 host。

---

## 11. 正确重启顺序

### 11.1 前后端

```bash
cd <PROJECT_ROOT>
./leaudit.sh restart
```

### 11.2 代理

```bash
docker restart leaudit-collabora-proxy
```

### 11.3 Collabora

推荐直接强制重建，而不是简单 restart：

```bash
cd <COLLABORA_DEPLOY_ROOT>
docker-compose up -d --force-recreate collabora
```

### 11.4 为什么要 force-recreate

如果只执行：

```bash
docker restart collabora_code
```

旧容器里的环境变量可能仍保留，尤其是：

- `extra_params`

本次就遇到过：

- compose 文件已经删掉了 `net.frame_ancestors`
- 但旧容器环境里仍残留该参数
- 只有 `--force-recreate` 之后才真正清理干净

### 11.5 推荐标准重建流程

```bash
cd <PROJECT_ROOT>
./leaudit.sh restart

docker restart leaudit-collabora-proxy

cd <COLLABORA_DEPLOY_ROOT>
docker-compose up -d --force-recreate collabora
```

---

## 12. 正确验证步骤

### 12.1 验证前端入口

```bash
curl -I http://<APP_HOST>:<APP_PORT>/
```

期望：

- 返回 `307`
- 跳转到 `http://<APP_HOST>:<APP_PORT>/login?...`

当前环境示例：

```bash
curl -I http://172.16.0.59:5173/
```

### 12.2 验证 discovery

```bash
curl -I http://<APP_HOST>:<APP_PORT>/hosting/discovery
```

期望：

- `200 OK`

### 12.3 验证 Collabora 页面

```bash
curl -I http://<APP_HOST>:<APP_PORT>/browser/dist/cool.html
```

期望：

- `200 OK`
- 响应头包含 `Content-Security-Policy`
- `frame-ancestors` 围绕当前 `<APP_HOST>:<APP_PORT>` 收口

### 12.4 验证 WOPI 文件接口

通过页面实际访问时，日志里应看到：

```text
GET /wopi/files/... 200
```

### 12.5 验证 websocket 子通道

Collabora 日志中应能看到类似：

- `/coolws/forkit`
- `/coolws/newchild`
- `Upgrading to WebSocket`

这说明文档会话已建立。

### 12.6 上线验收清单

上线到新服务器后，至少完成以下验收：

- 能打开登录页
- 能成功登录
- 能打开 2~3 个不同文档
- 能进入编辑态
- 能保存并再次打开
- 浏览器控制台不再出现：
  - `refused to connect`
  - `chrome-error://chromewebdata/`
  - `Framing ... violates Content Security Policy`
- Collabora 日志不再出现：
  - `Invalid regular expression for allowed host`
  - `Bad URI syntax`
  - `No authorized hosts found`

---

## 13. 浏览器侧正确测试方式

如果浏览器之前已经打开过：

- `nas.7bm.co`
- 或旧的失败 iframe 页面

即使后端已经修好，也可能继续残留：

- `chrome-error://chromewebdata/`
- 错误 iframe 上下文
- 跨源错误

### 正确做法

1. 关闭旧标签页
2. 打开无痕窗口
3. 只访问：
   - `http://<APP_HOST>:<APP_PORT>/login`
4. 登录后直接进入文档页面
5. 不要从旧域名页面跳转到新 IP 页面

当前环境示例：

- `http://172.16.0.59:5173/login`

---

## 14. 本次实际修复过的问题

### 问题 1：错误跳转到 `localhost:5193`

原因：

- 代理头不完整
- Next 在开发环境生成了错误绝对地址

修复：

- 增加 `X-Forwarded-Host` / `X-Forwarded-Port`
- 增加 `proxy_redirect`

### 问题 2：`/coolws/` 未代理

原因：

- 只代理了 `/cool/`，漏了 websocket 子通道

修复：

- 增加 `/coolws/` 到 Collabora 容器的代理

### 问题 3：Collabora 白名单正则错误

原因：

- 复杂 alias 正则不兼容当前 coolwsd 解析

修复：

- 改为显式 host

### 问题 4：CSP / frame-ancestors 冲突

原因：

- 旧的 `net.frame_ancestors=http://*`
- 域名与 IP 混用

修复：

- 删除旧参数
- 使用 `content_security_policy` 显式配置
- 强制重建容器

### 问题 5：`SavedUIState` 无关告警

原因：

- `ui_defaults` 里传了 Collabora 当前不识别的项

修复：

- 从 `legal-platform-frontend/lib/services/collabora.config.server.ts` 中移除该项

---

## 15. 回切域名方案时的注意事项

如果后续要恢复域名方案，不能只改其中一项，必须一起改：

- 前端 `.env`
- nginx 代理头与 `proxy_redirect`
- Collabora 白名单
- Collabora CSP `frame-ancestors`

### 15.1 推荐原则

上线时只选一种主链路：

- 全域名
或
- 全 IP

不要混合：

- 父页面域名
- iframe IP
- WOPI 又是另一个 host

否则最终还是会回到浏览器跨源与 iframe 拦截问题。

---

## 16. 推荐日常运维命令

### 查看前后端状态

```bash
cd <PROJECT_ROOT>
./leaudit.sh doctor
```

### 重启前后端

```bash
./leaudit.sh restart
```

### 重建 Collabora

```bash
cd <COLLABORA_DEPLOY_ROOT>
docker-compose up -d --force-recreate collabora
```

### 查看 Collabora 日志

```bash
docker logs --tail 200 collabora_code
```

### 查看代理日志

```bash
tail -n 200 <PROJECT_ROOT>/deploy/collabora-proxy/logs/error.log
```

---

## 17. 新服务器迁移 Checklist

### 17.1 准备阶段

- [ ] 准备好项目代码目录 `<PROJECT_ROOT>`
- [ ] 准备好 Collabora 部署目录 `<COLLABORA_DEPLOY_ROOT>`
- [ ] 准备好 Collabora 镜像 tar 或镜像仓库访问方式
- [ ] 确认 `<APP_HOST>`
- [ ] 确认 `<APP_PORT>`、`<BACKEND_PORT>`、`<COLLABORA_PORT>` 不冲突

### 17.2 配置阶段

- [ ] 修改 `legal-platform-frontend/.env`
- [ ] 修改 `deploy/collabora-proxy/conf.d/collabora.conf`
- [ ] 修改 `docker-compose.yml`
- [ ] 修改 `coolwsd.xml`

### 17.3 启动阶段

- [ ] 导入 Collabora 镜像
- [ ] 启动前后端
- [ ] 重启代理
- [ ] 强制重建 Collabora 容器

### 17.4 验证阶段

- [ ] `curl -I http://<APP_HOST>:<APP_PORT>/`
- [ ] `curl -I http://<APP_HOST>:<APP_PORT>/hosting/discovery`
- [ ] `curl -I http://<APP_HOST>:<APP_PORT>/browser/dist/cool.html`
- [ ] 浏览器无痕访问登录页
- [ ] 打开并保存至少一个文档

### 17.5 故障定位阶段

若失败，优先检查：

- [ ] 前端 `.env` 与实际入口是否一致
- [ ] nginx 是否代理了 `/coolws/`
- [ ] `proxy_redirect` 是否仍指向旧地址
- [ ] `coolwsd.xml` 白名单是否与实际 host 一致
- [ ] compose 是否仍残留旧 `extra_params`
- [ ] Collabora 是否已 `force-recreate`

---

## 18. 当前结论

当前这套正确配置的核心原则只有一句话：

**浏览器入口、前端生成的 WOPI 地址、Collabora iframe 地址、代理转发头、Collabora 白名单、CSP 来源，必须全部使用同一个 host。**

本次已经验证可用的 host 为：

```text
172.16.0.59:5173
```

如果迁移到新服务器，请先替换 `<APP_HOST>` 等参数，再按本文档的重启与验证步骤执行。
