termal.in

← Blog

The SSH flags you'll actually use (a practical cheat sheet)

· Termalin team sshcheat-sheetproductivitytutorial

ssh --help dumps forty flags in alphabetical order, which is the least useful way to learn them. You reach for flags by what you’re trying to do — connect as a different user, forward a port, hop through a bastion, debug a refusal — so here’s the same set organized by task, with a note on which ones to stop typing and put in your ssh_config instead.

The rule underneath all of it: flags are for one-offs; config is for permanence. Anything you pass twice belongs in the file.

Connection basics

The flags that answer “who, where, and with what key.”

  • -p <port> — connect to a non-standard port. ssh -p 2222 user@host. (Lowercase -p; uppercase -P is scp’s port flag, which trips everyone up once.)
  • -l <user> — the login user, an alternative to the user@ prefix. ssh -l deploy host equals ssh deploy@host; you’ll see -l in scripts and older docs.
  • -i <identity> — point at a specific private key. ssh -i ~/.ssh/work_ed25519 user@host. The most useful flag when auth fails: it forces the exact key instead of letting the agent guess.
  • -F <configfile> — use a different config file. ssh -F ./project.sshconfig web1, or -F /dev/null to ignore your personal config and test with zero customization.
  • -v / -vv / -vvv — verbosity, and the flag that ends most mysteries. One -v shows the auth methods tried and keys offered; -vvv shows the full handshake. When something fails, run it again with -vvv before you theorize.

The -o escape hatch

This is the flag worth understanding deeply, because it subsumes dozens of others. -o sets any ssh_config option inline. Anything you could write in ~/.ssh/config under a Host block, you can pass as -o Option=value — not a short list of blessed options, but the entire config vocabulary, available for a single connection.

A few that come up constantly:

ssh -o IdentitiesOnly=yes -i ~/.ssh/right_key user@host   # offer only this key
ssh -o StrictHostKeyChecking=accept-new user@host          # trust new hosts, still catch changes
ssh -o ServerAliveInterval=30 user@host                    # keepalive for a flaky link
ssh -o ProxyJump=bastion.example.com db.internal           # hop through a bastion inline

-o IdentitiesOnly=yes is the fix for Too many authentication failures when your agent offers six keys and a strict server cuts you off after five. -o StrictHostKeyChecking=accept-new is the sane middle ground — auto-trust a host you’ve never seen, but still scream if a known host’s key changes.

The point: you don’t need a special flag for each behavior. If you know the config directive, you know the flag — it’s -o Directive=value. Once you’re passing three or four every time, move them into config for good.

Forwarding and tunnels

The port-plumbing flags. The mental model — which side opens the port — gets its own read in SSH port forwarding explained; here’s the flag summary.

  • -L <local>:<host>:<port> — local forward. Open a port on your machine that tunnels to a destination reachable from the server. ssh -L 5432:localhost:5432 db.example.com brings a remote database to your 127.0.0.1:5432.
  • -R <remote>:<host>:<port> — remote forward. Open a port on the server that tunnels back to your side — the reverse-tunnel trick for reaching a machine behind NAT.
  • -D <port> — dynamic forward. A SOCKS proxy on your machine; destination chosen per connection. ssh -D 1080 jump.example.com, then point a browser at 127.0.0.1:1080.
  • -N — don’t run a remote command. Pair with any forward when you want only the tunnel and no shell.
  • -f — background ssh after it connects. Combine with -N for a fire-and-forget tunnel: ssh -fN -L 5432:localhost:5432 db.example.com.
  • -g — let other machines on your LAN use a local (-L/-D) forward, not just 127.0.0.1. A small exposure — you’re opening the tunnel to your whole network, so use it deliberately.

Jump hosts and the agent

Reaching the next hop, and the flag you should be cautious with.

  • -J <jumphost> — ProxyJump. Tunnel through a bastion and authenticate end-to-end from your laptop to the target. ssh -J bastion.example.com db.internal. The bastion only shuttles encrypted bytes; your key never lands on it — the right way through a gateway. Full case: ProxyJump: reach servers behind a bastion.
  • -A — agent forwarding. Exposes a socket on the remote host that proxies signing requests back to your local agent, so a process there can authenticate as you to the next server. Convenient and riskier than it looks: anyone with root on that host can borrow your identity while the session is open. Use -J for “reach the next hop” and keep -A for hosts you fully trust — the reasons are in agent forwarding is convenient and dangerous.

Between the two: -J gets your shell to a host behind the bastion without lending anyone your keys; -A lends your keys’ live use to the box you connected to. Not the same trade.

Session control

The small flags that fix specific annoyances.

  • -t — force a pseudo-terminal. Needed for a remote command that expects an interactive TTY: ssh -t host 'sudo systemctl status nginx' gives you a real terminal for the sudo prompt and colored output. Double it (-tt) to force one when there’s no local TTY.
  • -q — quiet mode. Suppresses warnings and banners; useful in scripts where you want only the command’s own output.
  • -C — request compression. A real win on slow, high-latency links; negligible or slightly negative on a fast LAN.
  • -o BatchMode=yes — never prompt. If auth would need a password or passphrase, fail immediately instead of hanging. This is what makes SSH safe inside cron and CI — a stuck prompt in an unattended script hangs forever.

The compact reference

FlagDoesssh_config equivalent
-p 2222Non-standard portPort 2222
-l user / user@Login userUser user
-i ~/.ssh/keySpecific identityIdentityFile ~/.ssh/key
-F fileAlternate config file— (this is the config)
-v-vvvVerbose / debugLogLevel DEBUG3
-o Opt=valAny config option inline(the option itself)
-L a:host:bLocal forwardLocalForward a host:b
-R a:host:bRemote forwardRemoteForward a host:b
-D 1080Dynamic (SOCKS) forwardDynamicForward 1080
-NNo remote commandRequestTTY no (+ no command)
-fBackground after connect— (one-off only)
-gOpen forward to your LANGatewayPorts yes
-J hostJump through a bastionProxyJump host
-AForward the agentForwardAgent yes
-tForce a TTYRequestTTY force
-qQuietLogLevel QUIET
-CCompressionCompression yes
-o BatchMode=yesNever promptBatchMode yes

The right column is the tell. Almost every flag has a config equivalent, and that’s the workflow: use the flag once to prove a connection works, then move the ones you’ll repeat into ~/.ssh/config so ssh web1 carries all of them with no flags at all. The flags with no config equivalent — -f, -F, the debug verbosity — are the genuinely one-off ones.

Where a client keeps the state for you

Flags and config both live in your dot-files, per machine, and that hurts at scale: settings copied across laptops by hand, tunnels re-run after every sleep, no way to see which of forty hosts is up. Termalin keeps the same facts a flag would carry — port, user, key, jump host, keepalives, saved local/remote/dynamic forwards — attached to the host as structured data, organized into folders and tags, synced across your machines end-to-end encrypted. It verifies each server on first connect, shows live status per host, and starts tunnels with the connection instead of a retyped command. The flags teach you what’s happening; a client stops you retyping them every morning.


Termalin is a free, cross-platform SSH client that stores per-host settings, keys and tunnels for you — download it, or read how it handles your keys safely.

Try it on one host.

Termalin is a fast SSH client for you — and your agents.

Free tier · 14-day Pro trial · pricing