.envファイルに平文でAPIキーを書いている。開発者なら一度はやったことがあるはずだ。
# .env(よくある状態)
OPENAI_API_KEY=sk-proj-abc123def456
DATABASE_URL=postgres://admin:P@ssw0rd@db.example.com:5432/myapp
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxx
.gitignoreに入れているから大丈夫? 新しいメンバーに.envをSlackで送っていないか。退職者のローカルマシンにAPIキーが残っていないか。CIのシークレット設定と.envの値がズレていないか。
opx(1Password CLIのラッパー)を使うと、.envからシークレットの平文を完全に排除できる。ファイルに書くのは1Passwordへの参照URLだけ。実際の値はopx経由で実行時に注入される。
仕組み
opxは1Password CLI(opコマンド)のラッパーで、.envファイル内のop://参照を検出し、1Passwordから実際の値を取得して環境変数に注入した上でコマンドを実行する。
.env の op:// 参照 → opx が検出 → 1Password から値を取得 → 環境変数に注入 → コマンド実行
つまり、.envファイルを見ても秘密情報は一切わからない。1Passwordへのアクセス権限がある人だけが、実行時に値を取得できる。
セットアップ手順
1. 1Password CLIのインストール
# macOS(Homebrew)
brew install 1password-cli
# 確認
op --version
2. 1Password CLIにサインイン
# 初回サインイン
op signin
# アカウントを確認
op account list
1Password 8のデスクトップアプリがインストールされていれば、生体認証(Touch ID等)でサインインできる。毎回マスターパスワードを入力する必要はない。
3. opxのインストール
opxは1Password CLIに組み込まれているop runコマンドのエイリアス、またはnpmパッケージとして利用できる。
# npmでインストールする場合
npm install -g opx
# または、op run を直接使う(opxと同等)
op run -- npm run dev
プロジェクトによってはopxをdevDependenciesに入れてnpx opxで使うパターンもある。
4. 1Passwordにシークレットを登録
1Passwordのvault内に「Secure Note」または専用のアイテムを作成し、各シークレットをフィールドとして登録する。
Vault: Development
Item: MyApp Secrets
Fields:
- OPENAI_API_KEY: sk-proj-abc123def456
- DATABASE_URL: postgres://admin:P@ssw0rd@db.example.com:5432/myapp
- STRIPE_SECRET_KEY: sk_live_xxxxxxxxxxxxxxxx
各フィールドの参照URLは、1Passwordアプリでアイテムを開き、フィールドの「参照をコピー」で取得できる。
.envファイルの書き換え: Before → After
Before(平文)
# .env
OPENAI_API_KEY=sk-proj-abc123def456
DATABASE_URL=postgres://admin:P@ssw0rd@db.example.com:5432/myapp
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxx
AWS_ACCESS_KEY_ID=AKIA1234567890ABCDEF
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxx
After(op://参照)
# .env
OPENAI_API_KEY=op://Development/MyApp Secrets/OPENAI_API_KEY
DATABASE_URL=op://Development/MyApp Secrets/DATABASE_URL
STRIPE_SECRET_KEY=op://Development/MyApp Secrets/STRIPE_SECRET_KEY
AWS_ACCESS_KEY_ID=op://Development/MyApp Secrets/AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY=op://Development/MyApp Secrets/AWS_SECRET_ACCESS_KEY
SENDGRID_API_KEY=op://Development/MyApp Secrets/SENDGRID_API_KEY
op://の形式は op://<vault名>/<アイテム名>/<フィールド名>。
この.envファイルはGitにコミットしても安全だ。参照URLだけなので、1Passwordへのアクセス権がなければ値を取得できない。
使い方
開発サーバーの起動
# Before: 平文.envを読み込む
npm run dev
# After: opx経由で起動
opx npm run dev
# または op run を使う場合
op run --env-file=.env -- npm run dev
opxが.envのop://参照を解決し、環境変数として注入した状態でコマンドを実行する。アプリケーション側のコード変更は不要。process.env.OPENAI_API_KEYでそのまま取得できる。
特定のコマンドだけ実行
# マイグレーション実行
opx npx prisma migrate deploy
# テスト実行(DB接続が必要な場合)
opx npm test
# シークレットが不要なコマンドにはopx不要
npm install # opx不要
npm run lint # opx不要
git push # opx不要
値の確認(デバッグ用)
# 特定のシークレットの値を確認
op read "op://Development/MyApp Secrets/OPENAI_API_KEY"
# .envの全参照を解決して表示
op run --env-file=.env -- env | grep -E "OPENAI|DATABASE|STRIPE"
チーム導入の手順
Step 1: Vaultの設計
Production Vault(本番用)
├── API Keys(外部サービス)
├── Database Credentials(DB接続情報)
└── SSL Certificates(証明書)
Development Vault(開発用)
├── API Keys(テスト用キー)
└── Database Credentials(ローカルDB)
Staging Vault(ステージング用)
└── (本番とは異なるキーを使用)
Vaultを環境ごとに分けると、開発者に本番のシークレットへのアクセス権を与えずに済む。
Step 2: アクセス権限の設定
1Passwordのチーム機能で、Vaultへのアクセスを役割ベースで管理する。
| 役割 | Development Vault | Staging Vault | Production Vault |
|---|---|---|---|
| 開発者 | 読み取り | 読み取り | アクセス不可 |
| リードエンジニア | 読み取り/書き込み | 読み取り/書き込み | 読み取り |
| CTO/インフラ | フル | フル | フル |
Step 3: オンボーディング手順の整備
新しいメンバーが参加したときの手順:
- 1Passwordのチームに招待
- Development Vaultへのアクセス権を付与
- 1Password CLIをインストール(
brew install 1password-cli) op signinでサインイン- プロジェクトをクローンして
opx npm run dev
.envファイルをSlackで送る必要がない。1Passwordのアクセス権を付与するだけで、環境構築が完了する。
Step 4: 退職者のアクセス削除
1Passwordのチームから削除するだけで、全プロジェクトのシークレットへのアクセスが一括で無効化される。個別のAPIキーをローテーションする必要はない(ただし、万全を期すなら主要なキーのローテーションは推奨)。
CI/CDとの統合
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Load secrets from 1Password
uses: 1password/load-secrets-action@v2
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
OPENAI_API_KEY: op://Production/MyApp Secrets/OPENAI_API_KEY
DATABASE_URL: op://Production/MyApp Secrets/DATABASE_URL
- name: Deploy
run: npm run deploy
GitHub Actionsの場合、1Passwordのサービスアカウントトークンを1つだけGitHub Secretsに登録する。個別のシークレットをGitHub Secretsに登録する手間がなくなる。
他のCIサービス
CircleCI、GitLab CI、Vercelでも同様の統合が可能。1Password公式のインテグレーションが提供されている。
コスト
1Passwordの料金(2026年3月時点):
| プラン | 月額/人 | 主な機能 |
|---|---|---|
| Teams | $3.99 | 5人〜、Vault共有、管理コンソール |
| Business | $7.99 | SSO統合、カスタムロール、監査ログ |
| Enterprise | 要問合せ | 専任サポート、SLA |
開発チーム5人の場合、Teamsプランで月$20程度。1つのAPIキーの漏洩リスクを考えれば、十分にペイする投資だ。
補足: 経営層への説明
技術的なメリットは明確だが、経営層への説明にはビジネスリスクの観点が必要になる。
- APIキー漏洩のコスト: OpenAI APIキーが漏洩すれば、数時間で数十万円の不正利用が発生しうる
- コンプライアンス: ISO 27001やSOC 2の要件として、シークレットの管理は必須項目
- 退職時のリスク: 平文の.envファイルが退職者のPCに残る問題を構造的に解決
「1Passwordの月額費用」と「漏洩時の損害額」を比較すれば、投資判断としては明快だ。
まとめ
opx(1Password CLI)で.envの平文シークレットを排除する手順:
- 1Password CLIをインストール(5分)
- シークレットを1Passwordに登録(15分)
.envをop://参照に書き換え(10分)opx経由でコマンドを実行する運用に切り替え
全体で30分程度の作業で、シークレット管理のリスクが大幅に下がる。新しいプロジェクトを始めるとき、最初に.envをop://形式で書く習慣をつけるのが一番楽だ。

