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