我的 API Key 散在 7 个 .env 里,试了三种方案才收拢

举报
yd_231995061 发表于 2026/11/04 19:46:51 2026/11/04
【摘要】 7 个项目 12 个密钥,一度差点误提交。记录两种走不通的做法、最终采用的方案,以及我认为密钥管理不能松的三条原则。

先说结论:我把 7 个项目的 API Key 从各自散落的 .env 里收拢到了一个地方,方法是起一个只写不读的密钥服务。下面是我试错的过程,包括两条走不通的路。

起因

整理硬盘时数了一下,7 个 .env 文件,12 个不同服务的密钥。Stripe、OpenAI、GitHub、两个云厂商、一个短信服务、一个地图 API,还有几个我已经忘了是干什么的。

其中有个项目 .gitignore 里只写了 .env,没写 .env.local,那个文件就差一次 commit。这种险我大概冒了一年多。

问题不只是泄露风险。改一个密钥要翻五个目录,改漏一个,那个项目半夜就开始报 401。换台机器要重配一遍,因为 .env 不在仓库里,得从别的地方找回全部 12 个。同事问"那个 key 是啥",只能截图发微信。

试过但不推荐的两条路

方案一:全部塞进系统环境变量

听起来最省事。写进 ~/.zshrc 或者 Windows 的系统环境变量,之后所有项目直接读。

死的很直接:改一个要改配置文件再 source 一遍,IDE 里的终端经常不跟着刷新,改了半小时代码还在用旧值。而且换机器的时候,12 个 key 还是得手工搬过去——它只是把 .env 移了个位置,没解决核心问题。

方案二:加密后提交进仓库

用 git-crypt 或者 openssl 把 .env 加密,密文提交,本地解密。

死在一个死循环上:解密的密钥本身存哪?存本地还是等于没加密;存 CI 的 secrets 里,那又回到"密钥散在各平台"的老问题。而且团队新人的入职流程会变成"先教你配加密环境",比配 .env 还麻烦。

最后采用的做法

起一个小的密钥服务,所有密钥存在里面,项目代码不改——照常从环境变量读值,值在运行时由服务注入。

具体用的是 GitHub 上的 treg(tools-registry),Python 写的。选它不是因为功能多,是因为它的设计思路跟我要的一致。装 CLI 就一个包:

pip install tools-registry

注意这只有命令行工具,想自己跑服务端还得装扩展,后面会踩这个坑。

存密钥:

treg secret add STRIPE_KEY --value sk_live_xxx

文件类凭据(比如 GCP 的 service account json)走另一条:

treg secret add GCP_SA --file ./sa.json --kind secret_file

看有哪些(只列名字和类型,看不到值):

treg secret ls

我认为重要的三条原则

工具能换,这三条我觉得不能松。

一、存进去的密钥不该取得回来。

treg 的接口设计成只写不读——你存了 sk_live_xxx,之后任何 API 调用都拿不回原文,只能用不能看。这不是技术做不到,是故意不给。

理由很实在:后端被拖库的时候,加密过的密文比明文值钱得多。而且"取不回来"这个约束会强迫你在创建密钥的时候就登记清楚用途,而不是随手贴进某个文件里。

二、密钥要注入,不要暴露。

它注入的方式是在起子进程时塞进环境,父进程的环境里没有。核心就一行:

env.update(secret_env)  # 按存储时的名字注入子进程

这样即使项目里某个第三方依赖想读环境变量,它也只能读到被授权的那几个,而不是全家桶。

三、名字匹配得有确定规则。

这条是我用下来最意外的收获。它导入 .env 时不是按名字死死对齐,而是把变量名按下划线切开去比对,比如 TREG_RESEND_API_KEY 会去匹配 RESEND。关键是取最长匹配:同时存在 HF 和 HUGGINGFACE 时,HUGGINGFACE_API_KEY 必须命中长的那个。

没有这条规则,短 token 会抢走本该属于长 token 的密钥,绑到错的凭据上,而且报错信息通常只会告诉你"认证失败",很难查到根因。

踩到的三个坑

装错包。前面提过,pip install tools-registry 只装 CLI。想自己跑服务端要加 [server],否则会连不上服务。我在这上面浪费了二十分钟。

以为存完就能直接用。实际上 add 只是把值存进去,还得建一个绑定关系,告诉它"这个密钥给哪个 API 用、放哪个 header 里"。我第一次存完直接调用,报找不到绑定,愣了挺久。

--kind 选错。json 文件必须标成 secret_file。用默认的 env 会把它当成一整串字符串塞进环境变量,项目里读出来全是转义符,报的错还特别迷惑。

自建服务端的命令

团队共用就起一个服务,大家连同一个,密钥只落在服务器上。两条命令:

uv run python -m treg keygen   # 生成加密用的密钥,只用一次
uv run python -m treg          # 起服务,默认 0.0.0.0:18790

什么场景够用,什么场景不够

说实话它不算严肃的生产级方案。没有细粒度权限控制,没有审计日志,没有自动轮换,也没有高可用。真要给几十人的团队用,Vault 或者云厂商的 KMS 才是正解。

但对我这种一个人维护几个项目、偶尔两三个人协作的场景,它把最要命的那件事解决了:密钥不再散落在磁盘各个角落,也不会跟着一次手滑的 commit 跑出去。

12 个密钥收拢到一处之后,我至少能一眼看清自己有哪些凭据、分别用在哪。这件事本身比工具选得对不对更重要。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。