How to Use the SSH Config File: The Beginner's Guide (Aliases, Keys, Jump Hosts)

CodexFuse Team · 2026-11-04T05:16:41.825Z · 12 min read min read

What Is the SSH Config File, Exactly?

The SSH config file is a plain-text file on your own computer that tells the OpenSSH client how to connect to each of your servers — the hostname, username, port, and private key for every destination — so you type ssh prod instead of ssh -i ~/.ssh/prod_key -p 2222 [email protected]. It lives at ~/.ssh/config, applies to every new connection, and is read not only by ssh but also by scp, sftp, and rsync running over SSH. If you manage servers by hand today, this one file is the single biggest productivity upgrade available to you.

Your first host alias takes about two minutes:

  1. Create the file. Run mkdir -p ~/.ssh && touch ~/.ssh/config, then lock it down with chmod 700 ~/.ssh && chmod 600 ~/.ssh/config (the SSH client demands strict permissions — more on that below).
  2. Add a Host block. Open ~/.ssh/config and write a stanza: Host prod on one line, then the details indented beneath it.
  3. Fill in HostName, User, and Port. HostName is the real server address; User and Port are what you used to type by hand.
  4. Point at your key. Add IdentityFile ~/.ssh/prod_ed25519 so the right private key is offered automatically.
  5. Connect. Type ssh prod. The client matches your alias, applies the block, and logs you in.

If you would rather generate config entries through a form than write them by hand, our free SSH config generator builds ~/.ssh/config entries with hosts, users, and key paths you can copy straight into the file. And if you manage dozens of connections and want a friendlier SSH session manager, the LazySSH beginner guide covers the tool that sits on top of this same config file — this page is the foundation it all rests on.

SSH Client Config vs Server Config: What's the Difference?

Three different files share the "ssh config" name, and mixing them up is the most common beginner mistake. ~/.ssh/config configures your SSH client — the program you run to connect outward. It cannot change anything on any server; there is no documented mechanism by which client settings reach the SSH daemon. The server reads exactly one file: /etc/ssh/sshd_config.

FileWho it configuresWhat it controls
~/.ssh/configYour client, per userAliases, keys, ports, jump hosts for outgoing connections
/etc/ssh/ssh_configYour client, system-wideDefaults for all users on this machine (must be world-readable)
/etc/ssh/sshd_configThe server daemonListening ports, who may log in, authentication policy

This guide covers only the first two — client configuration. Editing ~/.ssh/config never changes how any remote server listens or authenticates users, and nothing you change on a server ever writes to your ~/.ssh/config. Keep this separation straight and the rest of the guide clicks into place.

How Do I Create My SSH Config File?

The per-user client file lives at ~/.ssh/config, and OpenSSH is strict about its permissions. The man page states it plainly: "Because of the potential for abuse, this file must have strict permissions: read/write for the user, and not writable by others." In practice that means chmod 700 ~/.ssh and chmod 600 ~/.ssh/config — those exact octals are the common convention that satisfies the rule, not a documented requirement, but they are the pair every guide and every tool expects.

Get this wrong and SSH tells you immediately: the client aborts the connection with a "Bad owner or permissions on ~/.ssh/config" error, enforced by a runtime check that the file is owned by you (or root) and not writable by anyone else. Notice the asymmetry the OpenBSD docs describe: a private key with loose permissions is silently ignored — SSH just skips it — while a bad config file aborts the whole connection. If SSH suddenly refuses every server after you edited something, check permissions before you check anything else.

If you are starting from zero and the ~/.ssh directory does not exist yet, most of these servers are the VPS hosting kind — a remote Linux box you rent and administer yourself, which is exactly where SSH config pays off.

How Do I Set Up an SSH Host Alias?

A host alias is a nickname you type instead of the full connection details. The file is organized into Host blocks (stanzas): each begins with a Host line, followed by indented options that apply when you type that name. Comments start with #, options are separated from their values by whitespace, and keywords are case-insensitive — indentation is purely cosmetic.

Host prod
    HostName 203.0.113.50
    User ubuntu
    Port 2222
    IdentityFile ~/.ssh/prod_ed25519

Now ssh prod connects to 203.0.113.50 as ubuntu on port 2222 using the prod_ed25519 key. The critical trap, straight from the man page: Host patterns match the hostname you typed on the command line, not the value of HostName. You type prod, so the Host prod block matches; the real address inside is just where the connection goes.

A second rule matters from the moment you write your second block: the first obtained value wins. For each directive, SSH uses the first value it finds while scanning your file top to bottom. That is why every guide ends with the man page's own ordering advice — "more host-specific declarations should be given near the beginning of the file, and general defaults at the end" — with the catch-all Host * block sitting last. This is backwards from most config formats you have seen, so commit it to memory now.

How Do I Use Different SSH Keys for Different Servers?

Point each Host block at its own key with IdentityFile, and the client offers exactly the right key for each server — no more -i flags, no more "wrong key" authentication failures. If you do not have keys yet, our free SSH key generator creates server-ready key pairs in the browser, and when keys get stale, our guide on how to rotate SSH keys covers the replacement cycle.

Host work-github
    HostName github.com
    User git
    IdentityFile ~/.ssh/work_ed25519
    IdentitiesOnly yes

Host home-server
    HostName 198.51.100.10
    User pi
    IdentityFile ~/.ssh/home_ed25519
    IdentitiesOnly yes

Two subtleties here carry the whole section. First, IdentityFile is the one directive that appends instead of replacing: multiple IdentityFile lines all add to the list of identities tried in sequence, which the man page flags as "behaviour [that] differs from that of other configuration directives." Second, IdentitiesOnly yes exists for the moment your SSH agent is loaded with many keys: by default the agent offers all its loaded identities, and IdentitiesOnly tells SSH to offer only the configured ones — its documented purpose is precisely "situations where ssh-agent offers many different identities."

How Do I Change the SSH Port or Username?

Non-default ports and per-server usernames are the two most common options after the key. Port sets the remote port (the default is 22), and User sets the login name, so a hardened VPS listening on port 443 with a deploy account becomes a two-line block:

Host deploy-box
    HostName 192.0.2.44
    User deploy
    Port 443

These directives participate in the same first-match-wins game as everything else, so a Port 443 in your specific Host deploy-box block beats a Port 22 in a general Host * block below it. And because scp, sftp, and rsync all run through the same SSH client under the hood, scp file deploy-box:/backups picks up the alias, user, port, and key with zero extra flags.

How Do I Set Defaults for Every Host with Wildcards?

A Host * block at the end of your file applies its options to every connection — the shared baseline your specific hosts inherit. Patterns support * (matches zero or more characters) and ? (matches exactly one character), and a leading ! negates a pattern, so Host *.internal !bastion.internal covers the internal fleet except the bastion itself.

Host *.internal
    User ops
    IdentityFile ~/.ssh/internal_ed25519

Host *
    ServerAliveInterval 15
    ServerAliveCountMax 3
    AddKeysToAgent yes

The Host * block above sends a keepalive through the encrypted channel every 15 seconds of silence and gives up after 3 unanswered pings — about 45 seconds of dead air before SSH declares the connection lost, the man page's own example. AddKeysToAgent yes quietly loads your keys into ssh-agent on first use instead of asking you to run ssh-add by hand. If your file grows beyond a screenful, the Include directive (added in OpenSSH 7.3) splits it up — Include ~/.ssh/config.d/* pulls in every matching file in lexical order, with relative paths resolving to ~/.ssh, and included files get the same strict permission check.

How Do I Connect Through a Jump Host?

When a private server is reachable only through a bastion, ProxyJump tunnels your connection there automatically — one alias, one command, no manual two-hop dance. List multiple proxies separated by commas and SSH visits them sequentially, and if your command line used to say ssh -J bastion, that -J flag is the shortcut for this same directive:

Host db-private
    HostName 10.20.30.40
    User dba
    ProxyJump bastion.example.com

Host db-deeper
    HostName 10.99.0.5
    User dba
    ProxyJump [email protected]:2222,db-gateway

ProxyJump arrived in OpenSSH 7.3 (released 2016-08-01), so any remotely modern system has it — scp and sftp learned the matching -J flag in OpenSSH 8.0. The man page buries two real traps here. First, the destination host's config is not generally applied to jump hosts — your bastion needs its own Host block for its key and user. Second, ProxyJump competes with the older ProxyCommand: "whichever is specified first will prevent later instances of the other from taking effect," and combined with first-match-wins, a stale ProxyCommand in an early matching block silently kills a ProxyJump you added later.

Power users chaining many hops by hand eventually want a visual session manager — that is exactly what LazySSH is for, and it reads this same config file, so everything on this page carries over.

How Do I Check What SSH Will Actually Use?

Before you connect to a production box with a config you just hand-edited, ask SSH to show its work. ssh -G prod prints the complete effective configuration after evaluating every Host and Match block — then exits without connecting. Pipe it through grep to spot-check one directive:

ssh -G prod | grep -E '^(hostname|user|port|identityfile|proxyjump) '

When the output surprises you, the problem is almost always block order (remember: first match wins) or a wildcard pattern matching a name you did not intend. For connection-level debugging, ssh -v prints debugging messages about progress — "helpful in debugging connection, authentication, and configuration problems" per the man page — with up to three -v flags for more detail. To test an experimental config without touching your real one, ssh -F ~/test-config prod reads an alternative file; the system-wide /etc/ssh/ssh_config is then ignored, and -F none reads no config files at all.

Which Other Directives Are Worth Knowing?

Once the basics are fluent, a handful of directives solve the annoyances every SSH user eventually hits. Keep a reference table nearby:

DirectiveWhat it solves
ControlMaster auto + ControlPath ~/.ssh/sockets/%CReuses one network connection for many sessions (multiplexing) — second ssh to the same host connects instantly
LocalForward 8080 localhost:80Forwards a local port over the secure channel to a service on the remote host
ForwardAgent yesForwards your local agent to the remote machine — enable with caution; anyone who can bypass file permissions for the agent socket on the remote host can use (though never extract) your loaded keys
StrictHostKeyChecking accept-newAuto-accepts unknown host keys but still aborts on changed ones (middle ground between ask and the dangerous no)
Match host *.staging user ciApplies following directives only when conditions match — finer control than Host patterns
PreferredAuthentications publickey,passwordForces the authentication method order the client tries (default tries gssapi, hostbased, publickey, keyboard-interactive, then password)
LogLevel VERBOSEPermanent verbosity for a troublesome host (default is INFO; DEBUG1–DEBUG3 get progressively louder)

The full list runs to over a hundred keywords — type man ssh_config in any terminal to browse them — but these seven plus the ones from the earlier sections cover the overwhelming majority of real-world configs. As of this writing the current OpenSSH release is 10.6 (released 2026-10-06), so if a directive you read about online behaves oddly, check that your client is not years behind.

Sources

Every technical claim above was verified against pages fetched for this article in November 2026: the ssh_config(5), ssh(1), scp(1), sftp(1), and sshd_config(5) manual pages on man.openbsd.org; the official OpenSSH release notes on openssh.com; the rsync(1) manual on download.samba.org; and the LinuxPanda, Tutorials.Technology, dev.to, Linuxize, and Teleport guides that currently occupy page 1 for this query. Man-page quotations are verbatim.

Frequently Asked Questions

Where is the SSH config file on Linux and macOS?

Your personal file is ~/.ssh/config — the man page calls it "the per-user configuration file" that "is used by the SSH client." The system-wide defaults live at /etc/ssh/ssh_config (world-readable), and the server daemon reads only /etc/ssh/sshd_config. Create ~/.ssh/config yourself if it does not exist; nothing breaks by adding it.

Why does SSH say "Bad owner or permissions"?

The client aborts when ~/.ssh/config is not owned by you (or root) or is writable by anyone else — the man page's "strict permissions" rule enforced as a hard runtime check. Fix it with chmod 700 ~/.ssh and chmod 600 ~/.ssh/config. Note the contrast: a too-open private key is silently ignored, but a too-open config file kills the connection entirely.

Does the SSH config file work with scp, sftp, and rsync?

Yes. All three route their connections through the same OpenSSH client, so aliases, keys, ports, and ProxyJump all apply — scp backup.tar.gz prod:/backups just works, and scp/sftp even accept a -J jump flag (added in OpenSSH 8.0). Since OpenSSH 9.0, scp additionally uses the SFTP protocol for transfers by default.

Should I use ProxyJump or ProxyCommand?

Use ProxyJump — it is the modern one-line form (added in OpenSSH 7.3) that covers nearly every jump-host case, with comma-separated hosts for multiple hops. ProxyCommand is the older, more flexible mechanism; the two compete, and whichever is specified first silently disables the other, so do not set both for the same host.

Will my ~/.ssh/config change anything on the server?

No. Client configuration only affects the connections you initiate from your machine. Nothing in ~/.ssh/config reaches the server daemon, which reads exclusively from /etc/ssh/sshd_config — you would need to log into the server and edit that file (with root privileges) to change server behavior.

Featured on Twelve Tools Hunt for Tools Featured on LaunchBuff Launch Llama Tools Launch your MCP Top Web Development Companies in the US - OnToplist.com Designer Listings Listed on SeeWhatNewAI