👋

さようなら.env

2023/09/26に公開

TL;DR

  • 環境変数・シークレットを一元管理できるDopplerを導入
  • 対象はモノレポプロジェクト

https://www.doppler.com/

はじめに

先日The death of .env file***という過激タイトルの記事を見つけました

https://medium.com/@tony.infisical/the-death-of-the-env-file-6d65bfc6ac5e

釣り記事かなと思っていたのですが、内容を読んで調べていくととても面白い内容だったので紹介したいと思い記事を書いています。

上記の記事の内容をChatGPTで要約してみました。

環境変数を安全かつ効率的に管理するための新しいアプローチが必要です。従来、多くの開発者は.envファイルを用いてきましたが、これに頼るだけでは、大規模なプロジェクトやチームでの変数の同期やセキュリティが問題となります。そこで、秘密管理プラットフォーム、例えば「Infisical」のようなツールの使用が推奨されます。これにより、環境変数を中央で一元管理し、必要に応じてアクセスや取得ができるようになります。

ざっくりとしたイメージでは開発者向け1Passwordのようなもので、ローカルの.envも管理できるし、あらゆるシークレットを一元管理することができます。

このようにシークレットを管理するアプローチをSecretOpsというらしいです。SecretOpsに関して以下の記事で詳しく書かれていたので気になる方は見てみてください

https://www.doppler.com/blog/siloed-secrets-and-security-theatre-why-we-need-secretops

Pros

Secretや.envのような環境変数を一元管理するプラットフォームを利用することで以下のようなメリットがあります。

環境変数の一元管理

  • 効率的な一元管理: すべての秘密や環境変数を一箇所に集約することで、管理やアクセス、変更が簡単になります。いちいちシークレットを人に聞くようなことがなくなります!
  • 同期の容易さ: 複数の開発者やチームが 開発している場合でも、すべての人が最新の変数を利用できるようになり、変数の非整合性や競合を避けることができます。
  • 履歴のトラッキング: 変数の変更履歴をトラッキングする機能があり、どの変数がいつ変更されたか、誰が変更したかなどの情報を取得できます。

機密情報の漏洩リスクを大幅に削減

  • 漏洩リスクの削減: 秘密情報を集中管理することで、個別の.envファイルを誤って公開するなどのリスクが大幅に減少します。
  • アクセス制御: 特定の環境変数や秘密へのアクセスを、ロールや権限に基づいて制御できます。不要なアクセスを防ぐことができるため、セキュリティが向上します。

スケーラビリティ

  • 拡張性: プロジェクトやチームが大きくなるにつれて、環境変数や秘密の追加や変更が容易になります。
  • マイクロサービス連携: 複数のマイクロサービス間での環境変数の共有や同期が効率的に行えます。
  • 統一された環境: 開発、ステージング、本番などの異なる環境でも、統一されたインターフェースを介して環境変数を管理・取得することができます。

Cons

デメリットとしては以下があげられます

  • 学習コストがかかる
  • 開発者に応じてそれなりの金額がかかる

紹介した記事ではinfisicalを紹介していますが、類似サービスとしてDopplerを実際に試してみました!

https://www.doppler.com/

理由としてはDopplerは3ユーザーまで無料で利用することができるからです!

ちなみに、それぞれのプランごとの制限は以下になります。

https://docs.doppler.com/docs/platform-limits

しばしば個人開発を嗜んでいる私にとって無料でシークレット管理することができるのはとても魅力的です。

TerraformからアクセスするSecretManagerはAWS Secret Managerを使用していましたが、いちいちAWSのアカウントを作成したり、セットアップしたりするのが面倒でした。.envも消すことができてSecretManagerとしても使えるDopplerは私が求めていたサービスでした。

さらに、Dopplerもドキュメントがとても充実しています。

触り心地自体もInficialとそれほど変わりませんでした。

早速やっていきます

使ってみる💪

ローカルでViteとReactで使用していたモノレポのプロジェクト(メルカリShopsのモノレポ構成を参考)にDopplerを組み込みました。筆者がよくプライベートで使用する構成です。

.
├── Makefile
├── README.md
├── container
├── docker-compose.yml
├── go
│   ├── Makefile
│   ├── go.work
│   ├── go.work.sum
│   ├── pkg
│   └── service
│       ├── api
│       └── content-api
├── iac
├── schema
├── test
└── typescript
    ├── Dockerfile.local
    ├── apps
    │   ├── content
    │   ├── service-site
    │   └── system
    ├── package.json
    ├── packages
    │   ├── config
    │   └── ui
    ├── pnpm-lock.yaml
    └── pnpm-workspace.yaml

Dopplerでプロジェクトの作成

Dopplerのアカウントを作成しプロジェクトを作成します。作成する粒度は.envなどを管理したい単位で作成します。

https://docs.doppler.com/docs/create-project

このモノレポのプロジェクトでは以下の5つになりました。

  • system(toB向けのユーザーが閲覧する画面)
  • system-api(systemから呼ばれるAPI)
  • content(toC向けのユーザーが閲覧する画面)
  • content-api(contentから呼ばれるAPI)
  • service-site(サービスサイトの画面)

環境ごとに変数を設定

デフォルトではDevelopment、Staging、およびProductionがあります。もちろんカスタムの環境変数の設定をすることもできます。UIが非常に綺麗で使いやすいです。

https://docs.doppler.com/docs/default-environments

セットアップ

こちらのインストール手順通りに進めていけば簡単に導入できます。

# Prerequisite. gnupg is required for binary signature verification
> brew install gnupg

# Next, install using brew (use `doppler update` for subsequent updates)
> brew install dopplerhq/cli/doppler

❯ doppler --version
v3.66.0

> cd path/to/project

> doppler login

> doppler setup

既存のプロジェクトの.envを取り込む場合は、以下コマンドで簡単にdopplerの方にデータを同期することができます!

doppler import .env

package.jsonなどにある起動コマンドを変更します

> vite preview
以下のように変更
> doppler run -- vite preview

これでアプリケーションコード内でprocess.envから参照できるようになります🎉

process.envで変わらず読み込むことができるのでアプリケーションコードは一切変更する必要はありません👏

ちなみにdoppler runを追加することでコマンドが遅くなるかなと思ってたので計測してみたところ、差は0.5秒ほどしかなかったので開発者体験が悪くなることはなさそうです。

モノレポ構成に対応

モノレポ構成の場合はそれぞれのディレクトリで読み込みたい環境変数が異なります。そのため、doppler.ymlをそれぞれのディレクトリに配置することでディレクトリごとにどのプロジェクトのデータを取得するかを指定することができます。

https://www.doppler.com/changes/doppler-yaml-config

doppler.yml のサンプルは以下のようになっています。rocketプロジェクトのdev環境を指定しています。

setup:
  project: rocket
  config: dev

今回のディレクトリ構成では以下のようにdoppler.ymlを配置しました。

.
├── Makefile
├── README.md
├── container
├── docker-compose.yml
├── go
│   ├── Makefile
│   ├── go.work
│   ├── go.work.sum
│   ├── pkg
│   └── service
│       ├── api
│       │   └── doppler.yml
│       └── content-api
│           └── doppler.yml
├── iac
├── schema
├── test
└── typescript
    ├── Dockerfile.local
    ├── apps
    │   ├── content
    │   │   ├── doppler.yml
    │   │   ├── package.json
    │   │   └── tsconfig.json
    │   ├── service-site
    │   │   ├── doppler.yml
    │   │   ├── package.json
    │   │   └── tsconfig.json
    │   └── system
    │       ├── doppler.yml
    │       ├── package.json
    │       └── tsconfig.json
    ├── package.json
    ├── packages
    │   ├── config
    │   └── ui
    ├── pnpm-lock.yaml
    └── pnpm-workspace.yaml

まとめ

今回は簡単な紹介になるので DockerTerraformに組み込んだりする話は機会があったら記事に書くことにします。ドキュメントがとても充実しているのでないとは思いますが笑。

環境変数とシークレットを一元管理するSecretOpsという考えは自分にとってはとても新鮮な考えで面白かったです。今後プライベートのプロジェクトでは積極的に使っていきたいと考えています。実務でも機会があったら取り入れるかもしれません。

個人開発でTerraformを利用しておりシークレットの管理に悩んでいる人や、.envの管理に煩わしさを感じている人はぜひ触ってみてください!

Discussion