こんにちは。クロスイノベーション本部 AIデータテクノロジーユニット AIトランスフォーメーションセンターの青木 尚人です。
本記事では、SOPS を利用してチーム開発の環境変数管理を標準化する方法を紹介します。
はじめに
チーム開発で .env を使っていると、次のような運用になりがちです。
.envの実際の値を Slack や Teams で共有する- 新規メンバーが入るたびに、誰かが
.envを手作業で渡す .env.exampleはあるが、実際の値とはずれている- どの値が最新なのかわからない
- 秘密情報とそうでない値が混ざっている
.envを誤って Git にコミットしてしまう
そこで今回は、SOPS + Azure Key Vault + mise を使って、暗号化された .env を Git 管理できるようにします。
この記事で紹介するのは、次のような手順での環境変数の管理方法です。
- SOPS で
.env形式のファイルを暗号化する - Azure Key Vault の Key を SOPS の暗号化・復号に使う
- mise で
sopsとazure-cliを導入する - mise task で
.envの復号・生成コマンドを標準化する
この記事の前半では、まず SOPS を利用して暗号化された環境変数を作成します。
その後、mise task を使って .env の生成手順を標準化します。
本記事で紹介するプロジェクトで想定している最小の構成は以下です。
Existing Git Repository ├── .env.sops.env # SOPSで暗号化された.env。Git管理する ├── .env # 復号して生成する.env。Git管理しない ├── .sops.yaml # SOPSの暗号化設定。Git管理する └── mise.toml # ツールとタスク定義。Git管理する Azure Key Vault └── Key Vault Key # SOPSの暗号化・復号に使う鍵
SOPS とは
SOPS は、YAML、JSON、ENV、INI などのファイルを暗号化して管理するためのツールです。
- 公式ドキュメント: https://getsops.io/docs/
- GitHub リポジトリ: https://github.com/getsops/sops
一般的な暗号化ツールと違い、ファイル全体を単純にバイナリ化するのではなく、設定ファイルとして扱いやすい形で暗号化できます。
例えば .env 形式のファイルであれば、暗号化後もキー名は読める状態にしつつ、値だけを暗号化できます。
似た選択肢としては、Azure Key Vault Secret に環境変数を1つずつ保存する方法、.env.example で項目だけ共有する方法、.env ファイルの暗号化に特化したツールとして dotenvx もあります。
dotenvx は、既存の .env 運用に近い形で暗号化された .env ファイルを扱えるため、.env を中心にシンプルに管理したい場合は有力な選択肢です。
一方、今回の構成では Azure Key Vault の Key を使って復号権限を Azure 側で制御したかったため、SOPS を採用しています。
SOPS は .env だけでなく YAML、JSON、INI など複数の設定ファイル形式を扱えるため、環境変数以外の設定ファイル管理にも広げやすい点もメリットです。
暗号化前の .env が次のような内容だったとします。
DATABASE_URL=postgresql://demo_user:demo_password@localhost:5432/demo_db API_TOKEN=dummy-api-token JWT_SECRET=dummy-jwt-secret
SOPS で暗号化すると、次のようなファイルになります。
DATABASE_URL=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str] API_TOKEN=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str] JWT_SECRET=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]
この状態なら、暗号化された .env ファイルを Git 管理できます。
値は暗号化されているため、リポジトリに置いても平文の secret は見えません。
Azure Key Vault は何に使うのか
今回、Azure Key Vault は、環境変数そのものの保存先ではなく、SOPS がデータキーを保護するための Key Vault Key の管理基盤として使います。
Azure Key Vault では、主に次の3種類のオブジェクトを管理できます。
- Key
- Secret
- Certificate
このうち、今回使うのは Secret ではなく Key です。
環境変数を Azure Key Vault Secret に1つずつ保存する構成ではありません。
SOPS が暗号化・復号に使う鍵を、Azure Key Vault Key として管理します。
Azure Key Vault
└── Key
└── SOPSが.env.sops.envを暗号化・復号するために使う
SOPS は、ファイル本体の値を暗号化し、その暗号化・復号に必要な情報をファイル内に保持します。
ただし、その復号には Azure Key Vault Key へのアクセス権が必要です。
そのため、次のような管理ができます。
- Git には暗号化済みの
.env.sops.envを配置する - 復号できる人は Azure Key Vault の権限で制御する
- チャットで
.envの平文を共有しない - メンバー追加・削除時は Azure 側の権限を見直す
ここが、この構成の重要なポイントです。
mise とは
mise は、プロジェクトで使う CLI ツールのバージョン管理や、タスク定義をまとめて扱えるツールです。
SOPS と Azure CLI を各メンバーが個別にインストールしても、この構成は実現できます。
ただし、それだと次の問題が残ります。
- SOPS がインストールされていない
- Azure CLI がインストールされていない
- メンバーごとにバージョンが異なる
.envを生成するコマンドを毎回説明する必要がある
mise を使うと、プロジェクトに必要な CLI ツールとタスクを mise.toml にまとめられます。
[tools] sops = "3.12.2" azure-cli = "2.84.0"
これをプロジェクトに置いておけば、メンバーは次のコマンドで必要なツールをそろえられます。
mise install
さらに、.env を生成する処理も mise task にできます。
mise run env:render
つまり mise を使う理由は、単にツールを入れたいからではありません。
チーム全員が同じコマンドで、同じ手順を実行できるようにするためです。
ここからは、mise のインストール手順から、Azure Key Vault と SOPS を使った環境変数の管理手順までを順に紹介します。
mise をインストールする
macOS では Homebrew でインストールできます。
brew install mise
zsh を使っている場合は、シェルに mise を有効化する設定を追加します。
echo 'eval "$(mise activate zsh)"' >> ~/.zshrc source ~/.zshrc
インストールできたか確認します。
mise --version
macOS 以外のインストール方法は、公式ドキュメントを参照してください。
https://mise.jdx.dev/getting-started.html
mise.toml に sops と azure-cli を追加する
既存プロジェクトのルートに mise.toml を用意します。
すでに mise.toml がある場合は、既存の [tools] に追記してください。
[tools] sops = "3.12.2" azure-cli = "2.84.0"
コマンドで追加する場合は、以下のようにします。
mise use sops@3.12.2 mise use azure-cli@2.84.0
その後、ツールをインストールします。
mise install
確認します。
sops --version az version
Azure にログインする
SOPS が Azure Key Vault を使って復号するには、ローカル端末が Azure に認証済みである必要があります。
まず Azure にログインします。
az login
現在のサブスクリプションを確認します。
az account show -o table
必要であれば、利用するサブスクリプションに切り替えます。
az account set --subscription "<subscription-id-or-name>"
Azure Key Vault と Key を作成する
すでにチームで利用している Key Vault がある場合は、既存の Key Vault に SOPS 用の Key を追加しても構いません。
Key Vault の作成
Azure Portal から操作する場合は以下のようになります。

トップ画面からキーコンテナーを選択します。

作成ボタンを押下して、キーコンテナーを作成します。

基本タブでリソースグループとリージョンを選択します。

アクセス制御タブでは「Azureロールベースのアクセス制御(RBAC)」を選択してください。

ネットワークタブでは必要に応じてアクセス制御を設定します。
ここではデフォルトの「すべてのネットワークからのアクセスを許可する」を選択します。
※実運用では要件に合わせて制限してください。特に本番 secret に関わる Key Vault では、ネットワーク制限を含めた設計が必要です。

最後に確認タブで設定を確認し、作成ボタンを押下してキーコンテナーを作成します。
Key Vault のアクセス制御で権限を付与する
次に、Key Vault の Key を使えるように、アクセス制御で権限を付与します。

アクセス制御(IAM)タブを開き、ロールの割り当てを追加します。
Key Vault の Key を作成・編集する管理者には「キー コンテナー暗号化責任者」を割り当てます。
一方で、一般的な開発メンバーが環境変数の暗号化・復号に利用するだけであれば、「キー コンテナー暗号化ユーザー」を割り当てるのが適切です。

ここでは、Key を作成するために「キー コンテナー暗号化責任者」のロールを自身に割り当てます。
SOPS 用の Key の作成

[オブジェクト > キー] のタブから「+ 生成/インポート」を押下します。

名前や RSA キーサイズを選択して、環境変数を暗号化する SOPS 用の Key を作成します。
作成した Key の ID を取得します。

出力例は以下のとおりです。
https://kv-sops-xxxx.vault.azure.net/keys/sops-env-key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
この Key ID を SOPS の設定で使います。
.sops.yaml を追加する
プロジェクトルートに .sops.yaml を追加します。
creation_rules: - path_regex: \.env\.sops\.env$ azure_keyvault: - https://kv-sops-xxxx.vault.azure.net/keys/sops-env-key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
この設定により、.env.sops.env という名前のファイルを SOPS で作成するときに、Azure Key Vault の Key が使われます。
暗号化前の .env を用意する
ここでは、既存の .env から secret を含む値を暗号化する想定で進めます。
記事用の例ではダミー値を使います。
.env.plain という名前で、次のような内容を用意します。
DATABASE_URL=postgresql://demo_user:demo_password@localhost:5432/demo_db API_TOKEN=dummy-api-token JWT_SECRET=dummy-jwt-secret
SOPS で .env を暗号化する
.env.plain を SOPS で暗号化し、.env.sops.env を作成します。
sops encrypt \ --filename-override .env.sops.env \ --input-type dotenv \ --output-type dotenv \ .env.plain > .env.sops.env
暗号化後のファイルを確認します。
cat .env.sops.env
次のように値が ENC[...] 形式になっていれば成功です。
DATABASE_URL=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str] API_TOKEN=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str] JWT_SECRET=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]
暗号化前の一時ファイルは削除します。
rm .env.plain
この時点で、Git 管理する対象は .env.sops.env です。
平文の .env や .env.plain ではありません。
復号して .env を生成する
復号できるか確認します。
sops decrypt .env.sops.env
以下のような出力が得られれば成功です。
DATABASE_URL=postgresql://demo_user:demo_password@localhost:5432/demo_db API_TOKEN=dummy-api-token JWT_SECRET=dummy-jwt-secret
問題なければ、.env に出力します。
sops decrypt .env.sops.env > .env chmod 600 .env
これでアプリケーションが読む .env が生成されます。
cat .env
出力例は以下のとおりです。
DATABASE_URL=postgresql://demo_user:demo_password@localhost:5432/demo_db API_TOKEN=dummy-api-token JWT_SECRET=dummy-jwt-secret
mise task で .env 生成を標準化する
毎回 sops decrypt .env.sops.env > .env と入力するのは手間です。
そこで、mise.toml にタスクを追加します。
[tasks."env:render"] description = "Generate .env from encrypted env file" run = ''' set -euo pipefail sops decrypt .env.sops.env > .env chmod 600 .env echo "generated: .env" ''' [tasks."env:decrypt"] description = "Print decrypted env to stdout" run = "sops decrypt .env.sops.env"
これで、開発者は次のコマンドだけで .env を生成できます。
mise run env:render
以下のような出力が得られれば成功です。
% mise run env:render [env:render] $ sops decrypt .env.sops.env > .env generated: .env
復号結果を標準出力で確認したい場合は、次を使います。
mise run env:decrypt
以下のような結果が得られれば成功です。
% mise run env:decrypt [env:decrypt] $ sops decrypt .env.sops.env DATABASE_URL=postgresql://demo_user:demo_password@localhost:5432/demo_db API_TOKEN=dummy-api-token JWT_SECRET=dummy-jwt-secret
VSCode で暗号化された .env を編集する
暗号化済みファイルを編集する場合は、sops edit を使います。
VSCode で編集する場合は、次のようにします。
SOPS_EDITOR='code --wait' sops edit .env.sops.env
実行すると /var/folders/s7/86599dyd1g5clgw4f7l3d2840000gn/T/3982786129/.env.sops.env のような一時ファイルが VSCode で開かれます。
適宜編集して保存した後、ファイルを閉じると .env.sops.env が再暗号化されます。
これも mise task にしておくと便利です。
[tasks."env:edit"] description = "Edit encrypted env file with VSCode" run = "SOPS_EDITOR='code --wait' sops edit .env.sops.env"
実行します。
mise run env:edit
EMBEDDING_API_TOKEN などの値を適宜書き換えて保存し、VSCode を閉じます。
.env.sops.env が再び暗号化された状態で保存されれば成功です。
DATABASE_URL=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str] API_TOKEN=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str] EMBEDDING_API_TOKEN=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str] JWT_SECRET=ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]
最終的な mise.toml 例
最小構成の mise.toml は次のようになります。
[tools] sops = "3.12.2" azure-cli = "2.84.0" [tasks."env:render"] description = "Generate .env from encrypted env file" run = ''' set -euo pipefail sops decrypt .env.sops.env > .env chmod 600 .env echo "generated: .env" ''' [tasks."env:decrypt"] description = "Print decrypted env to stdout" run = "sops decrypt .env.sops.env" [tasks."env:edit"] description = "Edit encrypted env file with VSCode" run = "SOPS_EDITOR='code --wait' sops edit .env.sops.env"
このファイルをプロジェクトに置いておけば、開発者が覚えるコマンドは少なくなります。
mise install mise run env:render
新規メンバーが入ったときの手順
新規メンバーが入ったときは、次の手順でセットアップできます。
git clone <repository-url> cd <repository-name> mise install az login mise run env:render
もちろん、「キー コンテナー暗号化ユーザー」などの Key Vault 権限は事前に必要です。
発展:shared / secret / local に分ける
実際のチーム運用では、すべての値を1つの .env.sops.env に入れるより、値の性質ごとに分けたほうが扱いやすい場合があります。
例えば、次のように分けます。
.env.shared # チームで共有してよい非秘密情報 .env.secret.sops.env # SOPSで暗号化した秘密情報 .env.local # 個人用の上書き設定 .env # 最終的に生成されるファイル
この場合の考え方は次の通りです。
| ファイル | Git管理 | 用途 |
|---|---|---|
.env.shared |
する | チームで共有してよい非秘密情報 |
.env.secret.sops.env |
する | SOPSで暗号化した秘密情報 |
.env.local |
しない | 個人のローカル上書き設定 |
.env |
しない | アプリケーションが読む生成物 |
この構成にすると、非機密情報の差分が読みやすくなります。
一方で、ファイルが増えるため、最小構成よりは運用ルールが必要になります。
例えば、mise task は次のようになります。
[tasks."env:render"] description = "Generate .env from shared, encrypted secret, and local env files" run = ''' set -euo pipefail tmp_secret="$(mktemp)" cleanup() { rm -f "$tmp_secret" } trap cleanup EXIT sops decrypt .env.secret.sops.env > "$tmp_secret" { cat .env.shared printf "\n" cat "$tmp_secret" if [ -f .env.local ]; then printf "\n" cat .env.local fi } > .env chmod 600 .env echo "generated: .env" '''
まとめ
SOPS を使うと、.env 形式のファイルを暗号化して Git 管理できます。
Azure Key Vault を組み合わせることで、復号できる人を Azure 側の権限で制御できます。
さらに mise を使うことで、SOPS と Azure CLI の導入、そして .env の生成コマンドをチームでそろえられます。
最小構成は次の通りです。
.env.sops.env # 暗号化された.env。Git管理する .env # 復号して生成する.env。Git管理しない .sops.yaml # SOPS設定 mise.toml # ツールとタスク定義
開発者が実行するコマンドは、最終的にはこれだけにできます。
az login mise install mise run env:render
環境変数の管理はチーム開発において重要な課題です。
いざ開発に入ると、.env の値をチャットで共有してしまったり、誰が最新の値を持っているのかわからなくなったりします。
今回の構成を使うことで、Git 管理と Azure Key Vault の権限管理を組み合わせながら、チームで同じ手順で .env を生成できるようになります。
参考資料
- SOPS のドキュメント
https://getsops.io/docs/ - SOPS の GitHub リポジトリ
https://github.com/getsops/sops - SOPS Azure KMS
https://getsops.io/docs/usage/identities/azure-kms/ - dotenvx Encryption
https://dotenvx.com/docs/quickstart/encryption/ - SOPS Config File
https://getsops.io/docs/usage/identities/config-file/ - mise のインストール方法
https://mise.jdx.dev/installing-mise.html
執筆:@aoki.naoto
レビュー:@yamada.y
(Shodoで執筆されました)



