SSH on Mac: A Guide for People Who Are Tired of Googling the Same Commands
The first time I got “Permission denied (publickey)” I had no idea what it meant, so I just… retyped the same command. Three times. It did not work three times. For months after that I was googling the same handful of SSH commands over and over, every single time I needed to connect to something new. If that’s you right now, this is the guide I wish someone had handed me instead of a man page.
What SSH Actually Does
SSH (Secure Shell) is how you talk to a remote computer from your own. You type commands on your Mac, they run on the server, encrypted the whole way there. If you’ve ever deployed a website, poked around a VPS, or SSH’d into a Raspberry Pi at 1am because something broke — this is the tool doing the work.
Part 1: Making Your First Connection
Open Terminal (Cmd + Space, type “Terminal”). Then:
ssh username@server_address
For example:
ssh john@192.168.1.100
The first time you connect to any server, you’ll get something like this:
The authenticity of host '167.235.62.3 (167.235.62.3)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
This looks alarming the first time. It isn’t. SSH just doesn’t recognize the server yet and wants you to confirm it. Type yes. Your Mac saves this to ~/.ssh/known_hosts, and you won’t see the prompt again for that server.
Part 2: SSH Keys, and Why Passwords Are the Worse Option
You can log in with a password. Most people who’ve used SSH for more than a week don’t, though — keys are faster and harder to crack.
Check if you already have keys:
ls -la ~/.ssh
Look for id_ed25519 and id_ed25519.pub. If they’re there, you’re already set. If Terminal says “No such file or directory,” generate a pair:
ssh-keygen -t ed25519 -C "your_email@example.com"
Hit Enter to accept the default save location. It’ll ask for a passphrase — more on that in a second, but say yes to it.
This gives you two files:
id_ed25519— your private key. This one doesn’t leave your machine, ever.id_ed25519.pub— your public key. This is the one you hand out.
To look at your public key:
cat ~/.ssh/id_ed25519.pub
It’ll print something like ssh-ed25519 AAAAC3Nz... your_email@example.com. That’s the string you paste into a server’s authorized keys.
Part 3: Passphrases (Don’t Skip This)
A passphrase encrypts your private key on disk. Without one, anyone who gets a copy of that file — off a stolen laptop, a bad backup, whatever — can use it to log into every server you’ve added it to. With one, that file is useless to them without also knowing your passphrase.
The usual objection is “I don’t want to type this every time.” Fair, but macOS already solves it: Keychain remembers the passphrase after you enter it once, so in practice you’re typing it right after a restart and basically never after that.
Check whether your key has a passphrase:
ssh-keygen -y -f ~/.ssh/id_ed25519
If it asks you for a passphrase before showing the public key, you’re covered.
Change it:
ssh-keygen -p -f ~/.ssh/id_ed25519
Old passphrase, then new one twice.
You can actually see where it’s stored — open Keychain Access, search “ssh,” and there’s the entry, sitting in the same encrypted store as your other passwords.
Part 4: Key Auth vs. Password Auth
Key-based: your public key sits in ~/.ssh/authorized_keys on the server, your private key proves you’re you, no password typed at all. Set it up with:
ssh-copy-id username@server_address
or, if that’s not available:
cat ~/.ssh/id_ed25519.pub | ssh username@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Password-based: you type a username and password, same as logging into a website. It works, but it’s weaker, and a fair number of servers — especially anything production — turn it off entirely. That’s what’s behind the “Permission denied (publickey)” error: the server is telling you it will only accept a key, and yours isn’t on the list yet.
Part 5: Never Type the Full Command Again
ssh username@192.168.1.100 -p 2222 gets old around the third time you type it. Fix it with a config file:
nano ~/.ssh/config
A basic entry:
Host myserver
HostName 192.168.1.100
User john
IdentityFile ~/.ssh/id_ed25519
Now ssh myserver does the same thing as the long version.
Custom port:
Host webserver
HostName example.com
Port 2222
User admin
IdentityFile ~/.ssh/id_ed25519
Password-only server:
Host oldserver
HostName 82.112.239.96
Port 21098
User username
PreferredAuthentications password
One thing worth saying directly: don’t put your actual password in that file. PreferredAuthentications password just tells SSH which method to try — it still prompts you for the password at connection time.
You can also set defaults that apply everywhere:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
Put it together and a real config might look like this:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
Host production
HostName 203.0.113.10
User deploy
Host dev
HostName dev.mycompany.com
User developer
Host client-server
HostName 82.112.239.96
Port 21098
User clientuser
PreferredAuthentications password
ssh production, ssh dev, ssh client-server — done.
Part 6: Moving Files Around
scp, for one-off transfers:
scp file.txt myserver:/home/user/
scp myserver:/home/user/file.txt ~/Desktop/
scp -r my-folder/ myserver:/home/user/
rsync, when you’re moving a lot or doing it repeatedly:
rsync -avz local-folder/ myserver:/remote/path/
-a preserves permissions and timestamps, -v shows you what’s happening, -z compresses in transit.
Your config shortcuts work here too — scp important.pdf production:~/uploads/ is all it takes.
Part 7: When It Doesn’t Connect
“Connection refused” — the server’s down, a firewall’s in the way, or you’ve got the wrong port. Check the port first; it’s usually the port.
“Permission denied (publickey)” — your key isn’t on the server, or the server only takes keys and you tried a password. Add your public key to ~/.ssh/authorized_keys on the server.
“Connection timeout” — wrong IP, server’s offline, or your network’s the problem.
For anything else, run it in verbose mode and read what it actually says:
ssh -v myserver
Part 8: Keeping This Secure
Private key stays on your machine. Public key goes on servers. Passphrase protects the private key if your machine gets stolen or backed up somewhere it shouldn’t be. That covers most of it.
A couple things I’d actually bother with:
- Never send your private key over email, Slack, or any cloud storage. If you need it on a second device, AirDrop it or use an encrypted drive — or just generate a fresh key pair for that device instead. Separate keys per device means one stolen laptop doesn’t compromise everything.
- If you run the server yourself, turning off password authentication entirely is worth doing once you’re comfortable with keys. Changing the default port and setting up fail2ban cuts down on the constant background noise of bots trying to log in.
Part 9: A Few Things That Come In Handy Later
Run one command without staying logged in:
ssh myserver "ls -la /var/www"
Reach a service on the server as if it were running locally:
ssh -L 8080:localhost:80 myserver
Now localhost:8080 on your Mac points at port 80 on the server.
Stop SSH from silently dropping the connection when you’re idle:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
Different keys for different servers:
Host work-server
HostName work.example.com
IdentityFile ~/.ssh/work_key
Host personal-server
HostName personal.example.com
IdentityFile ~/.ssh/personal_key
Cheat Sheet
ssh username@server # connect
ssh myserver # connect via config shortcut
ls -la ~/.ssh # check for keys
ssh-keygen -t ed25519 -C "email@example.com" # generate a key
cat ~/.ssh/id_ed25519.pub # view public key
cat ~/.ssh/id_ed25519.pub | pbcopy # copy public key to clipboard
ssh-keygen -p -f ~/.ssh/id_ed25519 # change passphrase
nano ~/.ssh/config # edit config
scp file.txt myserver:/path/ # copy file to server
scp myserver:/path/file.txt ~/Desktop/ # copy file from server
ssh -v myserver # debug a connection
exit # disconnect
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
Host nickname
HostName actual.server.address
User username
Port 22
Where This Leaves You
Once you’ve got one key pair and a couple of servers in your config, ssh myserver is the whole interaction. That’s it. Everything that felt arcane the first week was really just three or four ideas wearing different outfits.
If I had to boil it down to one rule: keep the private key on your machine, use a passphrase, don’t overthink the rest.