A SSH client configuration makes accessing servers much easier and more convenient. Until recently the configuration was done in one single file which could be problematic. But newer versions support includes to read configuration from multiple places.
SSH is the default way to access servers remotely – Linux and other UNIX systems, and since recently Windows as well.
One feature of the OpenSSH client is to configure often used parameters for SSH connections in a central config file,
~/.ssh/config. This comes in especially handy when multiple remote servers require different parameters: varying ports, other user names, different SSH keys, and so on. It also provides the possibility to define aliases for host names to avoid the necessity to type in the FQDN each time. Since such a configuration is directly read by the SSH client other tools wich are using the SSH client in the background – like Ansible – can benefit from the configuration as well.
A typical configuration of such a config file can look like this:
Host webapp HostName webapp.example.com User mycorporatelogin IdentityFile ~/.ssh/id_corporate IdentitiesOnly yes Host github HostName github.com User mygithublogin IdentityFile ~/.ssh/id_ed25519 Host gitlab HostName gitlab.corporate.com User mycorporatelogin IdentityFile ~/.ssh/id_corporate Host myserver HostName myserver.example.net Port 1234 User myuser IdentityFile ~/.ssh/id_ed25519 Host aws-dev HostName 184.108.40.206 User ec2-user IdentityFile ~/.ssh/aws.pem IdentitiesOnly yes StrictHostKeyChecking no Host azure-prod HostName 220.127.116.11 User azure-prod IdentityFile ~/.ssh/azure_ed25519
While this is very handy and helps a lot to maintain sanity even with very different and strange SSH configurations, a single huge file is hard to manage.
Cloud environments for example change constantly, so it makes sense to update/rebuild the configuration regularly. There are scripts out there, but they either just overwrite existing configuration, or do entirely work on an extra file which is referenced in each SSH client call with
ssh -F .ssh/aws-config, or they require to mark sections in the
"### AZURE-SSH-CONFIG BEGIN ###". All attempts are either clumsy or error prone.
Another use case is where parts of the SSH configuration is managed by configuration management systems or by software packages for example by a company – again that requires changes to a single file and might alter or remove existing configuration for your others services and servers. After all, it is not uncommon to use your more-or-less private Github account for your company work so that you have mixed entries in your
The underneath problem of managing more complex software configurations in single files is not unique to OpenSSH, but more or less common across many software stacks which are configured in text files. Recently it became more and more common to write software in a way that configuration is not read as a single file, but that all files from a certain directory are read in. Examples for this include:
- sudo with the directory
- Apache with
- Nginx with
- Systemd with
- and so on…
Initially such an approach was not possible with the SSH client configuration in OpenSSH but there was a bug reported even including a patch quite some years ago. Luckily, almost three years ago OpenSSH version 7.3 was released and that version did come with the solution:
* ssh(1): Add an Include directive for ssh_config(5) files.
So now it is possible to add one or even multiple files and directories from where additional configuration can be loaded.
Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(7) wildcards and, for user configurations, shell-like `~’ references to user home directories. Files without absolute paths are assumed to be in ~/.ssh if included in a user configuration file or /etc/ssh if included from the system configuration file. Include directive may appear inside a Match or Host block to perform conditional inclusion.https://www.freebsd.org/cgi/man.cgi?ssh_config(5)
.ssh/config file defines a sub-directory from where additional configuration can be read in:
$ cat ~/.ssh/config Include ~/.ssh/conf.d/*
~/.ssh/conf.d there can be additional files, each containing one or more host definitions:
$ ls ~/.ssh/conf.d/ corporate.conf github.conf myserver.conf aws.conf azure.conf
$ cat ~/.ssh/conf.d/aws.conf Host aws-dev HostName 18.104.22.168 User ec2-user IdentityFile ~/.ssh/aws.pem IdentitiesOnly yes StrictHostKeyChecking no
This feature made managing SSH configuration for me much easier, and I only have few use cases and mainly require it to keep a simple overview over things. For more flexible (aka cloud based) setups this is crucial and can make things way easier.
Note that the additional config files should only contain host definitions! General SSH configuration should be inside
~/.ssh/config and should be before the include directive: any configuration provided after a “Host” keyword is interpreted as part of that exact host definition – until the next host block or until the next “Match” keyword.