TL;DR

  • Prefer rsync for anything bigger than a single file.
  • Avoid hardcoding IPs/users in scripts; use ~/.ssh/config hosts.
  • For “copy only if missing”, use rsync --ignore-existing or an SSH existence check.

SSH config first (recommended)

Put the boring parts into ~/.ssh/config:

Host myvps
  HostName example-vps-ip-or-domain
  User myuser
  Port 22
  IdentitiesOnly yes

Then you can use myvps: everywhere.

scp basics

Copy file from remote → local:

scp myvps:/etc/nginx/nginx.conf ./nginx.conf

Copy file from local → remote:

scp ./nginx.conf myvps:/tmp/nginx.conf

Copy directory (needs -r):

scp -r ./myfolder myvps:/tmp/myfolder

Custom port:

scp -P 2222 myvps:/var/log/app.log .

rsync patterns (better defaults)

Sync a folder (preserve times/permissions):

rsync -av ./myfolder/ myvps:/srv/myfolder/

Copy only new files (don’t overwrite):

rsync -av --ignore-existing ./myfolder/ myvps:/srv/myfolder/

Resume interrupted transfers:

rsync -av --partial --progress ./bigfile.iso myvps:/srv/

SSH “copy only if missing” (single file)

ssh myvps 'test -e /srv/file && echo \"exists\" || cat - > /srv/file' < ./file

Tunnels (quick reference)

Local forward (access remote service locally):

ssh -L 8080:127.0.0.1:8080 myvps

Dynamic SOCKS proxy:

ssh -D 1080 myvps