KhueApps
Home/DevOps/How to fix 'Host key verification failed' when using SSH

How to fix 'Host key verification failed' when using SSH

Last updated: October 07, 2025

Overview

SSH shows "Host key verification failed" when the server’s host key is missing from, or conflicts with, your known_hosts file. This protects you from man‑in‑the‑middle attacks. Fixes involve verifying the host’s fingerprint, then updating known_hosts.

Common contexts in DevOps/Git:

  • First-time SSH to a Git remote (e.g., [email protected])
  • CI/CD runners with ephemeral home directories
  • Rebuilt servers or rotated SSH host keys

Quickstart (safe defaults)

  • First connection to a known-good host:
    • Interactively: ssh -o StrictHostKeyChecking=accept-new user@host
    • Non-interactive (CI): ssh-keyscan -H host >> ~/.ssh/known_hosts
  • Host key changed and you trust the new host key:
    1. Remove old key: ssh-keygen -R host
    2. Add new key: ssh-keyscan -H host >> ~/.ssh/known_hosts

For Git remotes, replace host with your Git server (e.g., github.com, gitlab.com).

Minimal working example (CI-safe Git clone)

This snippet preloads known_hosts and clones over SSH without interactive prompts.

set -euo pipefail

# 1) Ensure SSH directory and correct permissions
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# 2) Preload host key(s) safely
# Optional: pin key types to modern algorithms
ssh-keyscan -t rsa,ecdsa,ed25519 -H github.com >> ~/.ssh/known_hosts
chmod 600 ~/.ssh/known_hosts

# 3) Clone using SSH; no prompts
GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=yes" \
  git clone [email protected]:org/repo.git

Notes:

  • Use StrictHostKeyChecking=yes after you preload known_hosts. Avoid "no"; prefer accept-new or preloading.
  • Repeat ssh-keyscan for each host you access (e.g., github.com, gitlab.com, your.internal.git).

Step-by-step fixes

  1. Identify the cause
  • First connect: host is not in known_hosts.
  • Host key changed: mismatch with stored key.
  • Wrong host name or DNS: connecting to an unexpected server.
  1. Verify the fingerprint
  • Obtain the host’s SSH fingerprint via your organization’s source of truth or console. Compare to ssh-keyscan output:
    • ssh-keyscan -H host | ssh-keygen -lf -
  1. Remove stale entries (only if a change is confirmed)
ssh-keygen -R host
# If a non-standard port, include it: ssh-keygen -R "[host]:2222"
  1. Add the correct host key
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keyscan -H host >> ~/.ssh/known_hosts
chmod 600 ~/.ssh/known_hosts
  1. Test SSH
ssh -o StrictHostKeyChecking=yes user@host exit
  1. Retry your Git operation
git ls-remote git@host:org/repo.git
# or
GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=yes" git clone git@host:org/repo.git

Git-specific tips

  • Non-interactive pipelines:
    • Preload keys with ssh-keyscan.
    • Or use accept-new if your OpenSSH supports it (7.6+): GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new" git fetch
  • Multiple hosts: maintain a single known_hosts shared across jobs or cache it between pipeline stages.
  • Custom ports: use the [host]:port format in known_hosts and ssh-keygen -R.

Using SSH config (host aliases)

Simplify commands and pin options per host.

# ~/.ssh/config
Host git-prod
  HostName git.example.com
  User git
  Port 22
  IdentityFile ~/.ssh/id_ed25519
  StrictHostKeyChecking yes
  UserKnownHostsFile ~/.ssh/known_hosts

Then:

git clone git@git-prod:org/repo.git

Common scenarios and fixes

SymptomLikely causeFix
Host key verification failed on first connectHost not in known_hostsssh-keyscan -H host >> ~/.ssh/known_hosts
Same error after server rebuildHost key rotated/mismatchssh-keygen -R host; ssh-keyscan -H host >> ~/.ssh/known_hosts
Works locally, fails in CIEphemeral home, empty known_hostsPreload with ssh-keyscan in pipeline before Git commands
Using non-standard portEntry doesn’t match [host]:portUse ssh-keyscan -p PORT -H host >> ~/.ssh/known_hosts
Intermittent DNS/CDN targetsDifferent backends/keysUse vendor-published known_hosts or pin to stable endpoint

Pitfalls to avoid

  • Using StrictHostKeyChecking=no in production. This disables verification and exposes you to MITM.
  • Appending duplicate or incorrect keys. Clean stale keys with ssh-keygen -R before adding new ones.
  • Wrong file permissions. SSH may ignore insecure files; ensure 600 for known_hosts, 700 for ~/.ssh.
  • Skipping fingerprint verification. Always verify when keys change.
  • Assuming one key type. Some hosts publish multiple keys (rsa, ecdsa, ed25519). Collect them as needed.

Performance notes

  • Pre-seed known_hosts once per workspace or container image to avoid repeated ssh-keyscan calls.
  • For many hosts, batch scan in one go:
ssh-keyscan -H host1 host2 host3 >> ~/.ssh/known_hosts
  • Reduce latency by reusing SSH connections when doing many Git operations:
# ~/.ssh/config
Host *
  ControlMaster auto
  ControlPersist 5m
  ControlPath ~/.ssh/cm-%r@%h:%p
  • Set a reasonable ssh-keyscan timeout for slow networks:
ssh-keyscan -T 5 -H host >> ~/.ssh/known_hosts

Troubleshooting checklist

  • Confirm you’re connecting to the expected hostname and port.
  • Verify fingerprints against a trusted source before updating.
  • Remove stale keys with ssh-keygen -R host (and [host]:port if needed).
  • Re-add with ssh-keyscan -H host and secure permissions.
  • Retry SSH with StrictHostKeyChecking=yes or accept-new.
  • For Git in CI, preload known_hosts before any git fetch/clone.

Tiny FAQ

  • Is StrictHostKeyChecking=no ever OK?
    • Avoid it. Use accept-new for first connections or pre-seed known_hosts.
  • Where is known_hosts?
    • Unix/macOS: ~/.ssh/known_hosts. Windows (Git for Windows/OpenSSH): %USERPROFILE%.ssh\known_hosts.
  • How do I handle rotated keys at scale?
    • Distribute updated known_hosts via config management or bake it into base images, then run ssh-keygen -R and redeploy.
  • Which key type should I prefer?
    • ed25519 is modern and fast. Collect all types the host publishes to avoid mismatches.
  • What OpenSSH version supports accept-new?
    • OpenSSH 7.6 and newer.

Series: Git

DevOps