你好!
我正计划将一些 Discourse 实例迁移到新的托管环境。我的计划是先将旧站点设置为只读,然后进行备份,将备份迁移到新托管环境并恢复,同时更新 DNS 设置(使用较短的 TTL)。整个流程参考了此处及其他地方的指南。
我已经在本地进行了一些模拟测试,通过修改 /etc/hosts 文件来模拟 DNS 更新(同时在浏览器中禁用了 DNS over HTTPS)。目前进展顺利。
然而,尽管我小心地在“源”站点关闭浏览器,并在“目标”站点完成迁移后再打开,浏览器却忘记了之前的登录状态。
显然,我不希望所有用户在迁移过程中都被登出。我应该从哪里排查,或者我遗漏了什么?
我当前测试的用户具有管理员权限,并启用了双因素认证(2FA)。此外,Discourse 容器位于 Nginx 之后,由 Nginx 负责终止 SSL 连接。这是否会影响问题?
提前感谢任何建议!
2 个赞
我想我会尝试创建一些未启用双因素认证(2FA)的测试账户,看看是否与这个问题有关——很少有网站成员使用 2FA,所以如果只有这些会话丢失,那或许可以接受。
另外,我还会检查源服务器和目标服务器是否已同步到 NTP,不过现在我认为它们之间的时间差应该不会超过几秒。
除此之外,我想还可以尝试查看源代码,弄清楚认证令牌中包含了哪些内容,以及可能导致问题的原因……
2 个赞
IAmGav
(Gavin Perch)
4
您最好的做法是告知用户这一变更,说明他们将需要重新登录。每个服务器在启用 SSL 后都有唯一的签名。与其尝试更改服务器设置,不如让用户重新登录,这样会省去很多麻烦。只需为造成的不便表示歉意,同时强调这是为了做得更好。
2 个赞
但情况真是如此吗?
SSL“签名”会如何影响会话 Cookie(尤其是当在我的案例中,新旧主机使用相同的 SSL 证书文件,且位于同一域名下时)?
3 个赞
[quote=“IAmGav, 帖子:4, 主题:166451”]
仅为造成的不便道歉,但请指出这是为了更好。[/quote]
虽然向会员道歉我毫无问题(
),但我真的想避免那种情况,因为我能看到几个不利的副作用:
- 会员不再登录,未来参与论坛的可能性降低
- 会员忘记密码,需要帮助恢复密码
- 会员忘记密码并创建新账号,导致论坛上留下大量“僵尸账号”,以及丢失或令人困惑的重复身份,且没有用户备注或发帖历史等……
SSL 部分在 Discourse 前端(即使使用 hosts 文件 hack)都能正常工作,如果你仔细想想,这必然是如此,否则负载均衡器就会出问题。据我所知,在此设置中,Discourse 甚至不知道 SSL 的存在,因为 SSL 在 Nginx 处终止。
我想另一个问题是“是否可以将 Discourse 服务器迁移到新 IP 而无需让所有人登出?”我曾假设可以,但也许这个假设是错误的……
3 个赞
riking
(Kane York)
7
我知道论坛会话确实经历过备份和恢复。我不太清楚这里出了什么问题:
3 个赞
david
(David Taylor)
8
会话 Cookie 使用随机生成的密钥进行加密,默认情况下该密钥存储在 Redis 中。Redis 数据不包含在备份中,因此当您将站点恢复到新服务器时,会重新生成新的密钥。
您可以在 app.yml 文件中通过环境变量 DISCOURSE_SECRET_KEY_BASE 手动设置密钥。您可以尝试以下方法来保留会话:
-
在现有服务器上,进入控制台并从 Redis 中查找密钥
pry(main)> GlobalSetting.safe_secret_key_base
=> "5fb9dc98be368599e0a..."
-
在旧服务器的 app.yml 文件的 env: 部分添加 DISCOURSE_SECRET_KEY_BASE,使用您在步骤 (1) 中找到的值,然后重建应用。理论上,如果一切顺利,Discourse 现在应使用 app.yml 中的值,用户会话将得以保留。您可以通过运行以下命令检查环境变量是否生效:
GlobalSetting.secret_key_base
-
确保新服务器上的 app.yml 具有相同的 SECRET_KEY_BASE。当您恢复备份时,用户会话应得以保留。
我尚未测试此流程,因此如果您计划将其用于生产环境的论坛,请务必先进行测试!
附注:您绝对不应在多个 Discourse 实例之间共享密钥。拥有密钥将允许某人解密并修改其在站点上的会话 Cookie,可能导致严重的安全问题。
7 个赞
太好了——我会在沙箱实例上尝试一下。如果成功,我会回来汇报结果:)
明白了。我现在正在考虑是否应该提出一个功能请求,要求在备份中添加导出该密钥的选项?对我来说,网站上所有会话丢失似乎是一件“非常糟糕”的事情,因为该网站上有数千个账户。通过演练迁移过程,我们已经发现了这个问题,但我猜想,如果服务器或 Docker 实例因某种原因丢失,密钥也会随之丢失,我们仍将面临同样的会话丢失问题。
也许在迁移主题中提及这一“功能”也是个不错的主意:Move your Discourse Instance to a Different Server
1 个赞
david
(David Taylor)
10
这需要在安全性和便利性之间进行微妙的权衡。
目前,如果有人成功窃取了 Discourse 备份,他们将拥有论坛上的所有数据。但他们无法登录到实时论坛。密码经过哈希处理,API 密钥经过哈希处理,会话 Cookie 经过加密。
如果我们将密钥包含在备份中,那么任何拥有备份的人都可以访问实时论坛,并进行网络钓鱼、欺诈等行为。
听起来很棒!我们完全愿意在这里的 Meta 板块创建一个主题,解释如何从 Redis 密钥迁移到 app.yml 密钥。该主题可以从“迁移到不同服务器”的主题中链接。
4 个赞
在我看来,默认备份的安全性也应得到加强。虽然密码和会话可能经过哈希处理并受到保护,但私人消息等中可能包含大量其他数据,这些数据仍应保持机密。特别需要注意的是,在我们的社区论坛中,我们鼓励人们使用私人消息交换联系方式并安排交易或取货,而不是将电话号码和地址放在公开场合。
我采取的备份方法是:进入实例,生成备份,然后立即使用 GPG 通过公钥对其进行加密。这使得没有相应私钥的人无法利用该备份,而我将私钥存储在服务器之外,并用密码短语保护。
话虽如此,如果会话的密钥不变,则只需备份一次即可。因此,一个简单的操作流程就足够了——希望这正是你上面概述的内容。
我会尝试一下,看看能否为你创建那个主题 
2 个赞
Stephen
(Stephen)
13
Discourse 不提供“私人消息”功能,该功能称为“个人消息”。这一区分非常重要,因为它并不暗示任何隐私性。
除非启用了加密,否则管理员已经可以阅读站点上的每一条个人消息。
1 个赞
说得好。但这并不能改变这样一个事实:会员可能会通过私信交换个人信息或他们不希望公开的内容。因此,在合理范围内保护这些数据至关重要。
是的,我们也必须信任我们所使用的每个网站的管理员,即使是在像 ProtonMail 这样的网站上。
1 个赞
david
(David Taylor)
15
有点离题……但你可能会对 Discourse Encrypt (deprecated) 感兴趣,那里介绍了如何实现真正“私密”的消息。即使加密的私信备份被泄露或被盗,攻击者也无法读取。
(不过,正如你所说,这仍然基于管理员值得信任的假设)
3 个赞
@david - 请帮忙检查以下帖子,如果没问题的话,请拆分并移动到 howto 好吗?(我无法在那里创建新主题,另外 Akismet 刚刚把帖子隐藏了,这个也需要修复一下
)
1 个赞
david
(David Taylor)
拆分了此话题
17
2 篇帖子已拆分到新主题:迁移到新主机时保留用户会话
@david - 非常感谢你解决这个问题并提供建议,希望这也能帮助到其他人。对我们来说,能够迁移并保留会话确实令人如释重负 
3 个赞