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; safeCHANGES THINGS be carefulON YOUR MAC type it in Terminal on your MacON THE SERVER type it after you've logged in to the serverAmazon 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.
The pieces
Private key
Stays 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 key
The .pub file. Safe to share. You put it on each server you want to log in to.
authorized_keys
A file on the server listing the public keys allowed in. One line per key.
Passphrase
A 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).
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 ed25519
The key type. Modern, short, and strong. Works with Amazon Linux 1, Ubuntu 24.04, and AWS.
-f~/.ssh/key-name
The 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.
Passphrase
Use 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.
fingerprint
A 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
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.
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
File
What it is
Permission
~/.ssh (the folder)
Holds everything below
700 (only you)
key-name
A private key you made (one per name)
600 (only you read/write)
key-name.pub
Its public key
644 (fine for others to read)
client1.pem etc.
Private keys AWS made for you
400 (only you, read-only)
config
Your server shortcuts (section 4)
600
known_hosts
Servers you've visited before (section 6). ssh manages it.
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.
Add the key: in 1Password, New Item › SSH Key. Import an existing key file, or generate a new ed25519 key there.
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.
Turn on the agent once:Settings › Developer › Use the SSH Agent.
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.
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.
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
Once per AWS region: in the AWS console, go to EC2 › Key Pairs › Actions › Import key pair.
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.
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:
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.
#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.
⚠ 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).
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).
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
Type
SSH (port 22)
Source
Your 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.
Description
Who it's for, e.g. "Home office" or "Hosting vendor"
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.
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 works
An 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 Manager
A 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 Connect
A "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.
Every SSH login goes through three stages in order. Figuring out which stage failed tells you where to look.
Stage 1: can't reach the server
Connection timed out, or it just sits there
Nothing 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 refused
The machine answered, but nothing is listening for SSH. The server is still booting, or its SSH service is down.
Could not resolve hostname ubuntu1
No config entry called ubuntu1, or a typo in the name.
Stage 2: the server's ID
REMOTE HOST IDENTIFICATION HAS CHANGED
The 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 file
Misleading. 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 .pem
Real this time: the key file is too open. Fix with chmod 400 on that file.
Too many authentication failures
ssh offered too many keys and the server hung up. Add IdentitiesOnly yes to that entry (section 4).
No 1Password window appears
It 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 line
Stuck 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?