# OpenIM + LiveKit 内网测试环境部署记录

内部通讯 App 的服务端测试环境。一键部署后两个测试账号可互发文字/语音/文件消息，并可打通一对一语音通话。

## 组件清单

| 组件 | 镜像 | 用途 |
| --- | --- | --- |
| OpenIM Server | `openim/openim-server:v3.8.3-patch.12` | IM 服务端（REST API + WebSocket 消息网关） |
| LiveKit | `livekit/livekit-server:v1.13.5` | 语音通话 SFU |
| account-server | 本地构建（`account-service/`） | 自研公司账号登录（工号+密码、管理员导入名单、管理页），见 `account-service/README.md` |
| MongoDB / Redis / Etcd / Kafka / MinIO | 见 `.env.example` | OpenIM 依赖组件 |

按任务约束做的裁剪（相对官方 openim-docker v3.8）：

- 移除 `openim-chat`（GPLv3 授权不利改造，注册登录后续由"公司账号登录"卡自研）
- 移除 `openim-web-front` / `openim-admin-front`（这两个前端依赖 chat 服务）
- 监控组件（Prometheus/Grafana 等）保留在 compose profile `m` 下，默认不启动

未改动 OpenIM 服务端任何核心代码，全部通过环境变量配置（`IMENV_*`）。

## 服务器要求

- 内网闲置机器，4 核 8G 起步，磁盘 ≥ 20G
- 已安装 Docker（含 compose 插件，`docker compose version` 能跑通即可）
- 不需要公网入口

## 端口表（需要对客户端开放的只有前 6 个）

| 端口 | 协议 | 用途 |
| --- | --- | --- |
| 10001 | TCP/WS | OpenIM 消息网关（客户端长连接） |
| 10002 | TCP/HTTP | OpenIM REST API |
| 10005 | TCP/HTTP | MinIO（图片/语音/文件下载） |
| 10010 | TCP/HTTP | 公司账号服务（员工登录接口 + 管理页） |
| 7880 | TCP/WS | LiveKit 信令（`.env` 的 `LIVEKIT_PORT` 可改） |
| 7882 | UDP | LiveKit 语音媒体（`LIVEKIT_RTC_UDP_PORT` 可改） |
| 7881 | TCP | LiveKit 媒体备用通道（`LIVEKIT_RTC_TCP_PORT` 可改） |
| 10004 | TCP/HTTP | MinIO 控制台（运维用，可不开放） |
| 12379/12380 | TCP | Etcd（仅容器间用，建议不对外） |

## 部署步骤

```bash
git clone ssh://git@192.168.200.36:222/leefer/tongxunruanjian.git
cd tongxunruanjian
./scripts/deploy.sh            # 自动探测本机内网 IP；也可 ./scripts/deploy.sh 192.168.x.x 指定
./scripts/selftest.sh          # 自测（见下）
```

`deploy.sh` 做的事：首次从 `.env.example` 生成 `.env` → 把服务器 IP 写入 `MINIO_EXTERNAL_ADDRESS`（文件下载链接用这个地址，写错会导致文件发不出）→ 预建数据目录 → `docker compose pull && up -d` → 等待 openim-server 健康检查通过。

数据全部落在仓库目录下的 `components/` 里；`.env` 里的密码/密钥是测试环境默认值，正式环境前再换。

## 自测覆盖（scripts/selftest.sh）

1. 管理员令牌获取（`/auth/get_admin_token`）
2. 注册测试账号 `test001` / `test002`（`/user/user_register`）
3. 签发用户令牌，即登录链路（`/auth/get_user_token`）
4. 两账号互发文字消息（`/msg/send_msg`）
5. 附件上传 MinIO 并发送语音消息、文件消息
6. 消息落库回查（`/msg/search_msg`，逐条核对刚发的文字/语音/文件）
7. LiveKit 一对一：两个客户端进同一房间，主叫发布音频轨，被叫端确认收到轨道

全部通过会打印客户端接入参数。失败项会标 `[失败]`，配合 `docker compose logs -f openim-server` 或 `docker compose logs -f livekit` 排查。

## 日常运维

```bash
./scripts/restart.sh           # 重启全部服务
./scripts/restart.sh livekit   # 只重启某个服务
docker compose ps              # 查看状态
docker compose logs -f openim-server   # 看日志
docker compose down            # 停止（数据保留在 components/）
docker compose up -d           # 再启动
```

## 客户端接入参数（自测通过后）

- OpenIM API: `http://<服务器IP>:10002`
- OpenIM WebSocket: `ws://<服务器IP>:10001`
- LiveKit: `ws://<服务器IP>:7880`（7880 为默认信令端口，可用 `.env` 的 `LIVEKIT_PORT` 改），API Key/Secret 见 `.env` 的 `LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET`
- 测试账号：`test001` / `test002`（由自测脚本注册）；语音通话时两名用户以各自 identity 进同一房间即可

## 常见问题

- **文件/语音能发但打不开**：`MINIO_EXTERNAL_ADDRESS` 没写成客户端能访问的 IP。改 `.env` 后 `docker compose up -d` 重建 openim-server。
- **启动报缺 `ETCD_USERNAME` / `KAFKA_USERNAME` 等警告**：未启用对应组件认证，官方说明可忽略。
- **openim-server 一直 unhealthy**：`docker exec -it openim-server mage check` 看哪项依赖没通；首次启动需等 30-60 秒。
- **livekit 启动报 `bind ... 7880/7881: address already in use`**：服务器上这些端口被别的程序占了（`ss -tlnp | grep 788` 查占用者）。不要动别人的服务，把 `.env` 里 `LIVEKIT_PORT` / `LIVEKIT_RTC_TCP_PORT` / `LIVEKIT_RTC_UDP_PORT` 改成空闲端口（如 17880/17881/17882），再 `docker compose up -d --force-recreate livekit`。之后客户端和自测脚本都用新端口（自测脚本会自动读 `.env`）。
- **livekit 日志报 `secret is too short`**：`LIVEKIT_API_SECRET` 必须 ≥32 字符，换个长密钥后重建 livekit 容器。
- **语音通话连不上**：确认服务器 UDP 7882 放行（内网防火墙/安全组）；UDP 不通时会走 TCP 7881 兜底。
