SSH の鍵を ssh-add しても毎回パスフレーズを聞かれる
ssh-agent はシェルのプロセスに紐づくため、端末を開き直すと登録済みの鍵が失われる。AddKeysToAgent yes を ~/.ssh/config に書くか、OS のエージェント常駐サービスへ接続するのが確実である。
公開: 更新:
要約
ssh-add で鍵を登録したのに、端末を開き直すとまたパスフレーズを聞かれる。
原因は ssh-agent が「常駐サービス」ではなく「起動したプロセス」でしかないことである。
エージェントのプロセスが消えれば、そこに預けた鍵も一緒に消える。
ssh-add -lCould not open a connection to your authentication agent.このメッセージは「登録した鍵が消えた」のではなく「そもそも接続先のエージェントが居ない」状態を指す。ssh-agent(1)(新しいタブで開く) が書いているとおり、ssh は環境変数 SSH_AUTH_SOCK が指すソケット経由でエージェントを探すので、この変数が引き継がれない端末では毎回ゼロからやり直しになる。
恒久的に直すなら、鍵を登録し直す運用をやめて、AddKeysToAgent で自動登録させるか、OS が管理する常駐エージェントに接続する。
実行例
alpine:3 のコンテナで SSH_AUTH_SOCK を外したまま ssh-add -l を打つと Could not open a connection to your authentication agent.(終了コード 2)が返り、1 つ目の ssh-agent に登録した鍵は 2 つ目のエージェントからは見えず、-t 5 を付けて登録した鍵も sleep 7 の後には The agent has no identities. になった。AddKeysToAgent yes を書いた ~/.ssh/config は、ssh -G の実効値で addkeystoagent true になっている。
$ ssh-add -l
Could not open a connection to your authentication agent.
$ echo $?
2$ eval "$(ssh-agent -s)"
Agent pid 20$ ssh-add /root/.ssh/id_ed25519
Identity added: /root/.ssh/id_ed25519 (root@cda6a526f534)$ ssh-add -l
256 SHA256:OmnNFmP+M7ihvYNLjkNpbJHgFvk4NOgXiMxavBWDRi8 root@cda6a526f534 (ED25519)$ eval "$(ssh-agent -s)"
Agent pid 25$ ssh-add -l
The agent has no identities.
$ echo $?
1$ ps -o pid,args | grep -c "[s]sh-agent"
2$ ssh-add -t 5 /root/.ssh/id_ed25519
Identity added: /root/.ssh/id_ed25519 (root@cda6a526f534)
Lifetime set to 00:00:05$ ssh-add -l
256 SHA256:OmnNFmP+M7ihvYNLjkNpbJHgFvk4NOgXiMxavBWDRi8 root@cda6a526f534 (ED25519)$ sleep 7$ ssh-add -l
The agent has no identities.
$ echo $?
1$ cat /root/.ssh/config
Host *
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519$ ssh -G example.com | grep -E '^(addkeystoagent|identityfile) '
Pseudo-terminal will not be allocated because stdin is not a terminal.
identityfile ~/.ssh/id_ed25519
addkeystoagent true— 2026-09-28 時点の出力
検証環境
- 検証日
- 実行環境
alpine:3Alpine Linux v3.24
この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。
よくある原因
- 端末ごとに
ssh-agentを起動している:eval "$(ssh-agent -s)"を.bashrcや.zshrcに書くと、端末を開くたびに新しいエージェントが起動する。
前の端末でssh-addした鍵は別プロセスの中なので見えない。ps aux | grep ssh-agentが何行も並ぶなら、この状態である。 SSH_AUTH_SOCKが引き継がれていない: エージェントは生きているのに、tmuxのセッションやsudo後のシェル、デスクトップから起動した GUI アプリに変数が渡っていないことがある。
エージェントの有無ではなく、変数の有無を先に疑う。- 鍵が既定のファイル名ではない:
~/.ssh/id_ed25519などの既定名ならsshが自動で読むが、~/.ssh/work_keyのような名前はIdentityFileを書かないと拾われない。
エージェントに入っていない鍵はその都度ファイルから読まれ、そのたびにパスフレーズを求められる。 - 寿命付きで登録している:
ssh-add -t 3600のように登録すると、指定した秒数でエージェントから自動的に削除される。
「しばらくすると聞かれるようになる」場合はこれを疑う。 - 登録自体は成功しているが接続で別の鍵が使われている: エージェントに複数の鍵が入っていると、
sshは順に試す。
目的の鍵に到達する前にサーバー側の試行回数の上限(sshd のMaxAuthTries、既定 6)に達すると、パスフレーズを聞かれることもなくToo many authentication failuresで接続を切られる。
解決策
1. AddKeysToAgent で自動登録させる
もっとも手数が少ないのはこれである。~/.ssh/config に書いておくと、その鍵を初めて使うときに一度だけパスフレーズを聞き、以後はエージェントに載ったものが使われる。
Host *
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519ssh_config(5)(新しいタブで開く) の AddKeysToAgent は yes のほか confirm や ask、1h のような寿命指定も受け付ける。
共用マシンなら confirm にして、鍵を使うたびに確認を出す運用にできる。
2. OS の常駐エージェントに接続する
シェル起動ファイルで ssh-agent を起動するのをやめ、OS が管理しているエージェントを使う。
プロセスの寿命がログインセッションに揃うため、端末を開き直しても鍵が残る。
macOS は標準で launchd がエージェントを起動しており、SSH_AUTH_SOCK も自動で入る。
Linux では systemd の user unit を有効にする。
systemctl --user enable --now ssh-agent.serviceWindows は OpenSSH Authentication Agent サービスを自動起動にする。
Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent3. macOS は Keychain にパスフレーズを預ける
macOS 限定だが、UseKeychain yes を併用するとパスフレーズ自体を Keychain が保持する。
再起動後の初回接続でも聞かれなくなる。
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519登録済みのパスフレーズを Keychain に入れ直したい場合は ssh-add --apple-use-keychain ~/.ssh/id_ed25519 を一度実行する。
4. 切り分けは ssh-add -l から始める
原因が「エージェントが居ない」のか「鍵が入っていない」のかで対処が変わる。
まず状態を見る。
echo "$SSH_AUTH_SOCK"
ssh-add -lSSH_AUTH_SOCK が空ならエージェントに繋がっていない(原因 1 か 2)。
変数はあるのに The agent has no identities. が返るならエージェントは生きていて鍵だけが無い(原因 4 か、単に未登録)。
鍵が並んでいるのに聞かれるなら、使われている鍵が違う(原因 3)ので ssh -v で実際に提示された鍵を確認する。Too many authentication failures で切られるなら原因 5 である。