Ansible "Permission denied (publickey)" - Fix SSH Auth in CI
SSH reached the host but rejected authentication - the private key the runner offered is not accepted for the user being used. This is a credentials/config problem, not a network one.
What this error means
Ansible reports the host UNREACHABLE with Permission denied (publickey). The connection itself succeeds (so it is not a timeout), but no offered key authenticates, so every task is skipped. It fails identically on retry.
fatal: [db01]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to
the host via ssh: deploy@10.0.4.7: Permission denied (publickey).", "unreachable": true}Common causes
Private key not loaded in CI
The deploy key is not added to the SSH agent or referenced via --private-key, so Ansible has no key to offer. Common when the key lives in a secret that was never written to disk or loaded.
Wrong remote_user or missing public key
The play connects as the wrong user, or the matching public key is not in that user’s authorized_keys on the target, so authentication is refused.
How to fix it
Load the deploy key into the agent
Write the secret key to the agent (or a file) before running the playbook.
- run: |
eval "$(ssh-agent -s)"
echo "${{ secrets.DEPLOY_SSH_KEY }}" | ssh-add -
ansible-playbook -i inventory site.ymlMatch remote_user and authorized_keys
- Set
ansible_user/remote_userto the account whoseauthorized_keysholds your public key. - Verify manually:
ssh -i key deploy@hostshould succeed before Ansible does. - Confirm the public key is present on the target for that user.
How to prevent it
- Store the deploy private key as a CI secret and load it per job.
- Pin
ansible_userexplicitly in inventory so the right account is used. - Use a dedicated, narrowly scoped deploy key rather than a personal key.