Server access and hardening
Read SSH logs and failures
Correlate client verbose output with server authentication logs and network evidence.
Permission denied (publickey) is the least helpful error message in SSH. It means the server rejected every identity you offered, and it says the same thing whether the key is wrong, the account does not exist, the file permissions are bad, or AllowUsers excluded you.
The client tells you what it tried. The server tells you why it said no. You almost always need both, and the reflex to fight is regenerating keys before you have read either.
Open both sides
On the server, follow the log live:
sudo journalctl -u ssh -f
On your laptop, run the failing connection with -v. Then read the two outputs together. Here are the failures you will meet most often, and what each side says.
Timeout
ssh: connect to host 203.0.113.10 port 22: Operation timed out
The server log shows nothing at all. No packet arrived. This is routing, a firewall, or a wrong address. Keys are irrelevant. Check ufw status from the console and your own IP.
Host key failure
Host key verification failed.
Client-side only. The server did answer, but its key did not match known_hosts. Go back to the known_hosts lesson. Do not touch the server yet.
Rejected key
Client:
debug1: Offering public key: /Users/flavio/.ssh/id_ed25519 ED25519 SHA256:aB3d...
debug1: Authentications that can continue: publickey
Server:
Connection closed by authenticating user deploy 198.51.100.7 port 51234 [preauth]
The server saw deploy, looked at authorized_keys, and found no line matching SHA256:aB3d.... Compare that fingerprint with ssh-keygen -lf ~/.ssh/authorized_keys on the server. Nine times out of ten you offered the wrong key or installed it for the wrong user.
Invalid account
Server:
Invalid user bob from 198.51.100.7 port 51240
The account does not exist. No key on earth will fix this. Check the User in your config with ssh -G.
File mode rejection
Server:
Authentication refused: bad ownership or modes for directory /home/deploy
The key is right and the user is right. sshd refuses to read authorized_keys because the home directory, .ssh, or the file itself is writable by others. Fix the modes: 755 or stricter on the home, 700 on .ssh, 600 on the file.
Shell startup failure
This one is sneaky. The server log says Accepted publickey for deploy ..., so authentication worked. Then the connection closes at once. Something in the login shell is failing, often a bad line in .bashrc or a shell that no longer exists in /etc/passwd. Skip the profile to get in:
ssh -t notes-server 'bash --noprofile --norc'
Practice the diagnosis
Create four of these on purpose on your disposable server: install a key for the wrong user, chmod 777 ~/.ssh, add exit to the top of .bashrc, and connect with a username that does not exist. For each one, write the diagnosis from the two logs before you change anything. Then apply one fix and confirm the log line disappears.
Every fix in this list changes exactly one thing, and the log told you which one. That is the whole method.
Lesson completed