The SSH client processes configuration files in a specific order, applying the first matching rule it encounters. This "first match wins" behavior is critical for managing multiple servers efficiently. Understanding these rules prevents unexpected connection failures and ensures your security policies are applied correctly without being overridden by later entries.
The Two Configuration Files
SSH configuration is split between system-wide and user-specific settings. The global configuration file is located at
/etc/ssh/ssh_config on Linux and macOS systems. On Windows, this file is typically found in
C:\ProgramData\ssh\ssh_config. This file applies to all users on the machine and should generally contain default settings that apply universally.
The user-specific configuration file is stored in
~/.ssh/config on Unix-like systems or
%USERPROFILE%\.ssh\config on Windows. This file takes precedence over the global configuration. If you define a setting in both files, the value in your personal config file will be used. It is best practice to keep sensitive host-specific details in the user config file while keeping general defaults in the global file.
The First Match Wins Rule
The most important concept in SSH configuration is the "first match wins" principle. When the SSH client reads a configuration file, it scans from top to bottom. For any given option, the first instance of that option that matches the current host criteria is used. All subsequent occurrences of that same option for the same host are ignored.
This means the order of your host blocks matters significantly. If you have a general block for
* (all hosts) and a specific block for a particular server, the specific block must appear before the general block if you want to override the general settings. Otherwise, the general settings will apply, and your specific overrides will be discarded.
# This will NOT work as expected because the wildcard matches first
Host *
IdentityFile ~/.ssh/default_key
User admin
Host myserver.example.com
IdentityFile ~/.ssh/special_key # Ignored!
User root # Ignored!
To fix this, reverse the order:
# Correct order: Specific hosts first
Host myserver.example.com
IdentityFile ~/.ssh/special_key
User root
Host *
IdentityFile ~/.ssh/default_key
User admin
Pattern Matching Syntax
SSH supports pattern matching using wildcards and negation. The asterisk (
*) matches any sequence of characters, including none. The question mark (
?) matches exactly one character. You can also use negation with an exclamation mark (
!).
For example,
Host *.example.com matches any subdomain of example.com.
Host !*.example.com matches anything that does not end with .example.com. You can combine patterns by separating them with spaces. The SSH client checks each pattern against the hostname you are connecting to.
# Matches any host ending in .local but not jump.local
Host *.local !jump.local
ForwardAgent yes
Applying Rules in PowerShell
When using PowerShell to manage SSH connections, the same configuration rules apply. The SSH client executable reads the config files regardless of the shell you are using. However, PowerShell scripts might need to explicitly specify the config file path if it is not in the default location.
You can test your configuration by running SSH with the verbose flag. This shows exactly which config file is being read and which rules are being applied. This is invaluable for debugging issues where connections behave unexpectedly.
ssh -v user@hostname
Look for lines indicating "Reading configuration data" and "Matched configuration." These lines confirm which rules were active during the connection attempt. If you are experiencing delays or authentication failures, check the verbose output to see if the wrong identity file or user was selected due to a misordered config entry. For more details on resolving connection delays, see our guide on
How to troubleshoot a long delay when connecting over SSH?.
Common Pitfalls and Best Practices
One common mistake is assuming that later entries override earlier ones. Remember that they do not. Always place specific host definitions above general wildcard definitions. Another pitfall is using incorrect syntax for negation or wildcards, which can lead to unintended matches.
It is also important to set proper permissions on your config file. On Unix systems, the file should be readable only by you (mode 600). If the file is world-readable, SSH may ignore it entirely for security reasons. On Windows, ensure the file has appropriate ACLs to prevent unauthorized access to your keys.
For related issues involving file dialogs or connection setups, refer to
How to Open File Dialogue Window in SSH for Windows, PowerShell, and Ubuntu 20.04.
Frequently Asked Questions
What happens if I define the same option twice for the same host?
The first occurrence is used, and the second is completely ignored. SSH does not merge or average values; it strictly follows the first match rule. Always review your config file order carefully to ensure the desired settings are defined first.
Can I use variables in the SSH config file?
No, the SSH config file does not support variable expansion like some scripting languages. You must hardcode values or use environment variables outside of SSH. Some clients allow includes, but native SSH config parsing is static.
How do I debug which config file is being used?
Use the
-v flag with the ssh command. The verbose output lists every config file read and highlights which options were matched. This helps identify if a global config is overriding your local settings unexpectedly.
Does the order matter for HostName vs IdentityFile?
Order matters within the context of host blocks. If you have two different host blocks for the same hostname, the first block encountered determines all settings for that connection. Ensure specific hosts are listed before general wildcards.
What permissions should my SSH config file have?
On Linux and macOS, set the permission to 600 using
chmod 600 ~/.ssh/config. On Windows, ensure the file is owned by your user account and not writable by others. Incorrect permissions cause SSH to silently ignore the file.