Permission denied (publickey) は、SSH で最も多く出会うエラーで、しかもメッセージはまったく親切ではありません。これは「鍵が間違っている」という意味ではありません。意味はこうです。サーバーは、あなたが提示したすべての認証方式を拒否し、公開鍵が、サーバーが応じる気のあった唯一の方式だった。 括弧の中は、サーバーがまだ開けている方式の一覧です。(publickey) は、パスワード認証がオフで鍵が通らなければならないのに、あなたの鍵がどれも通らなかった、という意味です。
この一覧はもっと長いこともあり、読む価値があります。Permission denied (publickey,password) は、サーバーがパスワードも受け付けるという意味です。ですから、パスワードを入力するつもりだったのに一度も尋ねられなかったなら、クライアントが鍵をあきらめた上でフォールバックすべきだったのにしなかったのです。-o PubkeyAuthentication=no でプロンプトを強制して試せます。Permission denied (publickey,keyboard-interactive) は同じ考え方で、対話的な方式(多くは PAM のプロンプトや 2 要素認証)がまだ候補に残っている状態です。括弧の中にあるものが、サーバーが開けておいた扉のすべてです。期待していた扉が載っていなければ、サーバーは最初からそれを受け入れるつもりがなかったのです。
これは広い網です。ユーザー名の誤りがこのエラーを生みます。クライアントが一度も提示しなかった鍵、サーバーが一度も受け取らなかった鍵、sshd が黙って見逃すことを拒むパーミッションの問題、そして聞いたこともない SELinux のラベルも、同じエラーを生みます。対処は当てずっぽうではなく、体系的です。まずはループ、それから、実際に答えであることの多い順に原因を挙げます。(GitHub や GitLab へのプッシュですか? それは別のチェックリストです:GitHub/GitLab の SSH 鍵が効かない。)
診断のループ:クライアントが何を試したかを読む
失敗する接続を、最大の詳細度で実行します(出力の壁がノイズに見えるなら、ssh -vvv の読み方(英語)が、重要な行を読み解きます):
ssh -vvv user@host
出力の中から 3 つを探します:
Authentications that can continue: publickey——サーバーの方式一覧です。passwordがなければ、パスワードは決して尋ねられません。鍵が成功しなければなりません。Offering public key: /home/you/.ssh/id_ed25519——クライアントが試したすべての鍵です。意図した鍵がこの一覧になければ、問題はクライアント側です(原因 2)。あるなら、次を見ます。- 何が返ってきたか。
Server accepts keyに続いて署名のやり取りがあれば、鍵は一致し、その後に何かが失敗したということです(まれ)。よく見るのは、提示の直後に次の鍵かPermission deniedが続く光景です。サーバーは鍵を見て肩をすくめた、ということで、これはサーバー側を指します(原因 3〜8)。
マシンに入る別の手段(プロバイダーの Web コンソール、別のユーザー、別の管理者)があるなら、サーバーのログが本当の理由をずばり名指しします:
sudo journalctl -u sshd -f # systemd distros
sudo tail -f /var/log/auth.log # Debian/Ubuntu
sudo tail -f /var/log/secure # RHEL/Alma/Rocky
Authentication refused: bad ownership or modes for directory /home/deploy のような行は、その場で調査を終わらせます。
原因 1:ユーザー名の誤り
最も多い原因で、特にクラウドイメージで多発します(初めての EC2 や VPS へのログイン(英語)で最初にぶつかる壁です)。ログインユーザーが、想像とは違うからです。Ubuntu イメージでは ubuntu、Amazon Linux では ec2-user、Debian の AMI では admin、素の VPS の多くでは root、Azure の既定では azureuser です。正しい鍵でもユーザー名が間違っていると、まさにこのエラーが出ます。サーバーは ~wronguser/.ssh/authorized_keys を調べ、何も見つからず、拒否します。
ほかに何かいじる前に、イメージのドキュメントが示すユーザーを確認し、二度と打ち直さずに済むよう ~/.ssh/config に固定します(ssh_config ガイド(英語)がこのパターンを扱っています):
Host web1
HostName 203.0.113.10
User ubuntu
原因 2:鍵が一度も提示されなかった
ssh -vvv が、あなたの鍵を Offering public key の行に出さないなら、クライアントはその鍵を知りません。明示的に指し示します:
ssh -i ~/.ssh/id_ed25519 user@host
それで通るなら、上の設定ブロックに IdentityFile を書いて恒久化します。関連する落とし穴が 2 つあります。多くの鍵を詰め込んだエージェントは、正しい鍵にたどり着く前にサーバーの試行回数の上限に引っかかることがあります(Too many authentication failures。IdentitiesOnly yes で直します)。そして、パスフレーズの入力をキャンセルした鍵は、黙ってスキップされます。エージェントが実際に何を保持しているか確認します:
ssh-add -l
Windows では、鍵を読み込んだばかりでもこの一覧が空に見えることがあります。Git Bash、OpenSSH サービス、WSL はそれぞれ別のエージェントを動かしており、ssh-add -l が答えるのは、いま実際に使っている ssh の分だけだからです。Windows の ssh-agentが、この 3 つを解きほぐします。
原因 3:公開鍵がサーバー上にない
公開側は、~user/.ssh/authorized_keys に 1 行として入っていなければなりません。しかもそのユーザーのために、そのユーザーのホームに、です。そこへ確実に入れる方法(コピーにはパスワード認証か既存の鍵を使います):
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
手作業で行う場合(たとえばプロバイダーのコンソール経由で)は、その 1 行を追記し、ファイルを決して上書きしません:
mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys
# paste the one line from id_ed25519.pub, Enter, Ctrl-D
よくある取りこぼし:鍵が root のファイルに入ったのに、あなたは deploy でログインしている。行がエディターで折り返されて、いまや 2 行になっている。秘密鍵を貼ってしまった(ファイルは ssh-ed25519 AAAA… で始まります。-----BEGIN が見えたら、それは間違った側です)。
原因 4:パーミッションと所有権
sshd の StrictModes(既定でオン)は、authorized_keys へのパスが所有者以外の誰かに書き込み可能だと、そのファイルを尊重することを拒みます。これが、あの定番の「鍵をコピーしたのに、それでも動かない」です。完全な修正を、対象のユーザーとして実行します:
chmod go-w ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh
ホームディレクトリの行が効くのに、忘れられがちです。グループ書き込み可能な /home/deploy は、誰でも読める鍵ファイルと同じくらいしっかりチェックに落ちます。サーバーログの bad ownership or modes の行が、どのディレクトリに異を唱えているかを正確に教えてくれます。
原因 5:鍵の形式またはパスフレーズの誤り
OpenSSH は PuTTY の .ppk ファイルを読めません。-i でそれを指すと、詳細出力で invalid format と出て失敗します。PuTTYgen から OpenSSH 形式の鍵をエクスポートするか(Conversions → Export OpenSSH key)、新しい現代的な鍵を生成して登録してください(ほとんどの場合 Ed25519(英語))。Windows でまだ PuTTYgen を使い続けているなら、PuTTY セッションをインポートして OpenSSH 形式の鍵をそのまま扱える Windows 用 SSH クライアントを使えば、この変換の手間はそもそも不要になります。秘密鍵ファイルが読めて、パスフレーズが思っているとおりのものだと確かめるには、その公開側を表示させます:
ssh-keygen -y -f ~/.ssh/id_ed25519
それで鍵が表示されれば、ファイルとパスフレーズは問題ありません。そして、その出力を authorized_keys の行と見比べれば、本当に同じ鍵かどうかを確認できます。
原因 6:サーバー設定が許可していない
これはあまり多くありませんが、サーバーにアクセスできるなら確認は簡単です。sshd が実際にどんな設定で動いているかを尋ねます:
sudo sshd -T | grep -Ei 'pubkeyauthentication|authorizedkeysfile'
PubkeyAuthentication は yes でなければなりません(既定ですが、堅牢化スクリプトが反転させることがあります)。AuthorizedKeysFile は、sshd がどこを見るかを教えてくれます。誰かがそれを /etc/ssh/authorized_keys/%u に向けていたら、丁寧に置いた ~/.ssh/authorized_keys は無視されています。/etc/ssh/sshd_config を変更したら、毎回:
sudo systemctl reload sshd
原因 7:SELinux のコンテキスト(RHEL 系)
RHEL、Alma、Rocky、Fedora などでは、変わった手段で作られた ~/.ssh——バックアップから復元、root でコピー、マウントしたボリューム上で作成——が、誤った SELinux のラベルを帯びることがあり、sshd はパーミッションが完璧なファイルへの読み取りアクセスを拒否されます。上のすべてが問題なく、エラーは残り続け、ls -Z ~/.ssh が ssh_home_t 以外の何かを示します。1 つのコマンドでラベルを修復します:
restorecon -R -v ~/.ssh
RHEL 系のマシンで手詰まりなら、とにかく実行してみてください。ラベルがすでに正しかった場合でも無害です。
原因 8:root ログインが無効
最近の既定は PermitRootLogin prohibit-password(鍵のみ)か no(決して許さない)です。root@host を試していて、鍵が本当に /root/.ssh/authorized_keys にあるなら、確認します:
sudo sshd -T | grep -i permitrootlogin
no の場合、root に対してはどんな資格情報も決して通りません。非特権のユーザーでログインして sudo してください。どのみち既定があなたに促している構成がこれです。
手早い回答
Permission denied (publickey) は、鍵が壊れているという意味ですか?
ほぼ違います。サーバーが、あなたが提示した方式をどれも受け入れなかったという意味で、たいていはユーザーか鍵の取り違えであって、壊れた鍵ではありません。鍵が読めてパスフレーズが正しいことは、ssh-keygen -y -f ~/.ssh/id_ed25519 で確認してください。
(publickey) と (publickey,password) の違いは?
括弧は、サーバーがまだ許可している方式を並べます。(publickey) は鍵のみ、(publickey,password) はパスワードも通るという意味なので、本来は尋ねられるはずでした。尋ねられなかったなら、クライアントが鍵を使い切ったあとであきらめたのです。
昨日は動いたのに今は失敗する——何が変わった?
サーバーの作り直し、鍵のローテーション、あるいはタイムアウト後に鍵を手放したエージェントです。まず ssh-add -l で何が読み込まれているかを見て、次にマシンが再イメージ化されていないか確認します(再イメージ化は host key verification failed(英語)も引き起こします)。
二度と起きないようにする
上の原因のほとんどは、毎回導き出す必要のない、ホストごとの事実です。どのユーザーか、どの鍵か、どのポートか。これらを ~/.ssh/config に固定すれば、このエラーの種類はおおむね消えます。そして残るエラーについては、エラー解読表が、出会うであろう残り 9 つを扱っています。
同じ事実は、ドットファイルの代わりにクライアントの中に置けます。Termalin は、ユーザー・ポート・鍵を、保存したホストと一緒に保存し、内蔵エージェントで鍵を一度アンロックし(パスフレーズのキャンセルが鍵を黙ってスキップすることはありません)、サーバーの身元を初回接続時に検証し、ホストごとにライブの状態を表示します。おかげで「そもそも起動している?」「正しい鍵を使っている?」が、診断の手順ではなくなります。さらに PuTTY のセッションをインポート(英語)することもでき、原因 5 を永久に引退させます。
Termalin は、ホストごとのユーザー・ポート・鍵をホストと一緒に保ち、初回接続時にサーバーを検証する、無料のクロスプラットフォーム SSH クライアントです。ダウンロードするか、鍵を安全に扱う仕組みをお読みください。