Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新

Jan 27, 2026 - 日記

direnvとdotenvx-rsの組み合わせ: 自動ロードと暗号化を両立させる設定パターン

direnvとdotenvx-rsの組み合わせ cover image

先日、プロジェクトの.envファイルをGitにコミットしたくてdotenvx-rs で暗号化を試したんですが、毎回dotenvx runを打つのが面倒で挫折しかけました。「direnv と組み合わせれば自動化できるのでは?」と思って試したところ、かなり快適な構成ができたので共有します。

direnvとdotenvx-rsの役割分担

まず、それぞれのツールが得意とする領域を整理しておきます。

ツール得意な領域苦手な領域
direnvディレクトリ移動時の環境変数自動ロード暗号化、バリデーション
dotenvx-rs.envの暗号化・復号化、署名検証自動ロード(手動実行が必要)

direnvは.envrcファイルを使ってシェル環境を自動的に切り替えますが、暗号化された.envファイルには対応していません。一方、dotenvx-rsは暗号化・復号化に特化していますが、ディレクトリ移動時の自動ロードは提供していません。

この2つを組み合わせることで、「ディレクトリに入ったら自動的に暗号化された.envを復号化して環境変数にロード」という理想的なワークフローが実現できます。

dotenvx-rsとは?

dotenvx-rsは、オリジナルのdotenvx をRustで再実装したCLIツールです。主な特徴は以下の通りです:

  • 軽量: バイナリサイズが約4MB(Node.js版は約50MB)
  • グローバルキーストア: $HOME/.dotenvx/.env.keys.jsonに秘密鍵を保存し、AIエージェントによるスキャンを防止
  • 署名機能: .envファイルの改ざん検知(secp256k1署名)
  • direnv/mise統合: .envrc経由での自動ロードに対応

既存のdotenvx紹介記事「dotenvx: 環境変数管理を快適にするツール 」では、オリジナルのNode.js版を扱いました。本記事では、Rust版の特徴である「direnv統合」に焦点を当てます。

基本的な設定パターン

1. dotenvx-rsのインストール

1
2
3
4
5
6
7
8
# Homebrewの場合
brew install linux-china/tap/dotenvx-rs

# cargo-binstallの場合
cargo binstall dotenvx-rs

# または、GitHubリリースから直接ダウンロード
# https://github.com/linux-china/dotenvx-rs/releases

2. .envファイルの暗号化

プロジェクトディレクトリで以下を実行します:

1
2
# 初期化(鍵ペアの生成と.envファイルの作成)
dotenvx init

dotenvx initを実行すると、以下が生成されます:

  • .envファイル(公開鍵DOTENV_PUBLIC_KEYを含む)
  • $HOME/.dotenvx/.env.keys.jsonに秘密鍵を保存

次に、環境変数を暗号化して追加します:

1
2
3
# 環境変数を暗号化して.envに追加
dotenvx set --encrypt DATABASE_URL "postgresql://user:pass@localhost/db"
dotenvx set --encrypt API_KEY "secret-api-key"

注意: --encryptオプションを明示的に指定することで、値が暗号化されます。暗号化された値はencrypted:プレフィックスで保存されます。READMEには「dotenvx setで自動的に暗号化される」と書いてありますが、実際に試したところ--encryptを付けないと平文で保存されました。明示的にオプションを指定することをお勧めします。

.envファイルの中身を確認すると、以下のようになっています:

1
2
3
4
# .env(暗号化後)
DOTENV_PUBLIC_KEY="02b4972559803fa3c2464e93858f80c3a4c86f046f725329f8975e007b393dc4f0"
DATABASE_URL=encrypted:BNexEwjKwt87k9aEgaSng1JY6uW8OkwMYEFTwEy/xyz...
API_KEY=encrypted:BGcRf5bK/mChGEqT1MZ8hUbMm3hhtuW9NVGkHtl7KRwq...

3. .envrcの設定

プロジェクトルートに.envrcファイルを作成します:

1
2
# .envrc
eval $( dotenvx decrypt --stdout --format shell )

この1行で、direnvがディレクトリに入った際に自動的にdotenvx-rsを呼び出し、暗号化された.envを復号化して環境変数としてロードします。

4. direnvの許可

初回のみ、direnvに.envrcの実行を許可します:

1
direnv allow

これで設定完了です。ディレクトリに入ると自動的に環境変数がロードされます。

動作確認

実際に環境変数がロードされているか確認してみます:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# プロジェクトディレクトリに移動
cd /path/to/project

# direnvが自動的に.envrcを実行
# direnv: loading .envrc
# direnv: export +DATABASE_URL +API_KEY

# 環境変数の確認
echo $DATABASE_URL
# postgresql://user:pass@localhost/db

echo $API_KEY
# secret-api-key

ディレクトリを出ると、環境変数は自動的にアンロードされます:

1
2
3
4
5
cd ..
# direnv: unloading

echo $DATABASE_URL
# (空)

複数環境の切り替え

dotenvx-rsは、プロファイル機能を使って複数の環境(dev、prod、testなど)を管理できます。

プロファイル別の.envファイル作成

1
2
3
4
5
6
7
# 開発環境用の.envファイルを初期化
dotenvx init -f .env.dev
dotenvx set --encrypt -f .env.dev DATABASE_URL "postgresql://localhost/dev_db"

# 本番環境用の.envファイルを初期化
dotenvx init -f .env.prod
dotenvx set --encrypt -f .env.prod DATABASE_URL "postgresql://prod-server/prod_db"

.envrcでプロファイルを切り替え

1
2
3
4
# .envrc
# 環境変数でプロファイルを指定
export DOTENVX_PROFILE="dev"
eval $( dotenvx decrypt --stdout --format shell -f .env.${DOTENVX_PROFILE} )

または、プロジェクトごとに固定のプロファイルを使う場合:

1
2
# .envrc(本番環境用)
eval $( dotenvx decrypt --stdout --format shell -f .env.prod )

セキュリティ上の利点

この構成には、以下のセキュリティ上の利点があります:

1. AIエージェントからの秘密鍵保護

dotenvx-rsは秘密鍵を$HOME/.dotenvx/.env.keys.jsonに保存します。これにより、Cursor やGitHub CopilotなどのAIコード補完ツールがプロジェクトディレクトリをスキャンしても、秘密鍵が読み取られるリスクを軽減できます。

従来のdotenvxでは、秘密鍵を.env.keysファイルとしてプロジェクト内に保存していました。AIエージェントがプロジェクト全体を読み取る場合、この秘密鍵も含まれてしまう可能性があります。

2. .envファイルの署名検証

dotenvx-rsは、.envファイルに署名を付けることができます:

1
dotenvx encrypt --sign

これにより、.envファイルが改ざんされていないかを検証できます。署名はsecp256k1楕円曲線暗号を使用しており、ファイルの完全性を保証します。

3. 暗号化された.envをGitにコミット可能

暗号化された.envファイルは、安全にGitリポジトリにコミットできます。秘密鍵が別の場所($HOME/.dotenvx/.env.keys.json)に保存されているため、リポジトリが漏洩しても秘密情報は保護されます。

1
2
3
4
5
6
# .gitignore
.env.keys  # 古いdotenvxの秘密鍵ファイル(念のため除外)

# .envは暗号化されているのでコミット可能
git add .env .envrc
git commit -m "Add encrypted environment variables"

トレードオフと注意点

この構成には、いくつかのトレードオフがあります。

1. 初回セットアップの手間

チームメンバーが新しくプロジェクトをクローンした場合、以下の手順が必要です:

  1. dotenvx-rsのインストール
  2. 秘密鍵の共有(DOTENV_PRIVATE_KEY環境変数、または$HOME/.dotenvx/.env.keys.jsonへの追加)
  3. direnv allowの実行

秘密鍵の共有方法は、チームの運用ポリシーに応じて決める必要があります。例えば:

  • 1Password/Bitwarden: チーム共有のボルトに秘密鍵を保存
  • CI/CD環境変数: GitHub SecretsなどにDOTENV_PRIVATE_KEYを設定
  • 手動共有: Slackなどで暗号化されたメッセージとして共有

2. direnvのパフォーマンス

dotenvx-rsは高速ですが、ディレクトリ移動のたびに復号化処理が走るため、わずかな遅延が発生します。実測では数十ミリ秒程度ですが、頻繁にディレクトリを移動する場合は体感できる可能性があります。

3. 環境変数の上書き

direnvは既存の環境変数を上書きします。システム全体で設定している環境変数と名前が衝突する場合、意図しない動作を引き起こす可能性があります。

1
2
3
4
5
6
# システム全体でPATHを設定している場合
export PATH="/usr/local/bin:$PATH"

# .envrcでPATHを上書きすると、システムのPATHが失われる
# 対策: .envrcでPATHを追加する形にする
export PATH="./bin:$PATH"

miseとの組み合わせ

mise (ミーズ)は、direnvの代替として使えるツールバージョン管理・環境変数管理ツールです。miseでもdotenvx-rsを統合できます。

mise.tomlの設定

1
2
3
# mise.toml
[env]
_.source = "scripts/env.sh"

scripts/env.shの作成

1
2
3
#!/bin/bash
# scripts/env.sh
eval $( dotenvx decrypt --stdout --format shell )

miseを使う場合、direnvと同様にディレクトリ移動時に自動的に環境変数がロードされます。miseはツールバージョン管理も統合されているため、Node.jsやPythonのバージョン切り替えと環境変数管理を一元化できます。

まとめ

direnvとdotenvx-rsを組み合わせることで、以下のメリットが得られます:

  • 利便性: ディレクトリ移動時の環境変数自動ロード
  • セキュリティ: .envファイルの暗号化と署名検証
  • AIエージェント対策: 秘密鍵をプロジェクト外に保存

一方で、初回セットアップの手間や、秘密鍵の共有方法の検討が必要です。チーム開発では、運用ポリシーを明確にしておくことをお勧めします。

個人的には、ローカル開発環境での利便性とセキュリティのバランスが取れた構成だと感じました。特に、CursorなどのAIコード補完ツールを使っている場合、秘密鍵がプロジェクト外に保存される点は安心材料になります。

最初は「暗号化と自動ロードの両立は面倒そう」と思っていましたが、.envrcに1行追加するだけで実現できたのは嬉しい誤算でした。興味のある方は、ぜひ試してみてください。

参考リンク