应用密钥与加密
本页说明运行 KolleK 时最重要的一条运维原则。实例的其他一切,只要有耐心都能挽回;唯独这一项设置,一旦出错就会造成不可逆的数据损失。
这个密钥的作用
KolleK 使用实例的应用密钥(也就是 .env 中的 APP_KEY)对静态敏感字段进行加密。姓名、藏品详情、自定义字段值、文件名、邮件记录、Webhook 密钥:大约有三十个模型带有加密字段。这些字段存入数据库的内容是密文,没有密钥就无法读取。同一个密钥也保护着用户会话。
你的数据是如何被保护的 从用户的角度描述了同样的机制。从运维角度看,这个密钥不是一项普通的配置,而是你数据的一半。
这条原则
警告
应用密钥只在首次启动前设置一次,之后绝不能在正在运行的实例上更改。一旦密钥丢失或被更改,所有加密字段和所有会话都将永久无法读取。没有任何恢复手段、没有技术支持、也没有任何工具能把数据找回来。
由此带来三个实际后果:
- 把密钥和数据一起备份。 没有对应密钥的数据库备份,恢复出来的只是一堆密文。请把密钥存放在密码管理器或密钥保管服务中,与服务器本身分开保存。
- 确保处处一致。 三个应用容器(web、queue、scheduler)必须使用同一个密钥运行。项目提供的 Compose 文件通过共享同一份
.env来保证这一点,如果你做自定义部署,也要保留这个特性。 - 不要“为了保险”重新生成密钥。 在正在运行的实例上执行
key:generate是最典型的自食其果的灾难。实例在没有密钥时会拒绝启动,正是为了避免有人在不知情的情况下缺失密钥启动实例,然后在运行期间生成一个全新的密钥。
有计划地轮换密钥
出于合规等原因,一些运维者需要按计划定期轮换密钥。KolleK 通过“历史密钥”机制支持这一需求:当前的 APP_KEY 用于加密所有新数据,而列在 APP_PREVIOUS_KEYS(以逗号分隔)中的密钥仍然可以解密已有数据。
APP_KEY=base64:NEW_KEY_HERE
APP_PREVIOUS_KEYS=base64:OLD_KEY_HERE
使用 php artisan key:generate --show 生成新密钥(切勿直接使用不带参数的 key:generate,那样会直接覆盖你正在使用的密钥),把旧密钥移入 APP_PREVIOUS_KEYS,把新密钥设为 APP_KEY,然后重新创建容器。
警告
只要某个密钥加密过的数据还存在,就绝不能把它从 APP_PREVIOUS_KEYS 中移除。数据只有在再次被写入时才会用新密钥重新加密,因此旧记录可能会无限期地依赖旧密钥。
如果没有强制要求你轮换密钥,最简单安全的做法就是:一个密钥,只设置一次,妥善备份。
接下来去哪里
- 确保这个密钥被纳入你的 备份与恢复方案 之中。
- 在 你的数据是如何被保护的 中阅读面向用户的加密说明。
KolleK 文档
在 GitHub 上编辑此页
此页面有帮助吗?