如何为 Chat2DB Community 创建、备份并在容器重建时保留数据源加密密钥
【免费下载链接】Chat2DBChat2DB is a free, cross-platform, local-first database client and SQL workspace for developers, DBAs, analysts, and data teams. Connect to 40+ databases, manage data, edit and run SQL, and use your own AI model to generate, explain, and optimize queries. Available on desktop, web, Docker, and CLI, with MCP support.项目地址: https://gitcode.com/GitHub_Trending/ch/Chat2DB
Chat2DB Community 使用每份安装独立的加密密钥,以 AES-256-GCM 加密保存在本地的数据源密码和 AI 模型 API Key。用 Docker 以 Web 方式部署时,这个密钥不能自动生成:文档明确说明 Web/headless 启动在未提供有效密钥时会失败,只有 Desktop 模式会在密钥缺失时自动创建。这篇文章完成三件事:用仓库自带的初始化脚本一次性创建密钥、把密钥文件单独备份,并让容器挂载宿主机上的同一份密钥文件,使得升级镜像、重建容器后,之前保存的数据源密码和 API Key 仍然可读。
这个密钥保护什么,丢了会怎样
先明确风险边界,再动手:
- 密钥加密两类数据:数据源密码、AI 模型 API Key。二者使用同一个密钥但带不同的 AAD(附加认证数据),因此一类用途的密文无法被当作另一类用途解密;
- 密钥是解码后恰好 32 字节的 Base64 值(标准填充形式为 44 个字符、以
=结尾),属于密码学密钥材料,不是人可读口令; - 替换或丢失密钥会使之前保存的数据源密码和 AI 模型 API Key 无法读取(README.md 的 Encryption Key 一节);
- 解析出的密钥在进程生命周期内缓存,更换密钥配置必须重启应用。
准备条件
- 一份 Chat2DB 仓库检出目录(初始化脚本位于仓库的
script/security/下,获取仓库的方式见 README.md 的 Quick Start); openssl:脚本启动时会检查,缺失则直接退出并提示;- Docker 19.03.0+;使用 Compose 变体时另需 Docker Compose 2.0.0+(Compose V2);
- 2+ CPU 核、4+ GiB 内存(Docker 部署的环境要求);
- 按 README 的 Security Notes,HTTP 服务保持在
127.0.0.1或::1绑定,不要暴露给其他用户或不可信网络。
创建密钥:在仓库检出目录中运行初始化脚本
./script/security/init-community-encryption-key.shinit-community-encryption-key.sh 的行为如下:
- 默认把密钥写入
~/.config/chat2db-community/encryption.key;也可以传一个路径参数,或用环境变量CHAT2DB_COMMUNITY_ENCRYPTION_KEY_FILE指定。优先级为:位置参数 > 环境变量 > 默认路径; - 目标位置已存在有效常规文件时直接复用(不覆盖);拒绝符号链接和非常规文件;已存在的文件无效时拒绝覆盖并以错误退出;
- 新生成时用
openssl rand -base64产生 32 字节随机密钥,临时文件权限 600、目录权限 700,生成后会按“44 字符 Base64、解码后 32 字节”自校验,校验不过即退出; - 重复运行是安全的:同一路径再次执行会复用现有有效密钥,不会生成第二把密钥。
示例输出(路径为你的实际路径):
Community encryption key created: /home/username/.config/chat2db-community/encryption.key decoded-bytes=32再次运行时首行的created变为reused。
可选分支:如果希望密钥放在自定义路径,直接把路径作为参数传入(该路径后续启动 Chat2DB 时必须与配置一致,见文末的解析顺序):
./script/security/init-community-encryption-key.sh /secure/path/chat2db-community.key备份密钥文件:单独保存,并且重建时保留
README 对备份的要求是:把这个文件单独备份,并在升级和容器重建之间保留它。具体要点:
- 备份对象就是
encryption.key文件本身——文件内容即密钥,把它复制到你的备份位置(备份介质与存放位置由你决定); - 备份文件同样应只允许 Chat2DB 进程属主可读,与脚本生成的 600/700 权限保持一致;
- 不要用重新生成一把新密钥的方式“替换”旧密钥:替换密钥后,旧密钥加密的既有数据源密码和 API Key 会无法读取。迁移到新机器时,应把旧密钥文件复制到新机器的默认路径(或你配置的自定义路径),再让容器指向它。
容器启动时挂载同一份密钥
Docker 部署的做法是:把宿主机密钥文件以只读方式挂载进容器内的/run/secrets/chat2db-community-encryption.key,并用环境变量CHAT2DB_COMMUNITY_ENCRYPTION_KEY_FILE指向该路径。加密后的数据存在容器数据卷里,密钥存在宿主机上,两者分开——只要宿主机的密钥文件保留,重建容器或升级镜像都不会丢密钥。
方式一:使用仓库自带的 Compose 定义
docker/docker-compose.yml 中与密钥和数据相关的配置是:
services: chat2db: image: chat2db/chat2db:${CHAT2DB_IMAGE_TAG:-latest} container_name: chat2db-community restart: unless-stopped ports: - "${CHAT2DB_BIND_ADDRESS:-127.0.0.1}:${CHAT2DB_PORT:-10825}:10825" environment: CHAT2DB_COMMUNITY_ENCRYPTION_KEY_FILE: /run/secrets/chat2db-community-encryption.key volumes: - chat2db-community-data:/root/.chat2db-community - "${HOME}/.config/chat2db-community/encryption.key:/run/secrets/chat2db-community-encryption.key:ro" volumes: chat2db-community-data:说明:数据落在命名卷chat2db-community-data(容器内/root/.chat2db-community);端口与镜像标签默认值分别为127.0.0.1:10825和latest,可用环境变量CHAT2DB_BIND_ADDRESS、CHAT2DB_PORT、CHAT2DB_IMAGE_TAG覆盖。注意 Compose 定义从宿主机的~/.config/chat2db-community/encryption.key挂载密钥,所以使用 Compose 时密钥应放在脚本的默认路径。
启动命令:
./script/security/init-community-encryption-key.sh docker compose --file docker/docker-compose.yml up --detach方式二:docker run
docker run 示例 中,密钥的挂载方式与 Compose 相同(宿主机默认路径挂到容器内/run/secrets并设置同名环境变量):
docker run --detach \ --name chat2db-community \ --restart unless-stopped \ --publish 127.0.0.1:10825:10825 \ --volume "$HOME/.chat2db-community-docker:/root/.chat2db-community" \ --env CHAT2DB_COMMUNITY_ENCRYPTION_KEY_FILE=/run/secrets/chat2db-community-encryption.key \ --volume "$HOME/.config/chat2db-community/encryption.key:/run/secrets/chat2db-community-encryption.key:ro" \ chat2db/chat2db:latest如果密钥使用了自定义宿主机路径,只要把最后一个--volume的宿主机一侧换成你的密钥文件路径,并保持容器内路径与CHAT2DB_COMMUNITY_ENCRYPTION_KEY_FILE的值一致即可。
两种方式的容器内数据目录相同(/root/.chat2db-community),但宿主机位置不同:docker run示例使用$HOME/.chat2db-community-docker,Compose 定义使用chat2db-community-data命名卷,两者不共享数据。需要数据连续时不要混用。
升级镜像与重建容器
README 给出的更新流程:拉取新镜像、移除旧容器、重新运行启动命令;期间保留~/.config/chat2db-community/encryption.key。由于密钥文件在宿主机、数据卷未被删除,重建后既有加密数据与密钥都完整,服务继续用同一把密钥解密旧数据。
一个边界要注意:Chat2DB Community 5.3.0 使用独立的/root/.chat2db-community目录,不会自动迁移更早镜像使用/root/.chat2db时的数据。
结果验证
按以下顺序确认:
- 脚本运行后输出
Community encryption key created: <path>(或reused: <path>)以及decoded-bytes=32;如果已有密钥文件无效,脚本会报告 invalid 且不覆盖; - 密钥文件本身应为 44 字符的 Base64、以
=结尾、解码后恰好 32 字节——脚本每次运行都按这个标准校验; - 启动服务:没有有效密钥时 Web/headless 启动会失败,不会回退到其他来源;启动成功后,在浏览器打开
http://localhost:10825即可访问。
密钥解析顺序与限制
启动时按以下顺序解析密钥配置,第一个配置到的值生效,不做向下回退:
- JVM 属性
chat2db.community.encryption-key(直接包含 Base64 密钥); - 环境变量
CHAT2DB_COMMUNITY_ENCRYPTION_KEY(直接包含 Base64 密钥); - JVM 属性
chat2db.community.encryption-key-file(包含密钥文件路径); - 环境变量
CHAT2DB_COMMUNITY_ENCRYPTION_KEY_FILE(包含密钥文件路径); - 默认文件
~/.config/chat2db-community/encryption.key。
空值、格式错误的 Base64、解码不为 32 字节的密钥或无效密钥文件都会直接导致启动失败。文档推荐文件方式(第 3~5 项),避免把密钥值直接放在进程参数或环境变量里。
密钥在进程生命周期内缓存,所以恢复备份、更换密钥文件之后必须重启应用,新密钥才会生效。密钥的加载与校验实现可参考 CommunityEncryptionKeyStore.java 与 AesGcmUtil.java。
【免费下载链接】Chat2DBChat2DB is a free, cross-platform, local-first database client and SQL workspace for developers, DBAs, analysts, and data teams. Connect to 40+ databases, manage data, edit and run SQL, and use your own AI model to generate, explain, and optimize queries. Available on desktop, web, Docker, and CLI, with MCP support.项目地址: https://gitcode.com/GitHub_Trending/ch/Chat2DB
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考