What's Actually Happening

You've set up an Include directive in your SSH config to organize hosts into separate files, but SSH isn't loading the configurations from those files. Hosts defined in included files are ignored, or you get errors about unknown hosts even though they're clearly defined.

The Error You'll See

When trying to connect to a host defined in an included file:

bash
ssh: Could not resolve hostname myserver: Name or service not known

Or when checking with verbose mode:

bash
ssh -G myserver | head

The output shows no settings from the included file, or you see no error but the connection uses wrong settings.

Why This Happens

The Include directive has specific requirements that must be met:

  1. 1.OpenSSH 7.3 or later is required
  2. 2.Paths are relative to the directory containing the current file
  3. 3.File permissions must allow reading
  4. 4.Wildcards must match actual files
  5. 5.The Include directive must be in the correct location within the config

Step 1: Check OpenSSH Version

First, verify your SSH version supports Include:

bash
ssh -V

You need OpenSSH 7.3 or later:

bash
OpenSSH_8.9p1 Ubuntu-3ubuntu0.1, OpenSSL 3.0.2 15 Mar 2022

If you have an older version, you cannot use Include directives.

Step 2: Verify File Existence and Paths

Check that the included files actually exist:

bash
ls -la ~/.ssh/config.d/

If using wildcards, verify they match files:

bash
ls -la ~/.ssh/config.d/*.conf

Your config should look like:

``` # ~/.ssh/config Include config.d/*.conf

Host default-server HostName example.com ```

Step 3: Check Config Syntax

Test your SSH config for syntax errors:

bash
ssh -G nonexistent-host > /dev/null

If there's a syntax error, you'll see:

bash
/Users/user/.ssh/config line 5: no argument after keyword "Include"

Common syntax errors include:

  • Missing newline after Include
  • Using quotes when not needed
  • Incorrect glob patterns

Step 4: Verify Relative Paths

The Include path is relative to the directory containing the current file. For ~/.ssh/config:

``` # Correct - relative path Include config.d/*.conf

# Correct - absolute path Include ~/.ssh/config.d/*.conf

# Wrong - tilde may not expand Include ~/config.d/*.conf ```

Use absolute paths or paths relative to the config file location.

Step 5: Check File Permissions

SSH is strict about permissions:

bash
ls -la ~/.ssh/

Your config files should be readable only by you:

bash
drwx------  2 user user 4096 .ssh
-rw-------  1 user user 1024 config
-rw-------  1 user user  512 config.d/server1.conf

Fix permissions if needed:

bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/config.d/*

Step 6: Test with Debug Mode

Run SSH with maximum debug to see config loading:

bash
ssh -vvvG myserver 2>&1 | grep -i include

This shows which files are being processed:

bash
debug1: /home/user/.ssh/config line 1: Including configuration file /home/user/.ssh/config.d/work.conf
debug1: /home/user/.ssh/config.d/work.conf line 5: Applying options for myserver

Step 7: Verify Include Order

Remember that SSH config is first-match-wins. If you have:

``` # ~/.ssh/config Include config.d/*.conf

Host myserver HostName wrong.example.com ```

And in config.d/work.conf:

bash
Host myserver
    HostName correct.example.com

The included file is processed first, so correct.example.com wins. But if you put the Include after the Host block, the inline Host block wins.

Verify the Fix

Your Include directives work correctly when:

  1. 1.ssh -vvvG hostname shows "Including configuration file" messages
  2. 2.ssh -G hostname shows settings from included files
  3. 3.Hosts defined in included files connect properly
  4. 4.No syntax errors appear in debug output

Create a test file to verify:

```bash echo 'Host include-test HostName test.example.com' > ~/.ssh/config.d/test.conf

ssh -G include-test | grep hostname ```

You should see hostname test.example.com in the output.