The SSH client configuration is controlled by two primary files: the global
/etc/ssh/ssh_config for system-wide defaults and the user-specific
~/.ssh/config for host-tailored settings. Understanding this distinction allows administrators to apply generic policies while overriding them with specific parameters for individual servers, ensuring both security and convenience without manual command-line flags.
Understanding the SSH Configuration Hierarchy
When you initiate an SSH connection, the client looks for configuration directives in a specific order of precedence. The most critical rule is that later definitions override earlier ones. This mechanism is what enables the "Generic vs. Specific" approach. The system first reads the global configuration file, typically located at
/etc/ssh/ssh_config. This file applies to all users on the machine and serves as the baseline for every connection attempt. It contains safe defaults for ciphers, key exchange algorithms, and authentication methods. However, modifying this file requires root privileges and affects every user, which is often undesirable in shared environments or when testing new configurations.
Next, the SSH client checks the user-specific configuration file located at
~/.ssh/config. This file is private to the current user and has higher precedence than the global config. If you define a setting here that conflicts with the global one, your local definition wins. This hierarchy is essential for managing complex environments where you might need different compression levels, proxy commands, or identity files for different hosts. For instance, you might want to use aggressive compression for a slow remote server but disable it for a high-speed local network device. By placing these overrides in
~/.ssh/config, you maintain flexibility without altering the system-wide security posture.
It is also worth noting that command-line arguments take precedence over both of these files. If you specify
-o Compression=no in your terminal command, it will override any compression setting in either config file. This three-tiered system (global, user, command-line) provides granular control over SSH behavior.
The Structure of the Config File
Both global and user-specific config files share the same syntax. They consist of blocks of directives that start with a keyword followed by its value. These blocks are grouped under
Host patterns. A pattern can be a literal hostname, an IP address, or a wildcard expression like
*. When you run
ssh myserver, the client scans through the
Host blocks in order and applies the first matching set of directives. If multiple blocks match, the settings are merged, with later matches taking precedence for conflicting keys.
For example, you might have a general block for all hosts that sets
ServerAliveInterval 60 to prevent timeouts, and then a specific block for
production-server.example.com that sets
IdentityFile ~/.ssh/prod_key. The client will apply both settings because they do not conflict, resulting in a connection that keeps alive and uses the production key.
Creating Generic Configurations
A generic configuration is ideal for establishing consistent behavior across many hosts. You should place these settings in the global
/etc/ssh/ssh_config if they apply to all users, or in
~/.ssh/config if they apply only to you. Common generic settings include disabling password authentication in favor of keys, enabling public key authentication, and setting default ports.
To create a generic setup, open
~/.ssh/config and add a block with a wildcard
Host *. This ensures the settings apply to any host unless explicitly overridden. For example:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
UseKeychain yes
This configuration tells the SSH agent to keep connections alive if the network drops, automatically adds keys to the agent, and uses the macOS keychain for passphrases. These are safe defaults that rarely need to change per host. However, avoid putting sensitive or host-specific details here. If you need to link to other resources, such as understanding how key exchange algorithms interact with these settings, you might refer to
Understanding KEX Algorithms in sshd_config: Does 'pseudo' Override or Take Effect? to ensure your generic cipher suites are compatible with modern security standards.
Implementing Specific Host Configurations
Specific configurations are necessary when a host deviates from the norm. This could be due to legacy hardware requiring older protocols, a jump host requirement, or distinct credentials. To define a specific host, create a new
Host block with the exact hostname or alias you wish to connect to.
Suppose you have a legacy server named
old-db that does not support modern encryption. You would create a specific block for it:
Host old-db
HostName 192.168.1.50
User admin
IdentityFile ~/.ssh/legacy_key
Ciphers aes128-cbc,aes256-cbc
KexAlgorithms diffie-hellman-group1-sha1
In this example, the
Host line defines the alias. When you type
ssh old-db, the client maps it to
192.168.1.50 and applies the specified legacy ciphers. This prevents errors related to incompatible algorithms. Note that using weak ciphers should be done cautiously and only for isolated systems. If you encounter issues with public key identities in tools like KeePassXC, reviewing
KeePassXC and ssh/config: Incorrect Public Key Identity Setting can help troubleshoot why your specific key file might not be recognized.
You can also use wildcards within specific configurations. For example,
Host *.internal.corp applies to all subdomains of
internal.corp, allowing you to set a common ProxyJump for an entire internal network segment while keeping external hosts separate.
Testing and Troubleshooting
After editing your config files, always test them before relying on them. The SSH client provides a verbose mode that shows exactly which config file was read and which settings were applied. Run the following command to see the effective configuration for a specific host:
ssh -G target-host
This command outputs the final resolved configuration, including defaults from the global file and overrides from your user file. If a setting is missing or incorrect, this output helps identify whether the issue lies in the syntax of your config file or in the remote server's acceptance of those parameters. Additionally, ensure that your
~/.ssh/config file has permissions set to
600 (
chmod 600 ~/.ssh/config). SSH will ignore the file if it is readable by others, which is a common source of confusion for beginners.
By mastering the balance between generic defaults and specific overrides, you streamline your workflow and reduce the likelihood of connection failures. This approach scales well, whether you manage five servers or five hundred.
Frequently Asked Questions
What happens if I define conflicting settings in both global and user configs?
The user-specific
~/.ssh/config always takes precedence over the global
/etc/ssh/ssh_config. If you set
Port 2222 in your user config and
Port 22 in the global config, SSH will connect to port 2222. This allows you to customize behavior without needing root access to modify system files.
Can I use wildcards in the Host directive?
Yes, you can use shell-style wildcards like
* and
? in the
Host directive. For example,
Host *.example.com matches any subdomain of
example.com. You can combine multiple patterns in one line, such as
Host prod-* staging-*, to apply the same settings to a group of similarly named servers.
Why does SSH ignore my ~/.ssh/config file?
SSH ignores the config file if it is not owned by you or if it is world-readable. Ensure the file permissions are set to
600 using
chmod 600 ~/.ssh/config. Additionally, check that the file is not symlinked incorrectly and that there are no syntax errors preventing it from being parsed.
How do I specify a non-standard port for a specific host?
Add the
Port directive inside the specific
Host block. For example, if your web server runs SSH on port 8022, define
Host webserver followed by
Port 8022. When you run
ssh webserver, the client automatically connects to port 8022 instead of the default 22.
Is it safe to store passwords in the SSH config file?
No, the SSH config file does not support storing passwords directly. It only supports key-based authentication or interactive prompts. If you need to automate password entry, you should use tools like
sshpass or configure your SSH agent to handle key passphrases securely. Never write plaintext passwords in config files.