Qué ves
En un script con BatchMode=yes, o sin terminal donde preguntar, solo aparece una línea:
Host key verification failed.
Con StrictHostKeyChecking=yes hay un motivo encima:
No ED25519 host key is known for server and you have requested strict checking.
Host key verification failed.
Git añade sus propias líneas, que no significan que falte el repositorio:
Host key verification failed.
fatal: Could not read from remote repository.
Averigua en cuál de los casos estás
Ejecuta esto con el mismo usuario que ejecuta el comando que falla:
ssh-keygen -F server
Para un servidor en otro puerto, la entrada se guarda entre corchetes:
ssh-keygen -F '[server]:2222'
- Sin salida: el host es desconocido para este usuario. Mira la causa 1 y la causa 2.
- Se imprime una línea y el error muestra un gran aviso REMOTE HOST IDENTIFICATION HAS CHANGED: mira la causa 3.
Causa 1: el servidor no está en known_hosts
En una terminal, SSH te pediría confirmar la huella. BatchMode=yes prohíbe las preguntas, y un trabajo sin terminal no tiene a quién preguntar, así que SSH falla. Añade la clave de antemano.
Obtén la clave y compárala con la del servidor antes de confiar en ella:
ssh-keyscan -t ed25519 server > server.hostkey
ssh-keygen -lf server.hostkey
En el propio servidor, o desde una consola de tu proveedor:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Si las dos huellas coinciden, instala la clave:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
cat server.hostkey >> ~/.ssh/known_hosts
Para un puerto distinto de 22, usa ssh-keyscan -p 2222 -t ed25519 server. ssh-keyscan por sí solo no demuestra nada, porque acepta lo que responda en esa dirección. La comparación es lo que lo hace seguro. Los servicios de alojamiento publican sus huellas, por ejemplo GitHub en la página de las fuentes.
En CI
Guarda la línea verificada como variable de CI y escríbela al principio del trabajo, en lugar de escanear en cada ejecución:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$KNOWN_HOSTS" >> ~/.ssh/known_hosts
accept-new y no
StrictHostKeyChecking=accept-new guarda una clave que no había visto nunca y sigue rechazando una que haya cambiado. Confía en la primera conexión sin comprobarla, algo aceptable para una máquina desechable en una red de confianza. Evita StrictHostKeyChecking=no: también deja continuar la conexión cuando la clave ha cambiado, que es justo la situación para la que existe esta comprobación.
Qué contiene cada línea del archivo: known_hosts explicado.
Causa 2: otro usuario u otro HOME
known_hosts pertenece a un usuario. Funciona en tu terminal y falla en el trabajo cuando este se ejecuta como otro: sudo ssh usa el archivo de root, y cron, las compilaciones de Docker y los runners de CI tienen su propia carpeta personal, a menudo vacía en cada ejecución.
whoami
echo "$HOME"
ssh -G server | grep -iE '^(userknownhostsfile|stricthostkeychecking) '
El último comando muestra qué archivos leerá SSH para ese host, sin conectar. Instala la clave para ese usuario, o indica al trabajo un archivo que controles:
ssh -o UserKnownHostsFile=/path/to/known_hosts -o BatchMode=yes user@server true
Causa 3: la clave guardada es distinta
La salida empieza entonces con ese aviso, y las dos últimas líneas son:
Host key for server has changed and you have requested strict checking.
Host key verification failed.
Lo más común es una reinstalación o un servidor nuevo en la misma dirección, pero así también se ve una interceptación. accept-new no lo salva. Compara las huellas como se ha explicado arriba y solo entonces borra la entrada antigua:
ssh-keygen -R server
Con github.com es habitual: GitHub sustituyó su clave de host RSA en marzo de 2023, así que una línea guardada antigua ahora falla. Bórrala con ssh-keygen -R github.com y añade las claves que publica GitHub, desde la página de las fuentes.
Más sobre este caso en REMOTE HOST IDENTIFICATION HAS CHANGED.
Preguntas
¿Qué significa Host key verification failed?
SSH no pudo confirmar la identidad del servidor y se detuvo. O el servidor no está en known_hosts y nadie podía responder a la pregunta, o su clave es distinta de la guardada.
¿Es StrictHostKeyChecking=no una solución segura en CI?
No. También acepta una clave cambiada. Instala la clave verificada en known_hosts, o usa accept-new en máquinas desechables dentro de una red de confianza.
¿Por qué funciona en mi terminal pero falla en cron?
known_hosts pertenece a un usuario. Cron, sudo y los runners de CI usan otro usuario u otra carpeta personal, donde falta la entrada guardada.
¿Por qué git dice Host key verification failed con GitHub?
O github.com no está en known_hosts para el usuario que ejecuta git, o sigue ahí una línea RSA guardada antes de marzo de 2023. Bórrala con ssh-keygen -R github.com y añade las claves de la página de huellas de GitHub.
Fuentes
- ssh_config(5), StrictHostKeyChecking
- ssh-keyscan(1), manual de OpenBSD
- ssh-keygen(1), manual de OpenBSD
- Huellas de las claves SSH de GitHub