换服务器不丢数据、不停站,手把手教你完成论坛搬家
一、什么时候需要做迁移?
| 场景 | 说明 |
|---|---|
| 更换服务器 | 从A云厂商搬到B云厂商,或从低配升到高配 |
| 更换域名 | 论坛域名发生变化 |
| 灾备恢复 | 服务器故障后从备份恢复 |
| 自建转托管 | 从自托管迁移到 Discourse 官方托管 |
迁移前问自己三个问题:
-
域名换不换?(换域名比换服务器复杂得多)
-
服务器架构变不变?(x64 ↔ ARM 可以,但需要测试)
-
能接受的停机时间是多少?(建议在凌晨进行)
二、迁移前的准备工作
2.1 环境一致性检查
必须保持一致:
| 项目 | 检查方法 | 说明 |
|---|---|---|
| Discourse 版本 | /admin/upgrade 查看 | 新服务器必须安装相同版本 |
| 插件列表 | 对比 app.yml 中的 hooks 部分 | 插件不一致会导致恢复失败 |
| PostgreSQL 版本 | psql --version | 必须主版本一致 |
可以在旧服务器上执行
git rev-parse HEAD获取确切版本号
2.2 降低 DNS TTL(换域名/换IP时必做)
如果你计划换服务器 IP 或换域名,提前在 DNS 解析商处将 TTL(生存时间)降低到 300 秒(5分钟),这样可以减少切换时的停机时间 。
操作路径:域名管理后台 → 找到你的域名解析记录 → 将 TTL 改为 300
2.3 准备清单
| 项目 | 说明 |
|---|---|
| 目标服务器 | 已安装 Docker,2GB+ 内存,足够的硬盘空间 |
| 旧服务器备份 | 完整备份(含上传文件)或数据库备份 + 上传文件分离 |
| 维护窗口 | 通知用户,建议选择凌晨低峰期 |
| 回滚方案 | 旧服务器保持运行,直到新服务器验证通过 |
三、两种迁移方案
方案一:完整备份恢复(最简单,推荐90%场景)
这是官方推荐的方式,通过 Discourse 自带的备份/恢复功能完成迁移 。
架构图:
flowchart TD A[旧服务器] -->|创建完整备份| B[备份文件.tar.gz] B -->|scp/rsync传输| C[新服务器] C -->|恢复备份| D[新Discourse实例] D -->|切换DNS| E[用户访问新服务器] A -.->|保留回滚| F[旧服务器保持只读] 第一步:在旧服务器上创建完整备份
登录旧服务器的 Discourse 后台:https://你的论坛域名/admin/backups
-
点击 Backup 按钮
-
确保勾选 Include uploads(包含上传文件)
-
点击 Start 开始备份
-
等待备份完成,下载或记录备份文件名
也可以通过命令行创建备份 :
bash
cd /var/discourse ./launcher enter app discourse backup exit 备份文件会生成在 /var/discourse/shared/standalone/backups/default/ 目录下。
第二步:将备份文件传输到新服务器
bash
# 从旧服务器复制到新服务器 scp /path/to/backup.tar.gz root@新服务器IP:/var/discourse/shared/standalone/backups/default/ 第三步:在新服务器上安装 Discourse
按照官方 Docker 安装流程,在新服务器上完成 Discourse 的基础安装,但不启动服务。
第四步:在新服务器上恢复备份
方法一:通过 Web 界面恢复
-
进入新服务器后台
/admin/backups -
点击 Restore 标签页
-
找到上传的备份文件,点击 Restore
方法二:通过命令行恢复
bash
cd /var/discourse # 进入容器 ./launcher enter app # 开启恢复功能(如果提示权限不足) discourse enable_restore # 执行恢复 discourse restore /var/discourse/shared/standalone/backups/default/你的备份文件名.tar.gz # 退出容器 exit # 重建容器 ./launcher rebuild app 恢复完成后会自动退出登录,用原管理员账号重新登录即可 。
方案二:分离备份(大容量附件场景)
如果你的论坛附件非常大(几十GB甚至上百GB),可以将附件和数据库分开处理,缩短迁移时间。
核心思路:
-
用
rsync同步附件目录(支持断点续传) -
用数据库备份(
.sql.gz)迁移核心数据 -
最后用
uploads:migrate_to_s3将附件迁移到对象存储(如 Cloudflare R2、阿里云OSS),彻底解决附件管理问题
这种方式适合附件超大、多次迁移的场景,也便于未来增量同步。
四、换域名时的特殊处理
如果你不仅要换服务器,还要换域名,比普通迁移多一步:
4.1 备份前修改配置
在旧服务器上修改 app.yml,将 DISCOURSE_HOSTNAME 改为新域名,然后重建一次:
bash
cd /var/discourse ./launcher rebuild app 然后再创建备份。
4.2 恢复后检查
恢复完成后,登录新服务器后台,检查以下设置是否与新域名一致:
-
站点设置中的
title和contact_email -
通知邮件中的链接
-
任何硬编码了旧域名的主题或插件
4.3 旧域名重定向(可选)
如果希望旧域名自动跳转到新域名,可以在旧服务器的 Nginx 配置中添加:
nginx
server { listen 80; server_name 旧域名.com; return 301 https://新域名.com$request_uri; } 五、对象存储迁移(可选但推荐)
如果你的附件很多,推荐在迁移的同时将附件迁移到对象存储(如 Cloudflare R2、阿里云OSS)。好处:
-
永久解决附件容量问题:不占服务器硬盘
-
减轻服务器 IO 压力:访问图片直接从 CDN 走
-
未来迁移更简单:只需迁移数据库,附件不用动
5.1 在旧服务器上完成附件迁移
如果旧服务器的附件还在本地,可以在迁移前先将其全部上传到对象存储 :
bash
cd /var/discourse ./launcher enter app # 执行附件迁移命令 sudo -E -u discourse RAILS_ENV=production bundle exec rake uploads:migrate_to_s3 exit
注意:这个命令会移动附件到对象存储,原文件会被删除。执行前请确保配置正确。
5.2 检查附件是否全部迁移成功
bash
# 检查是否有帖子尚未映射到新的 S3 URL sudo -E -u discourse RAILS_ENV=production bundle exec rails r ' ids = Post.where("cooked LIKE '%/uploads/default/%'").pluck(:id) puts "还有 #{ids.count} 个帖子需要重新处理" if ids.any? ' 如果还有帖子未映射,可以运行批量重新处理:
bash
sudo -E -u discourse RAILS_ENV=production bundle exec rake posts:rebake 5.3 在新服务器配置中使用对象存储
编辑新服务器的 app.yml,添加对象存储相关环境变量 :
yaml
env: DISCOURSE_USE_S3: "true" DISCOURSE_S3_REGION: "auto" DISCOURSE_S3_ENDPOINT: "https://你的账号ID.r2.cloudflarestorage.com" DISCOURSE_S3_BUCKET: "discourse-uploads" DISCOURSE_S3_ACCESS_KEY_ID: "你的Key" DISCOURSE_S3_SECRET_ACCESS_KEY: "你的Secret" DISCOURSE_S3_CDN_URL: "https://你的CDN域名" DISCOURSE_BACKUP_LOCATION: "s3" 重建新服务器即可直接使用对象存储中的附件。
六、常见问题与解决方法
Q1:恢复时报错 “备份文件不兼容”
原因:新服务器与旧服务器的 Discourse 版本或 PostgreSQL 版本不一致 。
解决:
-
检查旧服务器的 Discourse 版本和插件列表
-
在新服务器上安装完全相同版本后再恢复
-
不要将较新的备份恢复到较旧的 Discourse 版本上
Q2:恢复后无法登录(HTTPS 问题)
原因:旧服务器开启了强制 HTTPS,但新服务器没有配置 SSL 证书 。
临时解决:通过 Rails 控制台暂时关闭强制 HTTPS:
bash
cd /var/discourse ./launcher enter app rails c SiteSetting.force_https = false exit exit 然后配置好新服务器的 SSL 后再重新开启。
Q3:恢复后头像/图片不显示
原因:上传文件没有正确迁移,或者 CDN 地址配置错误。
解决:
-
检查备份是否勾选了
Include uploads -
检查
app.yml中的DISCOURSE_S3_CDN_URL配置 -
如果附件存储在本地,确认
/uploads目录已正确同步
Q4:恢复后帖子中的链接还是旧域名
原因:帖子内容中写入了绝对链接。
解决:
-
如果是换域名,可以在恢复后批量替换
-
通过 Rails 控制台或 SQL 执行替换(需谨慎操作,建议先备份)
七、企业级迁移流程(复杂场景)
如果你的论坛有以下特征:
-
数据量巨大(百万级帖子)
-
有复杂的权限模型(分类权限、私密板块)
-
有定制插件和主题
-
需要满足合规要求(审计、数据保留)
建议走企业级迁移流程,分为以下阶段 :
| 阶段 | 主要工作 | 产出 |
|---|---|---|
| 1. 发现与评估 | 分析源平台数据结构、统计数据量、梳理权限模型 | 迁移范围确认书 |
| 2. 环境搭建 | 创建迁移专用环境、部署相同版本 Discourse | 迁移测试环境 |
| 3. 映射设计 | 分类->分类/标签映射、用户组映射、权限映射 | 数据映射文档 |
| 4. 多轮验证 | 导入测试数据、功能验证、用户验收测试 | 验收通过报告 |
| 5. 正式割接 | 源站只读、最终导出、导入生产环境、DNS切换 | 正式上线 |
| 6. 验证与清理 | 上线后验证、遗留链接重定向、旧站下线 | 迁移完成报告 |
典型时间线:
-
数据量 50 万帖以内:约 1-2 周
-
数据量 50-200 万帖:约 3-6 周
-
数据量 200 万帖以上:约 6-12 周
八、迁移后检查清单
恢复完成后,按以下清单逐项检查:
| 检查项 | 验证方法 |
|---|---|
| 管理员登录 | 用原账号登录新站点 |
| 用户数量 | 后台统计与旧站一致 |
| 帖子数量 | 后台统计 + 随机抽查 |
| 分类/标签 | 与旧站结构一致 |
| 附件/图片 | 打开几个帖子图片显示正常 |
| 私信 | 进入消息页面检查私信内容 |
| 搜索功能 | 搜索关键词能返回结果 |
| 邮件通知 | 注册新用户能否收到激活邮件 |
| 主题/样式 | 前台样式显示正常 |
| 插件功能 | 各插件工作正常 |
九、总结
| 你的情况 | 推荐方案 | 预计停机时间 |
|---|---|---|
| 换服务器、不换域名、附件少 | 完整备份恢复 | 5-15分钟 |
| 换服务器、附件大 | 分离备份(附件rsync + DB备份) | 视附件大小而定 |
| 换服务器+换域名 | 换域名备份恢复 | 10-30分钟 |
| 同时想上对象存储 | 迁移前先做 uploads:migrate_to_s3 | 无额外停机 |
| 企业级复杂迁移 | 官方企业迁移服务 | 按项目定制 |
一句话:大多数场景用"完整备份恢复"就够了。如果你想顺便解决附件管理问题,迁移到对象存储是更一劳永逸的选择。