Un ejemplo que funciona
Include ~/.ssh/config.d/*
Host web
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Host *.example.com
User admin
Host *
ServerAliveInterval 60
User user
Ahora ssh web significa ssh -p 2222 -i ~/.ssh/id_ed25519_work deploy@203.0.113.10, y además envía un keepalive cada 60 segundos. Los mismos nombres funcionan con scp, sftp y rsync.
El archivo es ~/.ssh/config. No debe poder escribirlo nadie más, o ssh se detiene con Bad owner or permissions. Ejecuta chmod 600 ~/.ssh/config. Los ajustes de todo el sistema se leen después, desde /etc/ssh/ssh_config.
Con decenas de hosts, el archivo es solo una parte de la respuesta. Consulta cómo gestionar muchos servidores SSH para mantener en orden nombres, grupos y claves.
Gana el primer valor
Esta es la regla que sorprende a la gente. Se aplican todos los bloques Host que coinciden, no solo el primero. Para cada opción, ssh se queda con el primer valor que lee e ignora los posteriores. En el ejemplo:
ssh webrecibeUser deploy, porque su bloque va antes deHost *.ssh db.example.comrecibeUser admin.ssh otherrecibeUser user, y los tres recibenServerAliveInterval 60.
Así que pon los hosts concretos arriba y los valores por defecto al final. Si mueves Host * arriba, su User gana en todas partes. Las opciones de la línea de comandos van antes que todo, así que ssh -l other web, ssh other@web y ssh -p 3000 web anulan el archivo.
Hay una excepción que conviene conocer. IdentityFile se acumula: un valor en Host web-* y otro en Host * se prueban ambos, en orden. Añade IdentitiesOnly yes si quieres evitar las claves del agente, y deja IdentityFile fuera de Host * si quieres una clave por host.
Patrones de Host
| Patrón | Coincide con |
|---|---|
Host web db | Cualquiera de los dos nombres. |
Host *.example.com | Cualquier nombre que termine en .example.com. |
Host web-? | web- y un carácter. |
Host web-* !web-old | Todos los nombres web- salvo web-old. Una negación sola no coincide con nada: solo excluye de una coincidencia positiva. |
El patrón se compara con lo que escribes, no con la dirección a la que se resuelve. %h representa ese nombre, lo que permite nombres cortos:
Host web-*
HostName %h.example.com
ssh web-1 ahora se conecta a web-1.example.com.
Include
Include ~/.ssh/config.d/*
Esto lee otros archivos como si estuvieran pegados en ese lugar, lo que permite tener un archivo por proyecto. Las rutas relativas parten de ~/.ssh. Necesita OpenSSH 7.3 o posterior.
Ponlo al principio del archivo. Un bloque Host continúa hasta el siguiente, y un Include colocado después forma parte de ese bloque. Lo probamos: con Include debajo de un bloque Host a, los ajustes del archivo incluido no hicieron nada para ningún otro host. Puedes usarlo a propósito, para incluir un archivo solo para algunos hosts.
Match
Match es una forma más potente de Host, con condiciones:
Match host "*.internal" user deploy
Port 2200
Match exec "test -f /tmp/at-office"
ProxyJump bastion
El primero se aplica solo cuando se cumplen las dos condiciones. El segundo ejecuta un comando de shell y se aplica si termina con 0, que es como cambias ajustes según la red o el lugar. Ten en cuenta que este comando se ejecuta cada vez que se lee la configuración, incluso con ssh -G.
Las condiciones útiles son host, originalhost, user, localuser, exec, tagged, final y all. host comprueba el nombre después de aplicar HostName, y originalhost comprueba lo que escribiste. final hace que ssh lea la configuración una segunda vez, lo que permite a un bloque ver el resultado de la primera pasada:
Host *.corp
HostName %h.example.com
Match final host *.example.com
User admin
En OpenSSH 9.4 y posteriores, también puedes etiquetar hosts y seleccionarlos con Match tagged o ssh -P:
Host web
Tag prod
Match tagged prod
User deploy
ProxyJump tiene su propia página: cómo usar ProxyJump y un host de salto en SSH.
Ver el resultado con ssh -G
ssh -G web
Esto imprime todos los ajustes que ssh usaría para ese host, con todos los archivos y reglas aplicados, y termina sin conectar. Es la forma más rápida de responder a "¿por qué usa ese usuario?":
ssh -G web | grep -E '^(hostname|user|port|identityfile) '
Para saber si tu configuración es la causa de un problema, ignórala en un comando. -F none omite tanto el archivo del usuario como el del sistema:
ssh -F none user@203.0.113.10
Para la propia conexión, ssh -v web imprime qué líneas de la configuración se aplicaron.
Errores comunes
- Un
Host *al principio que anula todo lo que hay debajo. - Una opción global al final del archivo. Las opciones fuera de un bloque deben ir antes del primer
Host. Al final, pertenecen al último bloque. - Una errata en una opción. ssh se detiene con
Bad configuration optiony no conecta con nada, en ningún host. Para una opción que solo conocen algunas versiones, ponIgnoreUnknowny el nombre de la opción encima. - Secretos en el archivo. Contiene rutas a claves, no claves, y no tiene opción de contraseña. Así es como debe seguir.
Preguntas
¿Dónde está el archivo de configuración de SSH?
En Linux y macOS es ~/.ssh/config en tu carpeta personal. En Windows es C:\Users\nombre\.ssh\config. No existe hasta que lo creas. Los ajustes del sistema en /etc/ssh/ssh_config se leen después.
¿Por qué ssh ignora un ajuste de mi config?
Otro bloque que coincide definió la misma opción antes, y gana el primer valor. Ejecuta ssh -G seguido del nombre del host para ver el valor que usará ssh, y pon los hosts concretos encima de Host *.
¿El archivo de configuración de SSH sirve para scp, sftp y rsync?
Sí. Usan ssh para conectarse, así que los nombres de host y las opciones de ~/.ssh/config también se aplican, por ejemplo scp archivo.txt web:/tmp/.
Fuentes
- ssh_config(5), manual de OpenBSD
- ssh(1), manual de OpenBSD
- Notas de la versión OpenSSH 7.3, Include
- Notas de la versión OpenSSH 9.4, etiquetas