Skip to content

~/avetyan.com/cheatsheets

Cheat sheets

ssh cheat sheet

SSH keys, config, jump hosts, port forwarding, scp and sshd hardening: the commands and settings I use on every server.

5 min read


Keys

bash
# New key (Ed25519 is the default choice today)
ssh-keygen -t ed25519 -C "alice@laptop"

# Choose the file name with -f (default is ~/.ssh/id_<type>)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "alice@work"
ssh -i ~/.ssh/id_ed25519_work alice@host      # use it (or IdentityFile in ~/.ssh/config)

# Fingerprint of a key, to compare with what a server shows
ssh-keygen -lf ~/.ssh/id_ed25519.pub

# Change or add a passphrase
ssh-keygen -p -f ~/.ssh/id_ed25519

# Load the key into the agent once per session
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519
Key typeCommandNotes

OpenSSH has supported Ed25519 since 6.5 (2014). Since 9.5 (October 2023), ssh-keygen without -t creates an Ed25519 key instead of RSA. The OpenSSH developers chose it for its small public keys; it also signs without a per-signature random nonce, which ECDSA needs to get right every time.

ssh-copy-id

Appends your public key to ~/.ssh/authorized_keys on the server, creates ~/.ssh if needed and fixes its permissions. It logs in with your password (or another key) once to do that.

bash
ssh-copy-id alice@host                               # agent keys, else newest ~/.ssh/id*.pub
ssh-copy-id -i ~/.ssh/id_ed25519_work.pub alice@host # a specific key
ssh-copy-id -p 2222 alice@host                       # non-standard port
ssh-copy-id -o ProxyJump=bastion [email protected]     # any ssh -o option
ssh-copy-id -n alice@host                            # dry run: show what would be added
ssh -o PasswordAuthentication=no alice@host true && echo key works
FlagMeaning

Keys already on the server are skipped, so running it twice is safe. Where ssh-copy-id isn’t available (Windows, minimal images), do the same by hand:

bash
cat ~/.ssh/id_ed25519.pub | ssh alice@host \
  'umask 077; mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'

Connect

bash
ssh user@host
ssh -p 2222 user@host
ssh -i ~/.ssh/deploy_ed25519 deploy@host
ssh user@host 'df -h /'                 # run one command
ssh -t user@host 'sudo htop'            # command that needs a terminal
ssh -v user@host                        # debug: which key, which auth method

~/.ssh/config

Put hosts here once, then ssh db is all you type, and scp, rsync and git use it too.

~/.ssh/config
Host db
    HostName 192.0.2.11
    User alice
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host *.prod
    User admin
    ProxyJump bastion

Host *
    ServerAliveInterval 30
    AddKeysToAgent yes
    IdentitiesOnly yes

The first matching value wins, so put specific hosts above Host *.

Jump hosts

A jump host (or bastion) is the one hardened server that accepts SSH from outside; you reach every other server through it. That gives one place to enforce MFA, log admin sessions and close access, which is why PCI DSS and ISO 27001 audits usually expect one.

bash
ssh -J bastion [email protected]
ssh -J bastion1,bastion2 user@target

ProxyJump keeps your keys on your machine. Avoid ForwardAgent on hosts you don’t fully trust: root there can use your agent.

Port forwarding

bash
# Local: reach a remote service on localhost:5433
ssh -L 5433:localhost:5432 db

# Local through a host to something only it can reach
ssh -L 8080:192.0.2.20:80 bastion

# Remote: expose your local port 3000 on the server's port 9000
ssh -R 9000:localhost:3000 host

# SOCKS proxy for a browser
ssh -D 1080 bastion

# Tunnel only, no shell, in the background
ssh -fN -L 5433:localhost:5432 db

Copy files

bash
scp file.txt db:/tmp/
scp -r db:/var/log/app ./logs/
scp -P 2222 file.txt user@host:     # capital P for the port
sftp db

For directories and anything large, rsync -a over SSH is better: it resumes and copies only changes.

Multiplexing

Reuse one connection for every session to a host; repeated logins become instant.

~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m

Known hosts

bash
ssh-keygen -R host                   # forget a host after it's rebuilt
ssh-keyscan -t ed25519 host          # fetch a host key (verify it out of band)

A changed host key warning on a server that wasn’t rebuilt is exactly what the warning is for. Find out why before you remove the old key.

sshd hardening

/etc/ssh/sshd_config.d/10-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
AllowGroups ssh-users
MaxAuthTries 3
LoginGraceTime 20
X11Forwarding no
bash
sudo sshd -t && sudo systemctl reload ssh    # test the config, then reload

Keep your current session open and test a new login in a second terminal before you close it. The service is called ssh on Debian and Ubuntu and sshd on RHEL.

Keep in mind

  • Permissions: ~/.ssh 700, private keys 600, authorized_keys 600. sshd ignores keys with looser permissions.
  • ~. on a new line kills a hung session; ~? lists the other escapes.

Comments

Sign in with Google, GitHub or Facebook to comment.

Loading comments…