pubanswer

从 dotenv 到 dotenvx:下一代配置管理

像素游侠P2024-06-26

在美国独立日后的第二天,我编写了 dotenv 的第一个提交并在 npm 上发布了版本 0.0.1。它看起来是这样的。

在过去的 11 年里,它已经成为全球最依赖的软件包之一,与 TypeScript 和 ESLint 等普遍存在的软件齐名。它是“伟大事物有小的开始”的例子。README 很短,代码很简洁,但今天它被数百万开发者所喜爱。它是少数能以最小的麻烦提升你安全姿态的安全工具之一:

  • 一行代码:require('dotenv').config()
  • 一个文件:.env
  • 一个 gitignore 追加:echo '.env' >> .gitignore

它美观、有效且优雅。

但它并非没有问题!这就是我想讨论的内容。

dotenv 的问题

按重要性顺序,dotenv 存在三个主要问题:

  1. 泄露你的 .env 文件
  2. 管理多个环境
  3. 跨平台的不一致性

所有这三个问题都对安全构成风险,第一个问题尤为严重。

但我认为今天我们可以用 dotenvx 解决这三个问题。按反向顺序来看:

  • 运行在任何地方 -> 跨平台不一致性
  • 多环境 -> 管理多个环境
  • 加密 -> 泄露你的 .env 文件

让我们深入了解每个问题。我会尽量展示而非讲述。

运行在任何地方

dotenvx 在每种语言、框架和平台上的工作方式都是相同的——在运行时通过 dotenvx run -- your-cmd 注入环境变量。

$ echo "HELLO=World" > .env
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
$ node index.js
Hello undefined # 没有 dotenvx
$ dotenvx run -- node index.js
Hello World # 使用 dotenvx

.env 解析引擎、变量扩展、命令替换等功能完全相同。通过 npm、brew、curl、docker、windows 等方式安装 dotenvx。

这解决了跨平台不一致性的问题。✅ 你会在 Python、Node 和 Rust 应用中得到完全相同的行为。

多环境

创建一个 .env.production 文件并使用 -f 来加载它。这既简单又灵活。

$ echo "HELLO=production" > .env.production
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
$ dotenvx run -f .env.production -- node index.js
[dotenvx][info] loading env (1) from .env.production
Hello production

虽然 dotenvx 中的一切都受到社区建议的启发,但这个多环境特性尤其如此。之前有很多类似的建议,我也逐渐理解了它的用处。我现在相信它可以干净地解决命令行内置的多个环境管理问题。✅

你甚至可以用多个 -f 标志组合多个环境。

$ echo "HELLO=local" > .env.local
$ echo "HELLO=World" > .env
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
$ dotenvx run -f .env.local -f .env -- node index.js
[dotenvx] injecting env (1) from .env.local, .env
Hello local

非常方便!但下一个功能——加密,才是真正的游戏规则改变者(我认为这使得 dotenvx 成为下一代配置管理工具)。

加密

用一个命令为你的 .env 文件添加加密。运行 dotenvx encrypt

$ dotenvx encrypt
✔ encrypted (.env)
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/            public-key encryption for .env files          /
#/       [how it works](https://dotenvx.com/encryption)     /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY="03f8b376234c4f2f0445f392a12e80f3a84b4b0d1e0c3df85c494e45812653c22a"
# Database configuration
DB_HOST="encrypted:BNr24F4vW9CQ37LOXeRgOL6QlwtJfAoAVXtSdSfpicPDHtqo/Q2HekeCjAWrhxHy+VHAB3QTg4fk9VdIoncLIlu1NssFO6XQXN5fnIjXRmp5pAuw7xwqVXe/1lVukATjG0kXR4SHe45s4Tb6fEjs"
DB_PORT="encrypted:BOCHQLIOzrq42WE5zf431xIlLk4iRDn1/hjYBg5kkYLQnL9wV2zEsSyHKBfH3mQdv8w4+EhXiF4unXZi1nYqdjVp4/BbAr777ORjMzyE+3QN1ik1F2+W5DZHBF9Uwj69F4D7f8A="
DB_USER="encrypted:BP6jIRlnYo5LM6/n8GnOAeg4RJlPD6ZN/HkdMdWfgfbQBuZlo44idYzKApdy0znU3TSoF5rcppXIMkxFFuB6pS0U4HMG/jl46lPCswl3vLTQ7Gx5EMT6YwE6pfA88AM77/ebQZ6y0L5t"
DB_PASSWORD="encrypted:BMycwcycXFFJQHjbt1i1IBS7C31Fo73wFzPolFWwkla09SWGy3QU1rBvK0YwdQmbuJuztp9JhcNLuc0wUdlLZVHC4/E6q/K7oPULNPxC5K1LwW4YuX80Ngl6Oy13Twero864f2DXXTNb"
DB_NAME="encrypted:BGtVHZBbvHmX6J+J+xm+73SnUFpqd2AWOL6/mHe1SCqPgMAXqk8dbLgqmHiZSbw4D6VquaYtF9safGyucClAvGGMzgD7gdnXGB1YGGaPN7nTpJ4vE1nx8hi1bNtNCr5gEm7z+pdLq1IsH4vPSH4O7XBx"
# API Keys
API_KEY="encrypted:BD9paBaun2284WcqdFQZUlDKapPiuE/ruoLY7rINtQPXKWcfqI08vFAlCCmwBoJIvd2Nv3ACiSCA672wsKeJlFJTcRB6IRRJ+fPBuz2kvYlOiec7EzHTT8EVzSDydFun5R5ODfmN"
STRIPE_API_KEY="encrypted:BM6udWmFsPaBzlND0dFBv7R55JiaA+cZnbun8DaVNrEvO+8/k+lsXbZQ0bCPks8kUsdD2qrSp/tii0P8gVJ/gp+pdDuhdcJj91hxJ7nzSFf6h0ofRb38/2WHFhxg77XExxzui1s3w42Z"
# Logging
LOG_LEVEL="encrypted:BKmgv5E7/l1FnSaGWYWBPxxagdgN+KSEaB+va3PePjwEp7CqW6PlysrweZq49YTB5Fbc3UN/akLVn1RZ2AO4PyTVqgYYGBwerjpJiou9R2KluNV3T4j0bhsAkBochg3YpHcw3RX/"

生成一个 DOTENV_PUBLIC_KEY(加密密钥)和一个 DOTENV_PRIVATE_KEY(解密密钥),使用与比特币相同的公钥加密技术。

现在,即使你泄露了你的 .env 文件也没关系。攻击者需要 DOTENV_PRIVATE_KEY 才能解密。这有效地解决了泄露 .env 文件的问题 ✅。

附加好处:这种方法还使贡献者能够在无法解密配置的情况下添加配置。我预计这对开源项目会很有用,因为你希望允许秘密贡献而不解密先前的秘密。

1.0.0 版本发布

因此,我们很高兴地宣布发布 dotenvx 版本 1.0.0 🎉。它是下一代配置管理工具,我期待看到你们如何使用它。未来十年(如同过去十年)对 dotenv 来说是光明的!🌟