AnsibleでリモートホストへのSSH接続時に'Permission denied (publickey)'エラーを修正する

beginner🔧 Ansible2026-05-20| Ansible 2.9以降、Ubuntu/Debian/CentOS/RHEL、OpenSSH、Linuxコントロールノード

Error Message

Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic)
#ssh#publickey#認証#秘密鍵#ansible-ssh

何が起きているのか

プレイブックまたは ansible -m ping を実行すると、次のエラーが表示されます:

fatal: [192.168.1.10]: UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic)",
    "unreachable": true
}

AnsibleはSSHキーを提示しましたが、サーバーに拒否されました。何も実行されません。

これはタイムアウトではありません。リモートホストは起動していますが、キーを拒否しているのです。約90%のケースで、原因は次の4つのいずれかです:キーパスの誤り、authorized_keys にキーが登録されていない、リモートユーザーの誤り、またはキーや .ssh ディレクトリのファイルパーミッションの問題です。

デバッグ手順

ステップ1:まず手動でSSH接続をテストする

Ansibleを一旦置いて、SSHの生の接続をテストします:

ssh -i /path/to/private_key ansible_user@192.168.1.10

これも失敗する場合、問題はAnsibleではなくSSH自体にあります。まずSSHを修正すれば、Ansibleも動作するようになります。

行き詰まった場合は、-v を追加して認証のどこで失敗しているか詳細を確認します:

ssh -v -i /path/to/private_key ansible_user@192.168.1.10

出力から次のような行を探します:

debug1: Offering public key: /path/to/private_key
debug1: Authentications that can continue: publickey
Permission denied (publickey).

ステップ2:Ansibleを詳細出力モードで実行する

ansible all -m ping -vvv

-vvv を指定すると、Ansibleが内部で構築する正確なSSHコマンドが出力されます。どのキーを読み込んでいるか、どのユーザーで接続しているか、どのポートを使用しているかが確認できます。

ステップ3:インベントリを確認する

cat inventory.ini

以下の変数が正しく設定されているか確認します:

[webservers]
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa

よくある原因と対処法

原因1:プライベートキーのパスが間違っているまたは指定されていない

Ansibleが指定されたプライベートキーを見つけられない、または読み取れない状態です。

**対処法:**キーが存在し、正しい所有権を持っていることを確認します:

ls -la ~/.ssh/id_rsa
# 表示例: -rw------- 1 youruser youruser

次に ansible.cfg でパスを設定します:

# ansible.cfg
[defaults]
private_key_file = ~/.ssh/id_rsa

またはインベントリでホストごとに指定します:

192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=/home/youruser/.ssh/deploy_key

原因2:リモートホストの authorized_keys に公開鍵が登録されていない

公開鍵がそもそも登録されていません。リモートホストはあなたの認証情報を知りません。

**対処法:**1つのコマンドでキーを転送します:

ssh-copy-id -i ~/.ssh/id_rsa.pub ansible_user@192.168.1.10

パスワードでのアクセスもできない場合は、リモートホストで手動で追加します:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "your-public-key-content" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

原因3:キーまたは .ssh ディレクトリのファイルパーミッションが間違っている

SSHはパーミッションが緩すぎるキーを静かに無視します。「パーミッションが原因で無視しました」とは言わず、ただ「permission denied」と返して次に進むだけです。非常に紛らわしい挙動です。

**対処法:**コントロールノード側のパーミッションを適切に設定します:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub

リモートホスト側でも同様に設定します:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

600と644を混同しがちな場合は、ToolCraftのUnix Permissions Calculatorを使うと、パーミッションビットをクリックするだけで正しい数値を即座に確認できます。

原因4:リモートユーザーが間違っている

デフォルトでAnsibleはローカルのユーザー名で接続します。新規セットアップのUbuntuサーバーでは ubuntu、Amazon Linuxでは ec2-user、CentOSでは centos がデフォルトユーザーです。ローカルのユーザー名がこれらと一致することはほぼありません。

**対処法:**ユーザーを明示的に指定します。状況に応じて適切な方法を選んでください:

# インベントリで指定
192.168.1.10 ansible_user=ubuntu

# または ansible.cfg で指定
[defaults]
remote_user = ubuntu

# またはプレイブック内でプレイごとに指定
- hosts: webservers
  remote_user: ubuntu

原因5:SELinux または StrictModes がキーをブロックしている

RHEL/CentOS では、ファイルパーミッションが正しく見えても、SELinuxが authorized_keys の読み取りをSSHに対してブロックすることがあります。問題はモードビットではなく、SELinuxラベルにあります。

**対処法:**SELinuxコンテキストを復元します:

restorecon -Rv ~/.ssh

リモートホストの /etc/ssh/sshd_configStrictModes yes が設定されていないか確認してください。この設定は ~/.ssh ディレクトリとその中のファイルのパーミッションチェックを強制します。

原因6:SSHエージェントが読み込まれていない、または間違ったキーが読み込まれている

キーファイルを指定しない場合、AnsibleはSSHエージェントに現在読み込まれているキーを使用します。個人用キーを読み込んでいても、サーバーがデプロイ用キーを要求している場合、認証は失敗します。しかもエラーメッセージは全く同じように見えます。

**対処法:**現在読み込まれているキーを確認します:

ssh-add -l

正しいキーを読み込みます:

ssh-add ~/.ssh/deploy_key

またはAnsibleにエージェントを無視させ、特定のキーを使用させます:

[ssh_connection]
ssh_args = -o ForwardAgent=no

実際に動作する完全な例

ゼロからAnsible接続を確立するための最小限のセットアップ手順です:

# 1. 新しい ed25519 キーペアを生成する
ssh-keygen -t ed25519 -f ~/.ssh/ansible_key -N ""

# 2. リモートホストに公開鍵を転送する
ssh-copy-id -i ~/.ssh/ansible_key.pub ubuntu@192.168.1.10

# 3. Ansibleを使う前に生のSSH接続が動作するか確認する
ssh -i ~/.ssh/ansible_key ubuntu@192.168.1.10 exit
echo "Exit code: $?"  # 0 であること

# 4. インベントリを作成する
cat > inventory.ini  {
    "changed": false,
    "ping": "pong"
}

複数のホストを管理している場合は、すっきりした1行コマンドで全ホストを一度に確認できます:

ansible all -i inventory.ini -m ping --one-line

まとめと教訓

  • Ansibleを触る前にSSHをテストする。 ssh -v -i key user@host を実行すれば3秒で全てがわかります。これが失敗する場合、Ansibleに勝ち目はありません。
  • パーミッションの問題は静かに失敗する。 SSHはパーミッションが間違っているキーを無視しても、有用なメッセージを出しません。コントロールノードとリモートホストの両方で、プライベートキーには chmod 600.ssh ディレクトリには chmod 700 を必ず設定してください。
  • インベントリで明示的に設定する。 すべてのホストグループに ansible_useransible_ssh_private_key_file を宣言してください。デフォルト値に頼ると、3ヶ月後に別のマシンからAnsibleを実行したときにこのエラーが再発します。
  • 新しいキーにはed25519を使う。 RSA-1024やRSA-2048と比べて、短く、高速で、互換性の問題もありません。

Related Error Notes