~/.ssh/config turns ssh -i ~/.ssh/id_ed25519 bk3ssh@localhost into ssh web1, and scp, rsync 13,872 and VS Code 550 Remote-SSH read it too. Like sshd, the client keeps the first value it finds for each option, so specific Host blocks go first and the Host * defaults last:
Host web1
HostName localhost
User bk3ssh
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host app1
HostName 127.0.0.1
User bk3ssh
ProxyJump web1
Host *
AddKeysToAgent yes
ControlMaster auto
ControlPath ~/.ssh/cm-%C
ControlPersist 10mapp1 stands for a private server only web1 can reach. ProxyJump has web1 open a TCP connection onward and runs a second, end-to-end encrypted session through it, so HostName resolves on the jump host. ssh -G prints the settings a host would get:
ssh -G app1 | grep -E '^(user|hostname|proxyjump) '
ssh app1 'echo "arrived from: $SSH_CONNECTION"'user bk3ssh hostname 127.0.0.1 proxyjump web1 arrived from: 127.0.0.1 38356 127.0.0.1 22
With ControlMaster, later connections reuse the first one's session: a second ssh web1 true took 0.129 s instead of 0.741 s here. ssh -O exit web1 closes it. ssh-agent holds decrypted keys in memory: start it with eval "$(ssh-agent -s)", load a key with ssh-add, list keys with ssh-add -l. Since OpenSSH 10.1 23,707 its socket lives under ~/.ssh/agent/, not /tmp. On Windows the agent is a service that ships disabled.