wiki: add Ansible SSH Host Alias Bypass troubleshooting article
Documents why `ansible myhost -m ping` fails with Permission denied while `ssh myhost` works — SSH Host blocks match on literal pattern, not on resolved HostName, so `ansible_host: <IP>` bypasses the alias and the declared IdentityFile never gets applied. Covers the portable fix (ansible_ssh_private_key_file in host_vars), the symlink sidebar for standardizing key names across control nodes, alternatives, and a diagnosis checklist. Also catches index.md up with the ansible-check-mode-false-positives article that was already published but missing from the nav.
This commit is contained in:
parent
181c04bed8
commit
2dbeb22ef9
2 changed files with 106 additions and 1 deletions
103
05-troubleshooting/ansible-ssh-host-alias-bypass.md
Normal file
103
05-troubleshooting/ansible-ssh-host-alias-bypass.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
title: "Ansible Fails with Permission Denied While `ssh <alias>` Works (Host Alias Bypass)"
|
||||
domain: selfhosting
|
||||
category: troubleshooting
|
||||
tags:
|
||||
- ansible
|
||||
- ssh
|
||||
- ssh-config
|
||||
- inventory
|
||||
- host-vars
|
||||
- authentication
|
||||
- troubleshooting
|
||||
status: published
|
||||
created: 2026-04-21
|
||||
updated: 2026-04-21
|
||||
---
|
||||
|
||||
# Ansible Fails with Permission Denied While `ssh <alias>` Works (Host Alias Bypass)
|
||||
|
||||
## The Problem
|
||||
|
||||
Ansible can't connect to a host, but plain SSH to the same host works fine from the same shell:
|
||||
|
||||
```
|
||||
$ ssh myhost
|
||||
last login: ...
|
||||
|
||||
$ ansible myhost -m ping
|
||||
myhost | UNREACHABLE! => {
|
||||
"msg": "Failed to connect to the host via ssh: user@10.0.0.42: Permission denied (publickey).",
|
||||
"unreachable": true
|
||||
}
|
||||
```
|
||||
|
||||
The host is online, the key works, the inventory defines the host — yet Ansible sees `Permission denied (publickey)`.
|
||||
|
||||
## Why It Happens
|
||||
|
||||
Ansible is connecting to the host **by IP**, and SSH doesn't apply `Host` alias blocks when you connect by IP.
|
||||
|
||||
Your `~/.ssh/config` likely looks like this:
|
||||
|
||||
```
|
||||
Host myhost
|
||||
HostName 10.0.0.42
|
||||
User myuser
|
||||
IdentityFile ~/.ssh/id_ed25519_custom
|
||||
```
|
||||
|
||||
When you run `ssh myhost`, SSH matches the `Host myhost` block and uses the custom key.
|
||||
|
||||
When Ansible runs, its inventory specifies `ansible_host: 10.0.0.42`. SSH is invoked as `ssh user@10.0.0.42` — and the `Host` directive matches on **literal pattern**, not on resolved `HostName`. The string `10.0.0.42` doesn't match the pattern `myhost`, so the block is skipped. SSH falls back to default identity files (`id_rsa`, `id_ecdsa`, `id_ed25519`) — none of which are the actual key — and authentication fails.
|
||||
|
||||
Running `ssh -vv user@<IP>` confirms the custom key is never offered.
|
||||
|
||||
## The Fix
|
||||
|
||||
**Declare the key path in inventory** so Ansible passes it explicitly, independent of SSH config:
|
||||
|
||||
```yaml
|
||||
# host_vars/myhost/vars.yml
|
||||
ansible_user: myuser
|
||||
ansible_host: 10.0.0.42
|
||||
ansible_ssh_private_key_file: ~/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
This is the portable fix — it lives in the inventory repo, so every control node that pulls the repo picks it up.
|
||||
|
||||
**Caveat:** if different control nodes store the same key under different filenames (e.g. `id_ed25519` on one machine, `id_ed25519_fleet` on another), pick a single canonical path and standardize. The simplest way is to symlink on the outlier machines:
|
||||
|
||||
```
|
||||
ln -s id_ed25519_fleet ~/.ssh/id_ed25519
|
||||
ln -s id_ed25519_fleet.pub ~/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
Then host_vars can declare one path and work everywhere.
|
||||
|
||||
## Alternative Fixes (Less Portable)
|
||||
|
||||
**Second `Host` block matching the IP.** Add to `~/.ssh/config`:
|
||||
|
||||
```
|
||||
Host myhost 10.0.0.42
|
||||
HostName 10.0.0.42
|
||||
User myuser
|
||||
IdentityFile ~/.ssh/id_ed25519_custom
|
||||
```
|
||||
|
||||
The `Host` line accepts multiple patterns. Works immediately but is per-machine — doesn't help other control nodes.
|
||||
|
||||
**Change `ansible_host` to the alias instead of the IP.** Requires DNS or `/etc/hosts` entry that resolves the alias fleet-wide. Works if you already have reliable name resolution; otherwise adds infrastructure for no real gain.
|
||||
|
||||
## How to Diagnose This
|
||||
|
||||
If `ssh <alias>` works but Ansible fails with `Permission denied (publickey)`:
|
||||
|
||||
1. Check `ansible_host` in host_vars / inventory. If it's an IP, suspect alias bypass.
|
||||
2. Run `ssh -vv user@<IP>` (use the IP, not the alias) and look at the `Offering public key` lines. If the key from your `Host` block isn't listed, the block isn't being applied.
|
||||
3. Fix in inventory, not SSH config, if you want the result portable across control nodes.
|
||||
|
||||
## Why This Gotcha Is Invisible
|
||||
|
||||
SSH doesn't log "`Host` block skipped because pattern didn't match." The key simply isn't offered, and the server responds with the same generic `Permission denied (publickey)` you'd see for any auth failure. The inventory and SSH config both look correct in isolation — it's the interaction between them that's broken.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
created: 2026-03-15T06:37
|
||||
updated: 2026-04-19
|
||||
updated: 2026-04-19T04:57
|
||||
---
|
||||
# 🔧 General Troubleshooting
|
||||
|
||||
|
|
@ -23,6 +23,8 @@ Practical fixes for common Linux, networking, and application problems.
|
|||
- [SSH Timeout During dnf upgrade on Fedora Hosts](ansible-ssh-timeout-dnf-upgrade.md)
|
||||
- [Vault Password File Missing](ansible-vault-password-file-missing.md)
|
||||
- [ansible.cfg Ignored on WSL2 Windows Mounts](ansible-wsl2-world-writable-mount-ignores-cfg.md)
|
||||
- [Ansible Check Mode False Positives in Verify/Assert Tasks](ansible-check-mode-false-positives.md)
|
||||
- [Ansible Fails with Permission Denied While `ssh <alias>` Works (Host Alias Bypass)](ansible-ssh-host-alias-bypass.md)
|
||||
- [Fedora usrmerge: ebtables Symlink Blocks Directory Consolidation](fedora-usrmerge-ebtables-blocker.md)
|
||||
|
||||
## 📦 Docker & Systems
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue