Wekan 在 AWS 上的部署与扩容实战:从单机小团队到数千用户生产环境
【免费下载链接】wekanThe Open Source kanban, built with Meteor. GitHub issues/PRs are only for FLOSS Developers, not for support, support is at https://wekan.fi/commercial-support/ . PR source translation to imports/i18n/data/en.i18n.json, other translations at https://app.transifex.com/wekan/wekan项目地址: https://gitcode.com/GitHub_Trending/we/wekan
本文是一份面向生产环境的 Wekan 部署与扩容指南,内容以 docs/Platforms/Propietary/Cloud/AWS/README.md 为骨架,覆盖两大典型场景:在 AWS 上承载数千用户的高可用集群,以及单台 EC2 + Docker 的多租户小团队部署。读完本文,你将掌握 Wekan 的实例规格选型、MongoDB 副本集与 OPLOG 连接串配置、nginx 反向代理 + Let's Encrypt SSL 的完整落地步骤、多客户路径隔离、AWS SES 邮件集成、Docker 数据备份恢复与版本升级的完整操作流程,并了解这些做法在 Wekan 源码与仓库配置文件中的依据。
Wekan 在 AWS 上的两种部署形态
Wekan 是基于 Meteor 构建的开源看板应用,其部署方式直接受 Meteor 架构约束:浏览器与服务器通过 DDP/SockJS 保持实时连接,服务器需要持续监听数据库的变更流。在 AWS 上部署 Wekan,可以根据团队规模和预算选择两种路径:
- 多实例生产集群:面向数千用户,使用 ECS 集群运行多个 Wekan 应用容器,搭配 MongoDB 副本集,并通过
MONGO_OPLOG_URL开启 OPLOG 实时推送。 - 单服务器小团队部署:一台 Ubuntu EC2 + Docker Compose 即可承载,通过 nginx 反代和路径前缀(
/customer1、/customer2)在同一台机器上服务多个客户。
两条路径共享同一套镜像仓库与配置体系,区别主要在于实例数量和数据库拓扑。
面向数千用户的生产集群配置
推荐的实例规格
官方在生产环境验证过的方案(详见 AWS README)如下:
- Node 层(ECS Cluster):3~4 台
m4.large,每台承载一个 Wekan 应用实例。 - MongoDB 层:3 台
r4.large,组成一个副本集(Replica Set),其中 1 台 Primary 负责读写,另外 2 台为副本(Replica)。
文档明确指出,这一组合“可以非常稳定地支撑数千用户”(This setup runs very well for thousands of users)。副本集的意义不仅在于高可用:只有启用了副本集,MongoDB 才会产生oplog,而 oplog 正是 Meteor 实时数据推送(LiveData)的核心数据源。
关键:多实例必须设置 MONGO_OPLOG_URL
AWS 文档中引用了一个真实的生产事故修复案例:多实例部署时未设置MONGO_OPLOG_URL,导致 CPU 持续高占用。其原理是——Meteor 在未配置 OPLOG 时,会退化为“拉取并对比”(pull-and-diff)的数据同步方式,即定期把整个数据集拉到本地做 diff;而配置 OPLOG 后,Meteor 会订阅 MongoDB 的 oplog,由数据库主动推送变更事件,服务器只需增量应用即可。
官方在 docker-compose-mongodb-v7.yml 中正是同时给出了这两项配置(见第 357、408 行):
- MONGO_URL=mongodb://wekandb:27017/wekan?replicaSet=rs0 - MONGO_OPLOG_URL=mongodb://wekandb:27017/local?replicaSet=rs0MONGO_OPLOG_URL指向的是 MongoDB 副本集的local 数据库(oplog 存储在 local 库中),因此连接串中的数据库名固定为local。在 AWS 文档给出的带认证示例中,格式为:
MONGO_OPLOG_URL=mongodb://<username>:<password>@<mongoDbURL>/local?authSource=admin&replicaSet=rsWekan参数说明:
| 参数 | 含义 |
|---|---|
<username>:<password> | MongoDB 认证用户与密码 |
<mongoDbURL> | MongoDB 主机地址(可带端口) |
/local | 固定指向 local 数据库(oplog 所在库) |
authSource=admin | 认证库为 admin |
replicaSet=rsWekan | 副本集名称,必须与 MongoDB 实际副本集名一致 |
文档记录的真实效果:为所有 Wekan 实例设置MONGO_OPLOG_URL后,CPU 平均占用率降至10% 以下,仅在大规模操作时偶有尖峰。这一优化同样适用于任何基于 Meteor 的多实例应用。
进一步提升可扩展性
如果集群规模继续增长,AWS 文档建议引入Redis Oplog 支持:通过 redis-oplog 将 Meteor 的 OPLOG 事件订阅外移到 Redis,可显著降低对 MongoDB oplog 的直接压力。在 AWS 上可直接使用ElastiCache(Redis)作为承载。这是文档明确推荐的下一步扩容手段,适合用户量持续增长后的场景。
副本集与实时性的源码佐证
从当前仓库源码可以印证副本集对 Wekan 的重要性。在 attachmentStorageSettings.js 中,管理员执行附件存储压缩(compact)时,代码会先通过replSetGetStatus查询副本集状态,若存在 Secondary 节点,则先压紧凑 Secondary、再压缩 Primary,以保证 Primary 在压缩期间保持可用:
const rsStatus = await db.admin().command({ replSetGetStatus: 1 }); const secondaries = (rsStatus.members || []).filter(m => m.state === 2);这段代码直接依赖 MongoDB 副本集拓扑,说明 Wekan 的运维模型(备份、压缩、滚动维护)都以副本集为前提,也解释了为什么生产集群文档要求使用 3 节点副本集而不是单实例 MongoDB。另外,默认的 docker-compose.yml(FerretDB 方案)会显式设置METEOR_REACTIVITY_ORDER=polling,改用轮询模式弥补 FerretDB 无 oplog 的不足;而 docker-compose-mongodb-v7.yml 中的 MongoDB 7 容器则会自动执行rs.initiate()初始化副本集并等待 Primary 选举成功,为实时推送(change-stream/oplog)提供基础。
面向企业的进一步建议
文档还给出了一条企业级建议:如果 WKAN 被企业大规模采用,与其自行维护分支,不如参与上游 Wekan 开发(将特性贡献回上游),并借助商业支持;Wekan 团队本身拥有高性能裸金属服务器用于高负载测试。对普通用户而言,理解这一点即可——大规模部署时,官方更推荐走上游主线而非长期 fork。
单服务器多租户安装(小团队方案)
AWS 文档用 16 个步骤完整描述了单台 EC2 上部署 Wekan 并为多个客户服务的流程。下面按阶段整理并补充关键细节。
阶段一:AWS 网络与实例准备
- 创建安全组:新建安全组(例如名为
wekan),对所有人开放入站端口80 和 443;SSH 访问只对你的个人 IP 开放,CIDR 写法如123.123.123.123/32(/32 表示仅这一个 IP)。 - 启动 EC2 实例:使用Ubuntu 17.10 64 位(或更新的 Ubuntu LTS)镜像,至少2 GB 内存、30 GB 磁盘。文档提醒:随着客户增加,磁盘需求会上升,建议预留余量。实例创建时添加你的 SSH 公钥。
- 绑定弹性 IP(Elastic IP):为实例分配一个 Elastic IP。好处是:IP 长期不变;日后需要升级硬件时,可对实例做快照,用更大内存的实例类型启动新实例,再把 Elastic IP 指过去,即可最小化停机时间完成迁移(建议选择无活跃数据变更的时间段操作)。
- 配置 DNS:在 Route 53、Namecheap 或你的域名控制面板,把
subdomain.yourdomain.com用A 记录指向 Elastic IP。DNS 全球生效最长需要 24 小时。
阶段二:系统初始化与基础组件
- SSH 登录服务器:
ssh -i pubkey.pem ubuntu@server-ip-address # 部分镜像为 root 用户,则使用 root@server-ip-address- 更新系统全部软件包:
sudo apt update sudo apt -y dist-upgrade reboot- 安装 Docker CE 与 docker-compose:从 docker.com 官方源安装,安装后把
ubuntu用户加入docker组(post-install 步骤)。 - 安装 nginx 反向代理:
sudo apt install nginx # 或安装带额外模块的版本:sudo apt install nginx-full sudo systemctl start nginx sudo systemctl enable nginxnginx 的完整站点配置模板(含 WebSocket 升级、SSL 与反向代理)见 docs/Platforms/Webserver/Nginx.md,我们将在下一节详细展开。配置完成后校验并生效:
sudo nginx -t # 校验配置语法 sudo systemctl reload nginx- 安装 certbot:从 certbot.eff.org 获取 Let's Encrypt SSL 证书,并把 HTTP 流量重定向到 HTTPS。
阶段三:多租户路径规划
- 不同客户使用不同路径前缀:在同一个 nginx virtualhost 子域配置文件中,为每个客户写一个独立的
location /customer1、location /customer2块,各自反向代理到本机不同的 localhost 端口上的 Wekan 容器。这样一台服务器即可服务多个客户。 - 获取最新版本与配置说明:查看 Wekan 官方 release 页获取最新版本号;
docker-compose.yml中所有环境变量的含义都在官方 wekan-mongodb 仓库的 compose 文件中有注释说明(当前仓库的 docker-compose.yml 与 docker-compose-mongodb-v7.yml 同样对每个变量做了详尽注释)。核心设置示例:
ROOT_URL=https://sub.yourdomain.com/customer1 ports: - 8080:80 # 宿主机 localhost:8080 映射到容器内 80 端口镜像必须使用明确的版本标签,不要用latest:
image: quay.io/wekan/wekan:v0.70文档特别强调:只使用 release 版本标签,因为latest标签偶尔可能是损坏的构建。
关于ROOT_URL的重要提示(可参考 server/00checkStartup.js 的启动校验):Wekan 通过邮件发送的邀请链接、密码重置链接、以及地址验证都由ROOT_URL拼装而成。如果ROOT_URL设置错误,发出的链接会指向错误地址。在子路径部署时,ROOT_URL必须包含路径(如https://sub.yourdomain.com/customer1)。
阶段四:AWS SES 邮件集成
- 配置 AWS SES:在 AWS SES 控制台添加发件邮箱地址与域名,并验证SPF和DKIM(若域名托管在 Route 53,可用其 wizard 一键完成)。然后在 SES 创建新的 SMTP 凭据,填入 docker-compose.yml 的 SMTP 设置。
AWS SES 的 SMTP 端点、SPF TXT 记录以及排错细节见 docs/Features/Email/Troubleshooting-Mail.md。其中对 AWS SES 的典型配置是(注意:SES 凭据无需 urlencode 特殊字符):
- MAIL_FROM=Wekan Boards <boards@example.com> - MAIL_URL='smtp://username:password@email-smtp.eu-west-1.amazonaws.com:587?tls={ciphers:"SSLv3"}&secureConnection=false'SPF 记录示例(123.123.123.123换成你的服务器 IP):
@ TXT "v=spf1 ip4:123.123.123.123 include:amazonses.com ~all"阶段五:启动与多租户容器管理
- 启动 Wekan 与数据库容器:
docker-compose up -d请求链路为:nginx SSL 443 端口 → 代理到 localhost:8080(或其他端口)→ wekan-app 容器内 80 端口。 14.每个客户独立目录:为不同客户准备不同的 docker-compose.yml,放在以客户命名的目录中(如wekan-customer1/)。必要时把容器从默认的wekan-app重命名为wekan-customer1,并相应调整 Docker 内部网络名称,避免冲突。 15.备份、恢复与数据迁移:详见 docs/Platforms/FOSS/Container/Docker/Export-Docker-Mongo-Data.md(下文有精简版流程)。 16.首次登录与管理员配置:打开https://subdomain.yourdomain.com/customer1/sign-up注册,在https://subdomain.yourdomain.com/customer1/sign-in登录。第一个注册的用户自动成为管理员。登录后点击右上角用户名进入 Admin Panel,把注册设置改为“仅邀请”(invite only),避免陌生人注册。
nginx 反向代理与 SSL 配置详解
AWS 安装步骤第 8、9 步提到的 nginx 配置,其完整模板在 docs/Platforms/Webserver/Nginx.md。由于 Wekan(Meteor)使用 WebSocket(SockJS)进行实时通信,nginx 配置中 WebSocket 升级是否正确,直接决定看板能否实时刷新。
站点配置(/etc/nginx/conf.d/example.com.conf 或 sites-available 下)
# 这段 map 必须放在 http { } 上下文中,不能放在 server/location 内 map $http_upgrade $connection_upgrade { default upgrade; '' close; } # HTTP:非 SSL 流量重定向到 HTTPS server { listen 80; listen [::]:80 ipv6only=on; server_name example.com; location / { rewrite ^ https://example.com$request_uri? permanent; } } # HTTPS server server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3001; # 指向 Wekan 容器的宿主端口 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; # 允许 WebSocket 升级 proxy_set_header Connection $connection_upgrade; # 由 map 决定 upgrade/close proxy_set_header X-Forwarded-For $remote_addr; # 保留客户端真实 IP } }关键点(Nginx.md 中有完整排错章节):
map块必须在 http 上下文中,放在 server/location 内不生效;Connection头必须使用$connection_upgrade变量,不能硬编码""或"upgrade",否则 SockJS 的/sockjs/.../websocket请求无法完成升级,浏览器控制台会报WebSocket connection to 'wss://HOST/sockjs/.../websocket' failed,Wekan 会退化为慢速长轮询;proxy_http_version 1.1;是必需的(WebSocket 依赖 HTTP/1.1,默认 1.0 无法升级);- 若 Wekan 前面有多级代理/负载均衡,每一跳都需要这三行。
常见问题
- 看到 “Welcome to Nginx” 默认页:多半是
/etc/nginx/conf.d/和/etc/nginx/sites-available/下存在自动生成的default文件抢占了默认 server,删除它们即可(参考 Nginx.md 中引用的真实案例)。 - CentOS 7 上 nginx 连不上容器:执行
setsebool -P httpd_can_network_connect 1允许 Web 服务连接容器,不要关闭 SELinux。 - 页面日期格式异常:需要在 Content-Security-Policy 中追加
'unsafe-eval':
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval'";- 附件上传被拒(413 Request Entity Too Large):在
http { }中调大限制:
client_max_body_size 100M;- 启用站点:把配置文件软链接到
sites-enabled,然后sudo nginx -t校验、sudo systemctl reload nginx生效。完整流程见 Nginx.md。
Docker 数据备份、恢复与跨容器迁移
AWS 部署步骤 15 引用的 Export-Docker-Mongo-Data.md 提供了完整的 MongoDB 备份恢复方案。核心要点:
- 恢复前必须先停 Wekan 应用容器(
docker stop wekan-app),否则导入数据可能与运行中的应用冲突; - 确认
MONGO_URL中的数据库名正确(如wekan、admin),否则恢复后数据库可能是空的; - Docker 数据默认存放在宿主机
/var/lib/docker,直接操作该目录风险高、难以恢复,用 mongodump 文件恢复要容易得多,因此强烈建议以 mongodump 为备份手段。
手动备份/恢复流程
# 1) 进入 MongoDB 容器 docker exec -it wekan-db bash # 2) 备份到容器内 /dump 目录(只备份 wekan 数据库,不含 local) mongodump -o /dump/ # 3) 退出容器,把备份拷到宿主机当前目录 exit docker cp wekan-db:/dump . # 4) 恢复(先把 dump 拷回容器,再 mongorestore) docker cp dump wekan-db:/data/ docker exec -it wekan-db bash cd /data mongorestore --drop --db wekan /data/dump/wekan/ exit若恢复时报“索引已存在”类错误,可在 mongorestore 中加--noIndexRestore参数跳过索引重建。
自动化备份脚本(删除 7 天前旧备份)
#!/bin/bash DATE=$(date +%Y-%m-%d-%H-%M) SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" cd $SCRIPTPATH mkdir -p backups/$DATE docker ps -a | grep 'wekan-db' &> /dev/null if [ $? = 0 ]; then docker exec -t wekan-db bash -c "rm -fr /dump ; mkdir /dump ; mongodump -o /dump/" docker cp wekan-db:/dump $SCRIPTPATH/backups/$DATE tar -zc -f backups/$DATE.tgz -C $SCRIPTPATH/backups/$DATE/dump wekan if [ -f backups/$DATE.tgz ]; then rm -fr backups/$DATE find $SCRIPTPATH/backups/ -name "*.tgz" -mtime +7 -delete fi else echo "wekan-db container is not running" exit 1 fi注:以上命令与脚本以传统 MongoDB 容器(
wekan-db)为例。当前仓库默认的 docker-compose.yml 使用 FerretDB + SQLite 后端,备份对象与命令不同;使用 docker-compose-mongodb-v7.yml 的 MongoDB 7 副本集方案时,则与上述 mongodump 流程一致。
升级 Wekan 到新版本
AWS 文档给出了一套安全升级流程,核心原则是先备份、再换镜像标签、最后验证:
# 1) 进入客户目录并创建备份目录 cd wekan-customer1 mkdir backup-2018-02-03 cd backup-2018-02-03 # 2) 按上一节方法在备份目录中完成数据库备份 # 3) 回到客户目录,编辑 docker-compose.yml 更新版本标签 # image: quay.io/wekan/wekan:v0.70 → image: quay.io/wekan/wekan:v0.71 # 4) 重启 Wekan docker-compose stop docker-compose start- 登录 Wekan,在 Admin Panel 确认版本号已更新。
如果版本未更新,可用以下 Docker 命令排查:
docker ps # 查看运行中的容器 docker images # 查看本机已安装的镜像 docker stop wekan-app # 停止旧容器(或用 CONTAINER-ID) docker rm wekan-app # 删除旧容器 docker rmi quay.io/wekan/wekan:v0.70 # 删除旧镜像 docker-compose up -d # 用新配置重新创建并启动容器注意:升级后若直接docker-compose start不生效(容器仍引用旧镜像),通常需要docker-compose up -d重建容器。
部署清单速查
| 事项 | 关键操作/配置 | 依据文档 |
|---|---|---|
| 多实例集群 | 3~4× m4.large (Node) + 3× r4.large (Mongo 副本集) | AWS README |
| 实时数据推送 | 必须设置MONGO_OPLOG_URL=mongodb://.../local?...&replicaSet=... | 同上;docker-compose-mongodb-v7.yml |
| 进一步扩容 | 引入 redis-oplog,AWS 上用 ElastiCache | AWS README |
| 安全组 | 开放 80/443,SSH 仅限本机 IP(/32) | 同上 |
| 多租户 | nginxlocation /customerN→ 各自 localhost 端口;每客户独立 compose 目录 | 同上 |
| 镜像版本 | 只用版本标签,不用latest | 同上;docker-compose.yml 注释 |
| 邮件 | AWS SES 验证 SPF/DKIM,新建 SMTP 凭据 | Troubleshooting-Mail.md |
| WebSocket 反代 | map $http_upgrade+Connection $connection_upgrade+proxy_http_version 1.1 | Nginx.md |
| 备份恢复 | 停应用 → mongodump → 拷出/拷入 → mongorestore | Export-Docker-Mongo-Data.md |
| 升级 | 备份 → 换镜像标签 → stop/start → Admin Panel 验证 | AWS README |
结语
无论是数千用户的 ECS + MongoDB 副本集集群,还是单机多租户的 nginx + Docker 方案,Wekan 在 AWS 上的生产部署都遵循同一条主线:用 MongoDB 副本集 +MONGO_OPLOG_URL保证 Meteor 实时推送的规模上限,用 nginx 正确处理 WebSocket 升级保证前端实时体验,用版本标签 + 备份先行保证升级安全。本文引用的配置模板与脚本均来自仓库 docs/Platforms/Propietary/Cloud/AWS/README.md 及其关联的 Nginx、邮件、备份文档,可直接作为运维手册使用;当前仓库中的 docker-compose.yml 与 docker-compose-mongodb-v7.yml 则是上述所有环境变量的权威注释来源。
【免费下载链接】wekanThe Open Source kanban, built with Meteor. GitHub issues/PRs are only for FLOSS Developers, not for support, support is at https://wekan.fi/commercial-support/ . PR source translation to imports/i18n/data/en.i18n.json, other translations at https://app.transifex.com/wekan/wekan项目地址: https://gitcode.com/GitHub_Trending/we/wekan
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考