ssh.md

SSH #

Secure Shell: an encrypted connection to a remote machine. Authenticate with a key pair instead of a password, then layer file transfer and tunnels on top of the same connection.

Connecting #

ssh user@host                      # connect (default port 22)
ssh -p 2222 user@host              # non-default port
ssh user@host 'uname -a; uptime'   # run a command and exit
ssh -v user@host                   # verbose, for debugging auth
ssh -J jump@bastion user@host      # hop through a bastion (ProxyJump)

Keys #

ssh-keygen -t ed25519 -C "you@email"     # generate a modern key pair
ssh-keygen -t rsa -b 4096 -C "you@email" # RSA if ed25519 is unsupported
ssh-copy-id user@host                    # install your public key on a host
ssh-keygen -p -f ~/.ssh/id_ed25519       # change a key's passphrase
ssh-keygen -lf ~/.ssh/id_ed25519.pub     # show the key fingerprint

# Keys live in ~/.ssh : id_ed25519 (private, keep secret) and .pub (public)

The config file #

# ~/.ssh/config  -- aliases and per-host options
Host prod
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host *.internal
    ProxyJump bastion
    ForwardAgent yes
ssh prod                           # uses everything defined above

The agent #

eval "$(ssh-agent -s)"             # start the agent in this shell
ssh-add ~/.ssh/id_ed25519          # load a key (caches the passphrase)
ssh-add -l                         # list loaded keys
ssh-add -D                         # remove all keys from the agent

Copying files #

scp file.txt user@host:/tmp/             # local -> remote
scp user@host:/var/log/app.log .         # remote -> local
scp -r dir/ user@host:/srv/              # recurse a directory
rsync -avz --progress dir/ user@host:/srv/   # faster, resumable, deltas
rsync -avz --delete src/ user@host:/dst/     # mirror (removes extras)

Tunnels & forwarding #

ssh -L 8080:localhost:80 user@host       # local: your :8080 -> remote :80
ssh -R 9000:localhost:3000 user@host     # remote: their :9000 -> your :3000
ssh -D 1080 user@host                    # dynamic SOCKS proxy on :1080
ssh -fN -L 5432:db.internal:5432 user@host   # background tunnel, no shell

Hardening (server side) #

# /etc/ssh/sshd_config -- then: sudo systemctl reload sshd
PasswordAuthentication no          # keys only
PermitRootLogin no                 # no direct root login
Port 2222                          # move off the default
AllowUsers deploy                  # allow-list accounts

Troubleshooting #

chmod 700 ~/.ssh; chmod 600 ~/.ssh/id_ed25519   # fix "permissions too open"
ssh -o StrictHostKeyChecking=accept-new user@host
ssh-keygen -R host                 # drop a changed host key (after a rebuild)
ssh -T git@github.com              # test auth without opening a shell

© 2026 anguishedturtle.comBit Night RunnerSupportPrivacy