From 2dbeb22ef9b48c533406580da598addb4737dac4 Mon Sep 17 00:00:00 2001 From: MajorLinux Date: Tue, 21 Apr 2026 09:15:22 -0400 Subject: [PATCH] wiki: add Ansible SSH Host Alias Bypass troubleshooting article MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: ` 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. --- .../ansible-ssh-host-alias-bypass.md | 103 ++++++++++++++++++ 05-troubleshooting/index.md | 4 +- 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 05-troubleshooting/ansible-ssh-host-alias-bypass.md diff --git a/05-troubleshooting/ansible-ssh-host-alias-bypass.md b/05-troubleshooting/ansible-ssh-host-alias-bypass.md new file mode 100644 index 0000000..2483a90 --- /dev/null +++ b/05-troubleshooting/ansible-ssh-host-alias-bypass.md @@ -0,0 +1,103 @@ +--- +title: "Ansible Fails with Permission Denied While `ssh ` 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 ` 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@` 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 ` 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@` (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. diff --git a/05-troubleshooting/index.md b/05-troubleshooting/index.md index 36148d0..bc67333 100644 --- a/05-troubleshooting/index.md +++ b/05-troubleshooting/index.md @@ -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 ` Works (Host Alias Bypass)](ansible-ssh-host-alias-bypass.md) - [Fedora usrmerge: ebtables Symlink Blocks Directory Consolidation](fedora-usrmerge-ebtables-blocker.md) ## 📦 Docker & Systems