海狸IM 2.1 私有化部署从零到一:中间件、微服务与 Nginx 全流程
前面几篇把海狸IM 的功能、移动端、OAuth 登录、圈子都讲完了,这篇回到最基础也最常被问的问题:怎么把它部署到自己服务器上。数据不出自己机房,是很多人选私有化 IM 的第一理由,这篇就把我从一台空服务器到跑通全端的完整流程写出来。
一、先搞清楚你要部署的是什么
海狸IM 的后端不是单体服务,而是一套 Go + go-zero 微服务 。看 beaver-server/app/ 目录就知道,业务被拆成了 user、chat、group、friend、moment、circle、emoji、file、call、notification、gateway、auth、open、platform 等 17 个模块,每个模块再分 API 层和 RPC 层。
微服务意味着两件事:
- 有一堆中间件依赖:MySQL (主存储)、Redis (缓存/会话)、ETCD (服务发现与配置)、RocketMQ (消息推送)、LiveKit(音视频)。
- 服务之间有启动顺序:先 RPC,再 API,最后 Admin,反过来不行。
心里有这两条,部署过程就不容易迷路。
二、服务器准备
官方文档给的配置建议(beaver-docs/guide/deployment.md):
| 档位 | CPU | 内存 | 存储 | 网络 |
|---|---|---|---|---|
| 最低 | 2 核 2.4GHz+ | 2GB | 50GB SSD | 10Mbps+ |
| 推荐(100-1000 用户) | 4 核 3.0GHz+ | 8GB+ | 200GB+ SSD | 100Mbps+ |
系统建议 Ubuntu 20.04+ LTS,需要公网 IP + 域名。再补一句我自己的体感:如果要把 RocketMQ、OpenSearch 日志栈全拉起来,内存别低于 4GB,不然 JVM 系的组件会挤得很难受。
装 Docker 和 Docker Compose,官方一键脚本:
bash
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
装完记得重新登录一次让 docker 组生效。
三、第一步:拉起中间件
基础中间件(MySQL / Redis / ETCD / Nginx)用一个 docker-compose 拉起,放在 /mnt/docker/docker-compose.yml:
yaml
services:
redis:
image: redis:4
command: redis-server --appendonly yes --requirepass "your_redis_password"
ports:
- "6379:6379"
volumes:
- ./redis:/data
mysql:
image: mysql:5.7.31
restart: always
privileged: true
environment:
MYSQL_ROOT_PASSWORD: "your_mysql_password"
command: [
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_general_ci',
'--max_connections=3000'
]
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/my.cnf
etcd:
image: quay.io/coreos/etcd:v3.5.15
environment:
- ALLOW_NONE_AUTHENTICATION=yes
- ETCD_ADVERTISE_CLIENT_URLS=http://your_internal_ip:2379,http://your_external_ip:2379
ports:
- "2379:2379"
nginx:
image: nginx
restart: always
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
除此之外,beaver-server/docker/docker-compose.yml 里还提供了另外几样,按需起:
- LiveKit :音视频必需。信令 7880、RTC over TCP 7881、UDP 媒体端口段 50000-50050。
- RocketMQ 5.3.1 :namesrv(9876)+ broker(10909-10912),还有一个
rocketmq-init一次性任务,自动创建ws_push_topic------WebSocket 消息推送就走这个 topic。 - 日志可观测栈(可选) :OpenSearch 2.19 + Dashboards + OTel Collector(4317/4318 收 OTLP)。服务端的 beaverlog 日志通过
OtlpAddr配置推到这里,Dashboards 里就能查全链路日志。小团队可以先不起这套,不影响核心功能。
起服务之前先改三处:Redis 密码、MySQL root 密码、ETCD 的内外网广播地址。官方文档的安全建议很直接:随机密码(16-32 位),并且别用默认端口------3306、6379、2379 这些端口挂在公网上就是靶子。
bash
cd /mnt/docker
docker-compose up -d
docker-compose ps
四、第二步:初始化数据库
用 Navicat(或任意客户端)连上刚起的 MySQL,新建数据库:
- 库名:
beaver - 字符集:
utf8mb4 - 排序规则:
utf8mb4_bin
然后回到服务端代码,把 main.go 里数据库连接的密码和地址改成你的,执行初始化:
bash
go run main.go -db
看到输出 所有表结构生成成功 就说明建表完成。表结构是 GORM 风格自动生成的,不用手工导 SQL。
五、第三步:改服务端配置
beaver-server/deploy/ 下就是部署单元,每个服务一个目录(user_api/、user_rpc/、chat_api/......共 30 多个),各带一份 docker-compose 和 yaml 配置。
要改的配置集中在三处(对应 deploy/config.txt 里的替换规则):
text
# Etcd 地址
127.0.0.1:2379 -> 你的地址:2379
# MySQL 连接串
root:123456@tcp(127.0.0.1:3306)/beaver -> 你的账号密码@tcp(你的地址:端口)/beaver
# Redis 地址与密码
127.0.0.1:6379 -> 你的地址:端口
Password: '123456' -> Password: '你的密码'
改法有两种:手工逐个改各服务目录下的 yaml,或者改好 config.txt 之后跑 ./deploy/config.sh 批量替换(注意它会直接改写 yaml,不自动备份,跑之前最好留一份副本)。
镜像可以直接用官方 wsrh8888/ 开头的镜像,不用自己编译。
六、第四步:按顺序启动微服务
bash
cd /mnt/beaver
# 先停干净
./deploy/stop.sh
# 再按 RPC -> API -> Admin 的顺序全部拉起
./deploy/start.sh
start.sh 的逻辑是:先创建 beaver_network(没有的话),然后按目录名后缀 _rpc → _api → _admin 分三批,每批对每个服务目录执行 down → pull → build → up -d,批间等 2 秒。stop.sh 反向按 Admin → API → RPC 停止并清理。
两个小坑:
- Linux 上如果脚本因为空格转义问题起不来,文档给了一行修复:
sed -i 's/\\$/$/g' deploy/start.sh(stop.sh 同理)。 - 想单独重启某个服务,进对应目录手动
docker-compose up -d就行,不用动全家。
七、第五步:Nginx 收口
Nginx 负责把域名流量转发到宿主机上的 API 服务,关键配置在 /mnt/docker/nginx/conf.d/server.conf:
nginx
location /beaver/api {
rewrite ^/beaver/(.*)$ /$1 break;
proxy_pass http://10.0.24.6:20800; # 代理到宿主机服务
# WebSocket 支持 - 必须加这三个头,否则长连接起不来
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 300;
proxy_connect_timeout 30;
}
三个 WebSocket 头是 IM 的命根子,漏了的话登录能过、消息收不到,属于最难排查的一类问题。HTTPS 版本文档里也给了模板,证书放 ./nginx/ssl 挂载进去即可。生产环境建议直接上 HTTPS。
八、验证:从登录页到音视频
全部起来之后,按这个顺序验证:
- 浏览器打开域名,能看到登录页 → Nginx 和 API 通了。
- 注册一个账号,密码登录成功 → 数据库、user 服务、gateway 正常。

- 客户端(桌面端 Electron)配置好服务器地址后登录,能收发消息 → WebSocket 通了。

- 两个人发起音视频通话 → LiveKit 通了。这一步失败,九成是 7880/7881 没放行 TCP,或 50000-50050 没放行 UDP。
九、我实际踩过的坑
照实说,都是第一天的坑,过了第一天就顺了:
- 宿主机已有 MySQL 占了 3306 :改映射端口(
"3307:3306"这种),同步改服务端连接串。 - LiveKit 端口没放行:音视频一直连不上,聊天却一切正常,很有迷惑性。记得 UDP 端口段。
- 防火墙只放了 TCP:云服务器安全组里 UDP 要单独勾。
- RocketMQ 的 dashboard(8080)和 OpenSearch Dashboards(5601)别裸奔在公网:这套管理界面默认没有鉴权,用安全组限制到内网或 VPN 访问。
十、这套部署的边界
- 不是"一条命令起全栈" :中间件 compose 和服务端
deploy/是分开的,中间还有数据库初始化、配置替换、按序启动几步。对熟悉 docker-compose 的人是一下午的事,纯新手需要对着文档走。 - 服务端本身不在中间件 compose 里:34 个微服务各自一个 compose 目录,由 start.sh 统一编排,这是 go-zero 项目的常见形态,但和"单体镜像"的心智不一样。
- 日志栈是可选组件 :不起 OpenSearch/OTel 不影响功能,只是没有集中日志可查;要排查问题就靠
docker-compose logs。 - 文档在持续补 :
beaver-docs的 deployment 章节目前覆盖到初始化和基础部署,高可用、扩容这类主题还没有,多实例部署需要自己摸索。
如果只是 20 人以内的小团队自用,最低配置单机跑全套完全够用;上百人再考虑按官方推荐配置加机器。
参考链接
| 工程 | 地址 | 说明 |
|---|---|---|
| beaver-server | https://github.com/wsrh8888/beaver-server | 后端源码 + deploy 脚本 + docker-compose |
| beaver-desktop | https://github.com/wsrh8888/beaver-desktop | 桌面客户端 |
| 部署文档 | https://wsrh8888.github.io/beaver-docs/ | deployment 章节逐步说明 |
| Docker 镜像 | https://hub.docker.com/u/wsrh8888 | wsrh8888/ 开头的官方镜像 |