记一次统计软件umami由环境变量丢失引发无法登录的排查与恢复
如果你用1panel应用商店安装的umami且2FA加密密钥是自己手动改环境变量文件添加的话,千万别忘记备份这个密钥。要不然再更新的时候1panel模板就会给它覆盖掉造成丢失。然后你就登录不上了。
首先第一步是要解决这个报错,那就是重新把变量写回。由于1panel应用商店在底层上使用的是Docker Compose,你可以在安装目录里.env文件里写入这个环境变量,也可以将环境变量写入编排文件的“environment”对象下。这两个地方都可以写环境变量。
键名:
1 | TWO_FACTOR_ENCRYPTION_KEY |
值(也就是2FA的加密密钥)用以下命令生成:
1 | openssl rand -hex 32 |
umami只接受32位HEX字串,base64不行。我就是因为这个卡了老半天才发现表达的类型不对。(当前版本3.3.1)
解决报错的问题了,能够正常调用登录了。但真正的麻烦还在后面……
如果你一开始没备份最开始的那个密钥,丢失后你就永远找不回来了,重新建变量只能重新生成一个新的。你也别指望人脑能始终记得住一个32位(64字符)字符串HEX。
重新生成的虽然能走正常的登录流程,但你是绝对登不上的——新的密钥无法解密由旧密钥绑定的2FA验证码。
我的运气比较好,保存了umami的恢复密钥,这样就可以暂时绕过2FA直接登录了。需要注意每个恢复密钥只能使用一次,这只是临时恢复自己权限用的,不是权宜之计。
当然,你也可以选择直接改数据库。毕竟你是服务器主人,应用层面的限制直接明牌。唯一的问题是这个软件的表结构要啃一遍,很折磨。
临时恢复后,首先就是要解绑原来的2FA,旧的无法解密新的,反之亦然。如果你本来就备份过旧的那个32位HEX,直接写回去就能无缝衔接一切照常。这里面有给非常反人类的点,解绑2FA需要验证原来的验证码(我特么都能登录了)。而原来的验证码由于密钥变化导致无法验证,这不死循环了吗?
所以这种情况下,我们必须得从底层改数据库了。
1 | docker exec -it 容器名 psql -U 数据库用户名 -d 数据库名 -c "\d two_factor_auth" -c "SELECT user_id, username FROM \"user\" WHERE username='admin';" |
(修改里面的替换对应的真实值,其中umami对应的用户是admin)
这个命令可以看数据库对应软件用户的id,然后拿到这个id之后就可以直接去操作删除对应用户的设置项了。
从库里删除2FA绑定和恢复密钥:
1 | docker exec -it 容器名 psql -U 数据库用户名 -d 数据库名 \ |
当然,你也可以选择不删除恢复密钥,只删除2FA:
1 | docker exec -it 容器名 psql -U 数据库用户名 -d 数据库名 \ |
(其实就是把末尾那一行删掉而已)
看到umami设置里2FA的开关变成灰的就算成功了,这样我们通过直接操作数据库删除了旧数据,再次打开那个开关再绑定一次2FA就更新成功了。
我写这篇的目的是为了复盘,为了以后再遇到可以搜一下就能看到以前的经验。
那么,真正导致2FA加密密钥丢失的原因是自己手动操作修改文件后再用1panel应用商店里更新而引发的模板覆盖。 难道没有办法能持久化了吗?
当然有了,1panel有个很容易被忽视的“高级功能”就可以实现更新应用市场应用的时候不丢失自定义环境修改。
具体操作流程:
1 | 应用商店->已安装->对应的应用->参数->编辑->勾选“高级设置”->勾选“编辑compose文件” |
然后你就能看见该应用的容器编排文件了,直接在这里的environment对象下写自定义的环境变量即可,{它会在更新后自动应用上而不丢失(类似自定义模板)}(需要测试,可能不会自动)。更重要的:另外备份一份这个服务端2FA密钥,不然丢失重建后面就像现在一样会很麻烦。
就算是它不会自动应用,在升级应用的时候1panel也给自定义编排(compose),手动填回去再“使用自定义docker-compose.yml”升级也可以做到无损更新。

