Cheat Sheet

SSH Commands

ssh is the OpenSSH client that ships with Linux, macOS, and Windows 10 and later. This sheet covers connecting, running remote commands, copying files, keys, the config file, tunnels, and the flags you reach for when a connection misbehaves.

Last updated August 29, 2026

Connecting

Port 22 is the default. Every option below can also live in the config file so you only type .

CommandWhat it does
Log in as user on host (a name or an IP)
Log in with your local username
Non-standard port (lowercase p; scp and sftp use uppercase P)
Use a specific private key
Username as a flag instead of user@host
Go through a jump host (bastion) first
Jump host with its own user and port
Send a keepalive every 60 seconds so an idle session is not dropped
Accept a never-seen host key without a prompt, still refuse a changed one
Give up after 5 seconds instead of the system default
Compress traffic, useful on slow links
Force IPv4 ( forces IPv6)
Scripted password login (separate package; the password lands in history, use a key instead)
Print the client version
Log out (Ctrl+D on an empty prompt does the same)
Kill a hung session; type it at the start of a line ( lists the other escapes)

If the connection is refused or hangs, check the port from outside with the SSH port checker, then see Connection refused or Could not resolve hostname.

Remote Commands

CommandWhat it does
Run one command and disconnect
Several commands, quoted as one string
Force a terminal so sudo can ask for a password
Run a local script on the remote host
Save remote output to a local file
Stream a log until Ctrl+C
In double quotes, escape so the remote shell expands it; single quotes need nothing
Start a job that keeps running after you disconnect
Run in the background without ssh grabbing your terminal's input
Never prompt; fail instead (for cron and scripts)
After ssh returns: the remote command's exit code, or 255 if ssh itself failed

Copying Files

scp and sftp use the same keys, ports, and config aliases as ssh. Remote paths are written .

CommandWhat it does
Upload a file
Download a file to the current directory
Copy a directory
Non-standard port (uppercase P)
Use a specific key
Preserve timestamps and permissions
Copy between two servers through your machine
Limit bandwidth to 8000 Kbit/s
Config alias in place of user@host
Interactive session: , , , , ,
sftp on a non-standard port (uppercase P again)
Resumable sync for big trees; see the rsync cheat sheet
rsync over a non-standard port

Keys

CommandWhat it does
Generate a key pair at (the comment is just a label)
RSA key for old servers that reject ed25519
Key at a chosen path with no passphrase (automation)
Append your public key to the server's
Specific key and port
Manual ssh-copy-id where it is not installed
Print the public key from a private key
Change or remove the passphrase
Show the fingerprint
Permissions ssh insists on; a world-readable key is ignored
Cloud keys work as-is once locked down

Generate a key in the browser with the SSH key generator, check a key that refuses to work with the SSH key validator, and for PuTTY convert it with the PEM to PPK converter. If the server still says Permission denied (publickey), it is almost always permissions or the wrong key being offered.

Config File

turns a long command into . It needs . Build one with the SSH config generator.

Host prod
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/prod_ed25519
    IdentitiesOnly yes
    ProxyJump bastion

Host bastion
    HostName bastion.example.com
    User admin

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes
DirectiveWhat it does
The alias you type after ; applies to every host
Real address behind the alias
Username
Port
Key to offer
Offer only that key; fixes Too many authentication failures
Jump host, same as
Keepalive; fixes idle drops and Broken pipe
Give up after 3 missed keepalives
Agent forwarding for this host, same as
A tunnel that opens every time you connect
Load a key into the agent the first time it is used
Trust new hosts on first use, still refuse changed keys
Split the file (goes at the top)
Print the settings that apply to a host after all matching blocks merge
Use a different config file

Port Forwarding

Syntax is , where the destination is named from the SSH server's point of view, so means the server itself.

CommandWhat it does
Local: your reaches port 80 on host
Local: reach a database that only host can see
Remote: port 9000 on host reaches port 3000 on your machine
SOCKS proxy on local port 1080; point a browser or at it
Tunnel only, no shell
Tunnel in the background
Let other machines on your network use the local forward
Several tunnels, repeat the flag
Stop background tunnels
Close a shared master connection when is on

For to accept connections from outside the server, must be set in the server's . Confirm the far end is actually listening with the SSH port checker before you blame the tunnel.

Agent

The agent holds decrypted keys so you type the passphrase once per login.

CommandWhat it does
Start an agent in this shell
Load the default keys, prompting for passphrases
Load a specific key
List loaded keys ( prints the public keys)
Unload one key ( unloads all)
Load a key that expires after an hour
macOS: remember the passphrase in Keychain
Forward the agent so the remote host can use your keys, for on a server
Windows PowerShell (as admin): turn on the built-in agent

Known Hosts

CommandWhat it does
Remove a host's old key after a reinstall; fixes Host key verification failed
Same for a non-standard port
Check whether a host is in known_hosts
Pre-trust a host in scripts (compare the fingerprint first)
On the server: print its fingerprint to compare against the warning
Skip the check entirely; throwaway lab machines only
Do not record the host at all (pair with the line above)

X11 Forwarding

CommandWhat it does
Forward X11 so GUI programs on the server open on your screen
Trusted X11 with fewer restrictions; try it when gives errors
Quick test

The server needs in and the package. macOS needs XQuartz, Windows needs VcXsrv or the PuTTY setup in Cannot open display.

Debugging

CommandWhat it does
Show the handshake, which keys are offered, and where it stops
Maximum detail
Print the effective config for a host
Test a key against GitHub without asking for a shell
Stop the agent from offering every key it holds
List supported key types (, for the others)
Talk to an old server that only offers ssh-rsa
Is the port open at all (or use the SSH port checker)
On the server: watch the login log ( on RHEL and Fedora)
On the server: check syntax before restarting
On the server: apply config changes ( on RHEL and Fedora)
ErrorFix
ssh permission denied publickey
ssh connection refused
ssh host key verification failed
or ssh broken pipe
ssh too many authentication failures
ssh could not resolve hostname

Gotchas

  • ssh takes for the port, scp and sftp take . Lowercase on scp means preserve timestamps, and the copy quietly goes to port 22.
  • There is no password flag. If a script needs one, that is , and the better answer is a key plus .
  • A private key readable by anyone else is silently skipped. wants 700, keys and want 600, and the home directory must not be group-writable.
  • Single-quote remote commands. In double quotes your local shell expands and before ssh sends anything.
  • Closing the terminal kills whatever the session was running. Start long jobs inside tmux or under .
  • A background tunnel started with outlives the terminal. finds it when a port is unexpectedly busy.
  • On Windows, in PowerShell is OpenSSH and reads . PuTTY keys do not work with it; convert with the PPK to PEM converter, or stick with the PuTTY commands instead.

SSH Cheat Sheet FAQ

How do I run a command on a remote host over SSH without opening a shell?
Put the command after the host: ssh user@host 'uptime' runs it, prints the output, and disconnects. Quote the whole thing in single quotes so your local shell does not expand $ or * before it leaves your machine. Anything that needs a terminal, such as sudo asking for a password or an editor, needs -t: ssh -t user@host 'sudo systemctl restart nginx'. To run a local script remotely without copying it, use ssh user@host 'bash -s' < script.sh. The exit code you get back is the remote command's, so ssh user@host 'test -f /etc/nginx/nginx.conf' works as a check in scripts.
Can I pass a username and password in one ssh command?
Not with ssh itself. There is no password flag, on purpose: ssh reads the password from the terminal so it never lands in shell history or the process list. The username goes in the command as ssh user@host or ssh -l user host. If a script absolutely must supply a password, install sshpass and run sshpass -p 'secret' ssh user@host, or better, sshpass -f pwfile ssh user@host. The real fix is a key: ssh-keygen -t ed25519, then ssh-copy-id user@host, and the password prompt goes away for good.
Why does my ssh command fail with exit code 255?
255 means ssh itself failed before your command ran: it could not resolve the host, the connection was refused or timed out, or authentication failed. Any other code is passed through from the remote command, so exit 1 or 127 is your command's problem, not ssh's. Rerun with ssh -v to see which step broke; the message right before it gives up is the one to search. Connection refused, Permission denied (publickey), Host key verification failed, and Could not resolve hostname each have their own fix page linked in the Debugging section above.
How do I stop an SSH session from disconnecting when idle?
Add ServerAliveInterval 60 and ServerAliveCountMax 3 to ~/.ssh/config under Host *. The client then sends a probe every 60 seconds, which keeps NAT routers and firewalls from dropping the idle connection, and gives up only after three missed replies. For a single connection, pass -o ServerAliveInterval=60 on the command line. If the session still drops, for example on Wi-Fi or a laptop that sleeps, run long jobs inside tmux so they survive the disconnect and you can reattach with tmux a. The Broken pipe fix page covers the server-side settings too.
How do I remove a host from known_hosts?
ssh-keygen -R hostname deletes every entry for that name or IP from ~/.ssh/known_hosts and keeps a backup as known_hosts.old. Use the same spelling you connect with; a host known as both a name and an IP needs two runs, and a non-standard port is written as ssh-keygen -R '[hostname]:2222'. You need this after a server is reinstalled or replaced, because its host key changes and ssh refuses to connect with Host key verification failed. If nothing was reinstalled and the key still changed, ask whoever runs the server before you delete anything.

Related cheat sheets