一覧へ戻る

1Password SSHエージェントを使用してSSH Keyをセキュアに保存

2025-11-24 公開 2025-12-09 更新 GitHub
目次

SSH の秘密鍵を Mac と Windows(WSL)の両方で共通化し、1Password に集約して安全に管理できるようにする。 現状は、各 OS のユーザーディレクトリにある ~/.ssh に個別で秘密鍵を置き、ssh config から参照するごく一般的な構成になっている。

ただ、ホストにそのような情報を残しておくと、何らかのセキュリティ脅威によって端末情報が見られることがあった場合に、秘密鍵を盗まれるリスクがある。(所持している端末が多く、かつそれぞれで鍵を所持していたらなおさらリスクは上がる)

そこで、秘密鍵をすべて 1Password 側で生成・保存し、必要なときだけ 1Password の SSH Agent 経由で利用することにする。

1Password SSHエージェントを使用してSSHキーを保存

ドキュメントにもあるように、まずは各OSでデスクトップ版の1Passwordをダウンロードし、サインインしておく。

秘密鍵と公開鍵の作成・登録

今回はMac、Windowsの両方で既存で使用していたSSH Keyを削除して新しいキーを使用することにしたので、以下手順で秘密鍵と公開鍵の作成・登録を行う。

  1. 1Passwordを開いて「新規アイテム」を押下後、SSHキーの追加を行う。

  1. 表示内容に従い推奨される鍵方式(Ed25519)で秘密鍵を作成する。

  1. 公開鍵を設置したいサービスに遷移し、公開鍵を登録

Githubなら公開鍵登録時に1PasswordのChrome拡張機能がサジェストを出してくれる

1Password SSHエージェントの有効化と設定ファイル

ここまででSSHキーの作成と公開鍵の登録が完了したので、次にSSH設定ファイルにSSHキーファイルの参照を行う。

Mac/Windows(WSL)

  • Windowsのみ:Windowsでシステムの「サービス」を起動し、OpenSSH Authentication Agent を無効化する

  • 1Password デスクトップアプリを開き、プロフィールのプルダウンから「設定」を押下し「開発者」セクションでSSHエージェントを有効化する

これにより C:\Users\<ユーザー名>\.ssh\1Password\config (Macの場合、~/<ユーザー名>/.ssh/1Password/config)が自動生成され、Windowsの ssh.exe はこの設定を経由して鍵を提示できる状態になる

ただし、.ssh\1Password\configはWindows側に生成されているため、WSLから参照する必要がある。 そのための手順が2パターンあるため2パターン記述していくが、基本的にパターン2が推奨される方法(devcontainerと相性がいい)。

WSLの場合

パターン1:Windowsのssh.exeをWSLから使う

以下公式手順がパターンの1つ目となる。

Use the 1Password SSH agent with WSL | 1Password Developer

WSLからWindowsのssh.exeを実行する必要がある。 そのため、以下のエイリアスをWSL側のシェルの設定ファイルに記述しておく。

.zshrc
```bash
alias ssh=ssh.exe
alias ssh-add=ssh-add.exe

これで、WSL側でSSHコマンドを実行すればWindows側のSSHを利用することができる。

ただし今のままでは以下の状況になる。

  • ssh -T git@github.com は成功
Hi k-ito-cat! You've successfully authenticated, but GitHub does not provide shell access.

(Windows側の ssh.exe が1Password Agent経由で認証成功)

  • しかし、git pullgit push は失敗
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

(Git が WSLの /usr/bin/ssh を使っており、鍵が見つからず拒否)

ssh エイリアスはシェル操作時のみ有効でGit コマンド内部では エイリアスを無視して /usr/bin/ssh を直接呼び出すため、Windows経由では通るがWSL経由では鍵不一致で拒否された。

.gitconfigに以下を記述し、git操作でもWindowsのSSHを呼び出す必要がある。

.gitconfig
[core]
sshCommand = "/mnt/c/Windows/System32/OpenSSH/ssh.exe"

次に、SSH configを書き直す

~/.ssh/config を記述

chezmoi で管理するため、 chezmoi add ~/.ssh/config を実行

OSごとに IdentityAgent を切り替えるテンプレートにする。(chezmoi管理しているため)

~/.local/share/chezmoi/ssh/config
{{ if eq .chezmoi.os "darwin" }}
Host github.com
 HostName github.com
 User git
 IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
 ForwardAgent yes
{{ else if eq .chezmoi.os "linux" }}
Host github.com
 HostName github.com
 User git
 IdentitiesOnly yes
 IdentityAgent ~/.ssh/1Password/config
{{ end }}

ここまでを行い、両環境で以下の実行すると1Passwordのパスワードが求められるので入力して承認を行い、完了。

ssh -T git@github.com

パターン2:Windowsの1Password AgentをWSLのLinux sshから利用する

Linux SSH(WSL の /usr/bin/ssh)を直接使えるようにする(=Windows側のsshを直接参照しにいかない)。 devcontainerなどのコンテナ内ではWindowsのmntは存在せず、Windowsのssh.exeを参照できないのでLinux SSHで1Password agentを使用できる必要があり、今はこの構成にしている。

まずは、パターン1での記述などは削除しておく。

  1. .zshrc のエイリアス無効化
.zshrc
alias ssh="ssh.exe"
alias ssh-add="ssh-add.exe"

→ ssh.exeは参照しないので一式削除

  1. .gitconfig の SSH 強制を削除
.gitconfig
[core] sshCommand = "/mnt/c/Windows/System32/OpenSSH/ssh.exe"

→ 同様の理由で削除

  1. ~/.ssh/config(WSL側)の削除 以降の手順でSSH_AUTH_SOCKを優先的に参照させたいため、IdentitiesOnly・IdentitiesAgentなどは邪魔になるので削除。
ssh/.config
Host github.com
HostName github.com
User git
IdentitiesOnly yes
IdentityAgent ~/.ssh/1Password/config

次にWSL の Linux ssh が Windows の 1Password SSH Agent を使えるようにするためのソケット変換ツールをインストール

Terminal window
sudo apt install socat

以下の公式配布元からnpiperelay.exeを取得し、C:\Users\<ユーザー名>\bin など PATH の通る場所へ配置する。 https://github.com/jstarks/npiperelay/releases

※ WSLからnpiperelay.exeが実行できればどこでもよい

ブリッジ用スクリプトを作成 WSL 内で~/.local/bin/1pass-ssh-bridgeを作成。

cat > ~/.local/bin/1pass-ssh-bridge << 'EOF'
#!/usr/bin/env bash
set -e
SOCK="$HOME/.ssh/agent.sock"
mkdir -p "$HOME/.ssh"
rm -f "$SOCK"
socat UNIX-LISTEN:$SOCK,fork EXEC:"npiperelay.exe -ei -s //./pipe/openssh-ssh-agent",nofork
EOF
chmod +x ~/.local/bin/1pass-ssh-bridge

→ Windows側の1Password SSH Agent( .\pipe\openssh-ssh-agent )とWSLのLinux ssh を接続するブリッジ

.zshrc に自動起動処理を追加

.zshrc
if grep -qi microsoft /proc/version 2>/dev/null && command -v npiperelay.exe >/dev/null 2>&1; then
export SSH_AUTH_SOCK="$HOME/.ssh/agent.sock"
wsl_restart_ssh_bridge() {
rm -f "$SSH_AUTH_SOCK"
~/.local/bin/1pass-ssh-bridge >/dev/null 2>&1 &
sleep 0.5
}
# ソケットに接続できないまたはエージェントがいない場合はブリッジやり直し
if ! ssh-add -l >/dev/null 2>&1; then
wsl_restart_ssh_bridge
fi
fi

ソケットがなければブリッジを起動し、以降自動で 1Password を参照できるようにする。

新しいタブで動作確認

ssh-add -l
ssh -T git@github.com

上記いずれかのパターンの手順を行い、接続が完了したらこれまでの不要なSSHの秘密鍵を.sshから削除し、公開鍵も削除を行う。

流れを整理すると、

  1. 1Password Agent有効化してSSH Agent(Named Pipe)がWindowsに提供される
  2. npiperelay + socat により、そのWindowsのNamed PipeをWSL用UNIXソケットに変換する
  3. WSL内でSSH_AUTH_SOCKがそのUNIXソケットを指すことで、sshがAgentを使えるようになる

NOTE

Named Pipe → ここではWindowsのSSH Agentとの対話手段と解釈

UNIXソケット → ここではLinuxのSSH Agentとの対話手段と解釈

Macの場合

1Password Agentを有効化すると

~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock

にソケットが格納される。

わかりやすい場所に格納しておきたいので、~/.ssh/agent.sock へエイリアスを作っておく。

ln -sf "$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock" ~/.ssh/agent.sock

Windowsと同様に、SSH_AUTH_SOCKにソケットを毎回格納するようにする。

このマシンでは常に1Passwordのエージェントを使用するという宣言のようなもの。

~/.zshrc
export SSH_AUTH_SOCK="$HOME/.ssh/agent.sock"
source ~/.zshrc

※ターミナル再起動

こうすることでmacOSのssh、gitは1Password SSH Agent を使ってくれる。

SSH_AUTH_SOCKが正しく設定されていれば、鍵ファイルを明示する必要がなく、~/.ssh/configは不要になるのでWindows同様に削除。

Devcontainerで1Passwordの秘密鍵を使用するための準備

基本的にVSCodeの拡張機能はホストのSSH Agentをcontainer側に転送するようになっている。 WSLの場合はVSCodeで以下の設定がONになっていることを確認する(デフォルトでONのはず)。

Dev › Containers: Forward WSL Services

NOTE

Cursorにはこの設定がなく、おそらくWSLがサポートされていないため、明示的にマウントする必要がある。

devcontainer.json
"mounts": [
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind",
"source=${localEnv:HOME}/.ssh/agent.sock,target=/ssh-agent,type=bind"
],
"remoteEnv": {
"SSH_AUTH_SOCK": "/ssh-agent"
}

ssh agentの転送とは、ssh agentへ疎通するためのソケットファイルのパスを格納するSSH_AUTH_SOCK環境変数がdevcontainer側でも有効になることを意味する。

つまり、この環境変数にソケットファイルのパスが設定されていれば、 sshコマンド実行時にそのソケットを通してagentと疎通し、秘密鍵を見つけてくれて認証が行われる。

そのため、やることとしてはmacOS、WSL両方で、 ホスト側のSSH_AUTH_SOCKに1Password Agentのソケットパスを設定しておくことになる。

OpenSSHのagentの場合はSSH_AUTH_SOCK環境変数に自動でソケットパスが設定されるが(記憶が正しければそう)、 1Password Agentの場合はこれを手動で設定する必要がある。 また、セッションが切れると値が空になるため、zsh起動時に毎回設定されるよう.zshrcに記述しておく(参照:WSLの場合Macの場合)。

こうすることで、常にSSH_AUTH_SOCKに1Password Agentのソケットパスが設定された状態となり、 devcontainer起動時にそれが転送され、container内でもホストと同様にSSH接続が可能になる。

整理すると、以下は厳守する必要がある。

  • SSH_AUTH_SOCKに常に1Password Agentのソケットパスが設定されていること
  • WSLの場合、この転送はVSCode経由でのみ行われる点に注意する

SSHキーの保管庫の移動をする時

1PasswordのSSHエージェント有効化後、~/.config/1Password/ssh/agent.tomlにエージェント構成ファイルが作成されている(デスクトップアプリの1Passwordから登録したSSHキーを開き、三点リーダを押下して開くことも可能)。

以下の設定がデフォルトであるため、保管庫の移動を行った際はここも書き換えておく必要がある。

~/.config/1Password/ssh/agent.toml
[[ssh-keys]]
vault = "XXX"
この記事を共有