Cheat Sheets › SSH

SSH In Depth

Logging in to your servers safely from your Mac: keys, the config file, adding keys to EC2, and fixing problems. Basic ssh is on the Top 25 sheet.

READ-ONLY only looks; safe CHANGES THINGS be careful ON YOUR MAC type it in Terminal on your Mac ON THE SERVER type it after you've logged in to the server Amazon Linux 1Ubuntu 24.04 boxes show what differs $ = you type this

The basics

#1How SSH keys work

An SSH key comes as a pair of files that belong together, like a key and the lock it opens.

YOUR MAC folder ~/.ssh key-name PRIVATE: never share key-name.pub PUBLIC: safe to share copy the .pub once, at setup EC2 SERVER your login's ~/.ssh folder authorized_keys one public key per line "Let in anyone whose private key matches a line here."
The pieces
Private keyStays on your Mac (or in 1Password). Anyone who gets a copy can log in as you. Never email it, paste it in chat, or put it on a server.
Public keyThe .pub file. Safe to share. You put it on each server you want to log in to.
authorized_keysA file on the server listing the public keys allowed in. One line per key.
PassphraseA password that protects the private key file itself. If the file is stolen, it's useless without it.
Where your AWS .pem files fit in

When you launch an EC2 server, AWS can create a key pair for you. The .pem file you download is the private half; AWS puts the public half into the server's authorized_keys. A key you make yourself (next section) works exactly the same way, but you control it and can use one key for every server.

MOODLE NOTEAnyone else who logs in to your servers, like your hosting vendor, should use their own key, added as a separate line in authorized_keys. Then you can remove one person's access without changing anyone else's (section 6).
↑ Back to top

#2Make your own key

CHANGES THINGSON YOUR MAC

Give each key a name that tells you what it's for, so you can pick out the right one later in ~/.ssh, in 1Password, and in a server's authorized_keys. (1Password can also create keys for you; see section 3.)

Step 1: choose a name
  • Describe what it's for: a client, a group of servers, or a purpose. For example client-a, moodle-servers, or multipass-vms.
  • Lowercase letters, numbers, and dashes. No spaces.
  • On this sheet the name is shown as key-name. Replace it with your own name in every command.
Step 2: make sure that name isn't taken (read-only)
ls -la ~/.ssh
  • If a file with your chosen name is already there, pick a different name. Using the same name would replace that key.
  • No such file or directory = you have no keys yet. That's fine; go on.
Step 3: make the key
ssh-keygen -t ed25519 -f ~/.ssh/key-name -C "key-name" Generating public/private ed25519 key pair. Enter passphrase (empty for no passphrase): ← type a passphrase Enter same passphrase again: ← type it again Your identification has been saved in /Users/me/.ssh/key-name Your public key has been saved in /Users/me/.ssh/key-name.pub The key fingerprint is: SHA256:k3Xr9…Qe2w key-name The key's randomart image is: (a little box of symbols)

No Copy button on purpose: type it with your own name in both places.

What it means
-t ed25519The key type. Modern, short, and strong. Works with Amazon Linux 1, Ubuntu 24.04, and AWS.
-f ~/.ssh/key-nameThe file name. Makes two files: key-name (private) and key-name.pub (public). Without -f, every key gets the same default name, id_ed25519.
-C "key-name"A label stored at the end of the public key. Using the same name means you can tell whose key is whose in a server's authorized_keys.
PassphraseUse one. You won't type it every time; 1Password or your Mac remembers it (section 3). Nothing shows on screen as you type; that's normal.
fingerprintA short ID for the key. Useful for checking which key is which. The randomart box can be ignored.
⚠ CAREFULIf it asks Overwrite (y/n)?, answer n. A key with that name already exists, and replacing it locks you out of every server that trusts the old one. Run it again with a different name.
Step 4: see your public key, or copy it to the clipboard
cat ~/.ssh/key-name.pub ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM…long string…Qx7 key-name
pbcopy < ~/.ssh/key-name.pub
  • The public key is one long line: type, the key itself, then your label.
  • pbcopy is a Mac command that puts it on the clipboard, ready to paste. Note it's the .pub file, never the private one.
GOOD TO KNOWA key with its own name isn't used automatically. ssh only tries keys with the default names unless told otherwise, so each server's entry in ~/.ssh/config names the key it uses (section 4). That's also what makes named keys easy to keep straight.
IN 1PASSWORDGive the SSH Key item the same name as the file, so the file, the 1Password item, and the label in authorized_keys all match.
↑ Back to top

#3Store & protect your keys

CHANGES THINGSON YOUR MAC

Keys live in the hidden .ssh folder in your home folder (~/.ssh). ssh refuses to use keys that other people on the computer could read, so the permissions matter.

What belongs in ~/.ssh
FileWhat it isPermission
~/.ssh (the folder)Holds everything below700 (only you)
key-nameA private key you made (one per name)600 (only you read/write)
key-name.pubIts public key644 (fine for others to read)
client1.pem etc.Private keys AWS made for you400 (only you, read-only)
configYour server shortcuts (section 4)600
known_hostsServers you've visited before (section 6). ssh manages it.644
Set the permissions in one go
chmod 700 ~/.ssh && chmod 600 ~/.ssh/key-name && chmod 400 ~/.ssh/*.pem
  • && means "then, if that worked, do the next one."
  • No output = done. No matches found: *.pem just means you have no .pem files in that folder.
Seeing the folder in Finder

Folders starting with a dot are hidden. Either type open ~/.ssh in Terminal, or in Finder press Cmd+Shift+. (period) to show hidden files.

FULL STEP-BY-STEP SETUPSetting this up on a new Mac, or for someone else? Follow the 1Password for SSH sheet.
Using 1Password for your keys (your setup)

1Password stores each private key and hands it to ssh when you log in, after a Touch ID or password check. The keys are backed up with the rest of your vault and don't need to sit loose on your Mac.

  1. Add the key: in 1Password, New Item › SSH Key. Import an existing key file, or generate a new ed25519 key there.
  2. Put it in your Personal vault (called Private on some accounts). By default the SSH agent only looks there. A key in any other vault is ignored.
  3. Turn on the agent once: Settings › Developer › Use the SSH Agent.
  4. Point each server entry at 1Password in your config file. That's section 4.
⚠ WRONG VAULT = MISLEADING ERRORIf the key isn't in Personal/Private, ssh doesn't say so. Instead it complains UNPROTECTED PRIVATE KEY FILE about your .pub file, then Permission denied. Don't change that file's permissions; move the key to the right vault.
The other option: Mac Keychain

Built in, nothing to install. The key stays as a file in ~/.ssh, and your Mac remembers its passphrase after ssh-add --apple-use-keychain ~/.ssh/key-name. Fine for one or two keys, but you have to back the files up yourself.

⚠ CAREFULIf your only copy of a private key is lost, you can't log in with it again. Keep a backup somewhere safe before you start relying on a key. (Lockout recovery is in section 6.)
MOODLE NOTEYour AWS .pem files are the keys to client servers. Import each into 1Password, named after the client. Keep the original files until every server that uses them logs in through 1Password; then decide whether to delete them. Private keys on the Desktop may be copied to iCloud if "Desktop & Documents" syncing is on.
↑ Back to top

Setting up

#4The ~/.ssh/config file

CHANGES THINGSON YOUR MAC

A plain text file of shortcuts, one entry per server. It lets you type ssh ubuntu1 instead of a long command with an address, user name, and key.

One entry, line by line
Host ubuntu1 HostName 203.0.113.10 User ubuntu IdentityFile ~/.ssh/key-name.pub IdentitiesOnly yes IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
Host ubuntu1The nickname you type: ssh ubuntu1. Starts a new entry.
HostNameThe server's real address.
UserWho to log in as: ec2-user on Amazon Linux 1, ubuntu on Ubuntu.
IdentityFileWhich key. With 1Password, point to the key's public half (.pub), so ssh asks 1Password for the matching private key.
IdentitiesOnly yesUse only that key. Without it, ssh may try every key in 1Password and the server hangs up after about 6 wrong ones (Too many authentication failures).
IdentityAgent "…"Where to ask for the key: 1Password. Copy it exactly; the spaces and quotes matter.
Rules of the file
  • Indenting is just for looks. Spaces or tabs, any amount.
  • A line starting with # is a note to yourself; ssh ignores it.
  • Several servers can share one key: give each entry the same IdentityFile.
  • Entries that still point to a private key file (like a .pem) keep working. You can switch servers to 1Password one at a time.

Switching one server to 1Password

One command per box. Run them one at a time.

Step 1 (first time only): back up the config file
cp ~/.ssh/config ~/.ssh/config.backup

No output = done. To undo any change later, copy it back: cp ~/.ssh/config.backup ~/.ssh/config.

Step 2: make the key's .pub file (skip if it already exists)
ssh-keygen -y -f /path/to/key-name > ~/.ssh/key-name.pub

Reads the private key and saves its public half. Use the real path from that entry's current IdentityFile line. No output = done.

Step 3: check it's the same key as in 1Password
ssh-keygen -lf ~/.ssh/key-name.pub

Compare the SHA256: part with the fingerprint field of the key in 1Password. The first 6 to 8 characters matching is enough. Also check the key is in your Personal/Private vault.

Step 4: edit that server's entry
nano ~/.ssh/config

In that entry, change IdentityFile to the .pub file, and add the IdentitiesOnly and IdentityAgent lines shown at the top of this section. Leave Host, HostName, and User alone. Save: Ctrl+O, Enter. Exit: Ctrl+X.

Step 5: test it
ssh ubuntu1

A 1Password window asks to allow ssh; approve it, and you're in. Type exit to log out. If it fails, see Troubleshooting.

MOODLE NOTEName each Host after the client, and add a # note above it (for example # Client: Example School, Moodle 4.1, Amazon Linux 1). With 25 servers, the config file becomes a handy directory of your whole fleet.
↑ Back to top

#5Put your key on an EC2 server

CHANGES THINGSON YOUR MACON THE SERVER

To log in with your key, the server needs your public key in its authorized_keys file. How you get it there depends on whether the server is new or already running.

A. New server: give AWS your public key, pick it at launch

  1. Once per AWS region: in the AWS console, go to EC2 › Key Pairs › Actions › Import key pair.
  2. Give it a name you'll recognize, and paste in your public key (the one line from your .pub file; pbcopy < ~/.ssh/key-name.pub copies it). Never paste the private key.
  3. When launching a server, choose that key pair. AWS puts your public key into the server's authorized_keys on first boot.
  • Key pairs belong to one region. A server in another region needs the key imported there too.
  • Since you're importing your own key, AWS never has your private key, and there's no .pem to download or lose.
⚠ COMMON MISTAKEThe key pair shown for an existing server in the AWS console is only a record of what it was launched with. Changing key pairs in the console does not change who can log in. For a running server, use part B.

B. Existing server: add your key to authorized_keys

You log in the way you do today (with the old key), add your new public key as an extra line, then test. The old key keeps working until you decide to remove it.

Step 1: copy your public key (on your Mac)
pbcopy < ~/.ssh/key-name.pub

Puts the public key on your clipboard. No output = done.

Step 2: log in the usual way
ssh ubuntu1
Step 3: open authorized_keys (on the server)
nano ~/.ssh/authorized_keys

You'll see one or more long lines starting with ssh-rsa or ssh-ed25519. Don't change them. Use the down arrow to go to the very end, make sure you're on a new empty line, and paste with Cmd+V. Save: Ctrl+O, Enter. Exit: Ctrl+X.

Where it lives

Amazon Linux 1

/home/ec2-user/.ssh/authorized_keys

Ubuntu 24.04

/home/ubuntu/.ssh/authorized_keys

~/.ssh/authorized_keys means the same thing on either, once you're logged in as that user.

Step 4: keep this window open, and test in a NEW Terminal window

First switch the server's config entry to the new key (section 4), then in a new Terminal window:

ssh ubuntu1
  • Logs in (after the 1Password approval) = done. Close the old window.
  • Permission denied = something's off, but your first window is still logged in, so you can fix authorized_keys from there. That's why you keep it open.
⚠ CAREFULYou may see shortcuts online like cat key.pub | ssh server 'cat >> ~/.ssh/authorized_keys'. The >> adds a line. A single > replaces the whole file, removing every other key, possibly including the one you're using, and locking you out. That's why this sheet uses nano.
Labelling keys in authorized_keys

Lines starting with # are notes. Put one above each key, so later you know whose it is:

# Me, 1Password key, added Nov 2026 ssh-ed25519 AAAAC3Nza…Qx7 me@mac # Hosting vendor ssh-rsa AAAAB3Nza…k9 vendor-key
MOODLE NOTEDo one server completely (add key, switch config, test) before starting the next. Keep each server's old key in place until the new one is proven, so a mistake never costs you access to a client's site.
↑ Back to top

Things you might forget

#6aknown_hosts and "host identification has changed"

CHANGES THINGSON YOUR MAC

Every server has its own ID (its host key). The first time you connect, your Mac saves that ID in ~/.ssh/known_hosts. After that, if the ID ever changes, ssh refuses to connect, in case someone is pretending to be your server.

What you'll see
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ … Offending ED25519 key in /Users/me/.ssh/known_hosts:14 Host key verification failed.
Is it safe? Usually yes, if you know why
  • Expected: you replaced or rebuilt the server, moved an Elastic IP to a new server, or a Multipass machine got an address another one used before.
  • Not expected: nothing changed that you know of. Stop and find out before connecting.
Fix (only when the change is expected): forget the old ID
ssh-keygen -R 203.0.113.10
  • Use the server's address (its HostName), not its nickname; known_hosts stores addresses.
  • It removes just that one entry and saves a backup as known_hosts.old.
  • Then connect again and answer yes to save the new ID.
↑ Back to top

#6bCopy files to and from a server

CHANGES THINGSON YOUR MAC

Both use the same login as ssh, so your config nicknames and 1Password work here too. Pattern: FROM TO, with server: in front of a path on the server.

scp: copy single files
scp ubuntu1:/tmp/report.csv .Download to the folder you're in on your Mac (. = here)
scp notes.txt ubuntu1:/tmp/Upload into the server's /tmp folder
rsync: copy whole folders, and resume if interrupted
rsync -av ubuntu1:/var/log/apache2/ ./ubuntu1-logs/Download a folder's contents into ubuntu1-logs on your Mac (on Amazon Linux 1 the folder is /var/log/httpd/)
rsync -av --dry-run …Show what would be copied, without copying. Run this first.
  • -a keeps dates and permissions; -v lists each file as it goes.
  • A trailing / on the source means "the contents of this folder." Without it, you get the folder itself inside the destination.
Getting files only root can read

You can't put sudo in front of scp. Log in, copy the file somewhere you can read with sudo cp, then download that copy:

sudo cp /var/log/httpd/error_log /tmp/ && sudo chmod 644 /tmp/error_log

Delete the copy from /tmp when you're done.

⚠ CAREFULBoth silently replace a file with the same name at the destination.
MOODLE NOTEHandy for downloading a large course backup (.mbz) or Apache logs to look at on your Mac. Never upload into a Moodle folder or moodledata this way without a backup; ownership will be wrong (see chown).
↑ Back to top

#6cRemove someone's access

CHANGES THINGSON THE SERVER

Delete their line from authorized_keys. That's all it takes, as long as they had their own key. If they used a key you also use (like a shared .pem), you have to give yourself a new key first.

Step 1: find every place their key is (read-only)
sudo sh -c 'grep -n "vendor-key" /home/*/.ssh/authorized_keys /root/.ssh/authorized_keys'
  • Replace vendor-key with the label at the end of their key line.
  • sudo sh -c '…' runs the whole search as root, so it can look inside every user's private .ssh folder.
  • Each match shows the file, then the line number. No such file for /root is fine.
Step 2: open the file it was found in (one file at a time)
sudo nano /home/ec2-user/.ssh/authorized_keys

Use the exact file path from step 1. Move to their line (and its # note). Ctrl+K cuts a whole line. Save: Ctrl+O, Enter. Exit: Ctrl+X.

Step 3: make sure YOU can still get in

Keep that window open and run ssh ubuntu1 in a new Terminal window, exactly as in section 5.

MOODLE NOTEDo this on every server they had access to. If your hosting vendor ever changes, this list is your offboarding checklist, along with any AWS console logins and IP addresses in your security groups (6d).
↑ Back to top

#6dSecurity groups: who can reach port 22

CHANGES THINGS

A security group is AWS's firewall for a server. SSH uses port 22. Even with perfect keys, port 22 should only be open to the addresses that need it, not the whole internet.

What a good SSH rule looks like
TypeSSH (port 22)
SourceYour IP address, written like 198.51.100.25/32 (/32 = exactly that one address). Add your vendor's address as a separate rule if they need it.
DescriptionWho it's for, e.g. "Home office" or "Hosting vendor"
0.0.0.0/0Anyone on the internet. Avoid for port 22.
What's my IP address right now? (read-only)
curl -s https://checkip.amazonaws.com 198.51.100.25
Where to change it

AWS console: EC2 › Security Groups › pick the group › Inbound rules › Edit inbound rules. The Source › My IP option fills in your current address.

⚠ WATCH FOR THISHome internet addresses can change. If ssh suddenly says Connection timed out on every server, check your IP against the security group rule before anything else.
↑ Back to top

#6eLocked out? Ways back in

If your key is lost or authorized_keys got broken, the server itself is fine; you just need another door. From easiest to hardest:

1. Another key that still worksAn old .pem, or a second window still logged in. This is why the sheet says keep old keys until new ones are proven.
2. AWS Session ManagerA command line in your browser through the AWS console, no port 22 or key needed. Only works if it was set up beforehand (agent on the server plus an AWS permission role). Worth setting up before you need it; covered on the AWS sheet.
3. EC2 Instance ConnectA "Connect" button in the console that pushes a temporary key. Works on Ubuntu 24.04 servers launched from AWS's images; not on Amazon Linux 1.
4. Disk swap (last resort)Stop the server, attach its disk to another server, fix authorized_keys there, put the disk back. Slow and fiddly, but it always works. Make a snapshot of the disk first.
MOODLE NOTEThe best recovery plan is prevention: every private key backed up in 1Password, and Session Manager set up on each server so there's always a second way in that doesn't depend on SSH keys.
↑ Back to top

When it doesn't work

#7Troubleshooting

READ-ONLYON YOUR MAC

Every SSH login goes through three stages in order. Figuring out which stage failed tells you where to look.

1. REACH Can my Mac get to the server at all? 2. ID CHECK Is it the same server as last time? 3. KEY Does the server accept my key?
Stage 1: can't reach the server
Connection timed out, or it just sits thereNothing answered. Server is off or stopped, wrong address, or the security group doesn't allow your current IP (6d). For Multipass: the virtual machine is stopped.
Connection refusedThe machine answered, but nothing is listening for SSH. The server is still booting, or its SSH service is down.
Could not resolve hostname ubuntu1No config entry called ubuntu1, or a typo in the name.
Stage 2: the server's ID
REMOTE HOST IDENTIFICATION HAS CHANGEDThe server at that address isn't the one your Mac remembers. See 6a.
Are you sure you want to continue connecting (yes/no)?Not an error: your first visit. Type yes.
Stage 3: the key
Permission denied (publickey)The server didn't accept any key you offered. Check, in order: the User line (ec2-user vs ubuntu), the right key in the entry, and that the key is actually in the server's authorized_keys (section 5).
UNPROTECTED PRIVATE KEY FILE naming a .pub fileMisleading. 1Password didn't hand over the key, so ssh tried the .pub as a private key. Check: key in your Personal/Private vault, SSH Agent turned on in 1Password, and the IdentityAgent line in the entry. Don't change the file's permissions.
UNPROTECTED PRIVATE KEY FILE naming a private key or .pemReal this time: the key file is too open. Fix with chmod 400 on that file.
Too many authentication failuresssh offered too many keys and the server hung up. Add IdentitiesOnly yes to that entry (section 4).
No 1Password window appearsIt may be hidden behind other windows; check the Dock. Or 1Password is locked or not running.
Not sure which stage? Add -v
ssh -v ubuntu1

-v means "verbose": ssh prints each step it takes. Read the last few lines before it stops; they show where it got stuck.

Connecting to … port 22. as the last lineStuck at stage 1. Never reached the server.
Server host key: …Reached the server; now at stage 2.
Offering public key: …At stage 3. Shows exactly which key it's trying. Check it's the one you expect.
Authenticated to …Success. You're in.

Press Ctrl+C to stop it if it's stuck. Use -vvv for even more detail.

Check what ssh will actually use for an entry
ssh -G ubuntu1 | grep -i identity

-G prints every setting ssh would use for ubuntu1, without connecting. grep -i identity keeps just the key lines (identityfile, identitiesonly, identityagent). Good for spotting a typo or the wrong key in an entry. Swap in user or hostname to check those.

MOODLE NOTEIf every server fails at stage 1 at once, it's almost never the servers; it's your end: your home IP changed (security groups), you're on a VPN, or your internet is down. If only one server fails, check that server in the AWS console first: is it running, and do its status checks pass?
↑ Back to top