I Installed the Key, So Why Is It Asking for a Password
In one line
Most causes of public key authentication failing are not cryptography but file permissions. If permissions are loose, sshd silently rejects the key.
Why this exists
You put a key in with ssh-copy-id, yet it still asks for a password. If you look at the client log (ssh -vvv), it offered the key (Offering public key) but the server does not accept it. The server log has no clear reason either.
The cause is usually this.
chmod 755 ~ # 홈이 그룹 쓰기 가능이면 거부된다
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
There is a reason sshd is so picky. If another user can write to authorized_keys, that user can add their own key with one line and log in to someone else's account. Permissions are, in effect, the authentication policy.
The RHEL family has one more trap. If you created the home directory by hand or copied the file from another path, the SELinux context is wrong and the key is rejected. The log does not clearly say it is a permission problem, so it eats a lot of time. restorecon -Rv ~/.ssh is the standard fix.
How it works
A key is two pieces. The private key is only in your hands, and the public key goes into the server's authorized_keys as one line. Authentication works by signing a challenge the server issues with the private key, so the private key never goes out over the network.
Key types have effectively narrowed to two.
ssh-keygen -t ed25519 -C 'youngju@laptop-2026' -f ~/.ssh/id_ed25519
ssh-keygen -t rsa -b 4096 -C 'youngju@laptop-2026' -f ~/.ssh/id_rsa
ssh-keygen -t ed25519-sk -f ~/.ssh/id_ed25519_sk # FIDO2 하드웨어 키
Ed25519 is the default, and you use RSA 4096 only when an organizational policy such as FIPS requires it. With -sk, the private key never leaves the hardware.
The habit of writing the person and the device in the -C comment matters. When 20 lines have piled up in authorized_keys, it is the only clue to which line belongs to whom.
You can put restrictions on each line of authorized_keys.
restrict,from="10.0.0.0/8",command="/usr/local/bin/deploy-only" ssh-ed25519 AAAAC3Nza... deploy@ci
restrictis a safe default that turns off every feature. You then turn back on only what you need.from=restricts the source of the connection.command=runs only the specified command no matter what the client requests. It is especially useful for deployment keys.
It is better to write client-side settings in a file too.
Host bastion
HostName bastion.example.com
User youngju
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
Host prod-*
User deploy
ProxyJump bastion
IdentitiesOnly yes
IdentitiesOnly yes is especially important. Without it, it tries every key loaded in the agent in turn and runs into the server's MaxAuthTries (default 6), and authentication fails. It is the classic problem of people who have several keys.
What it looks like in the field
Revoking a key does not end with deleting a line from the file. Sessions that are already open stay alive. A full revocation is this order: delete the line → check sessions with who → end that user's sshd sessions. The last step can also cut your own session, so be sure to check the target account.
Habitually ignoring the host key warning. It happens because the warning appears every time you reinstall a server. That habit disables the only line of defense against a man-in-the-middle attack. As you scale up, moving to SSH certificates (signing host keys with a CA) is the right answer.
When you have a key but cannot log in
Permission denied (publickey) has several causes, but if you set the order of checks, it is
usually finished within a minute.
First, look at which key the client is sending.
ssh -v user@host 2>&1 | grep -E "Offering|Authentications|Server accepts"
If you have several keys, ssh tries them in order, but it runs into the server's
MaxAuthTries (default 6) first and gets cut off before it sends the right key.
In that case, state the key to use explicitly.
Host prod
IdentityFile ~/.ssh/id_prod
IdentitiesOnly yes # 다른 키는 아예 시도하지 않는다
sshd refuses even if permissions are only slightly loose. This is the most common cause.
| Target | Permissions |
|---|---|
~ |
No write for group or other (755 or tighter) |
~/.ssh |
700 |
~/.ssh/authorized_keys |
600 |
| Private key | 600 |
In the server-side log (journalctl -u sshd), Authentication refused: bad ownership or modes is left, so if you can access it, that is the fastest answer.
The server configuration may be blocking that method. Look at PubkeyAuthentication,
AuthorizedKeysFile, AllowUsers/AllowGroups, and PermitRootLogin. Recent distributions
reject old key formats (ssh-rsa with SHA-1) by default, so an old key can suddenly stop working. In that case, making a new key is right, and if you are in a hurry, add it temporarily to PubkeyAcceptedAlgorithms.
It is easy to forget about the agent. If ssh-add -l is empty, you cannot use a key
locked with a passphrase. Agent forwarding (-A) is convenient, but root on that server can use your agent as it is. If jumping is the goal, use ProxyJump — the key is not
exposed to the intermediate server.
Host prod
ProxyJump bastion
What you will do in the next lab
You create a key, set its permissions, register it in authorized_keys, and actually connect to 127.0.0.1:2222. You make an alias with ~/.ssh/config and confirm that a key with a command= restriction really runs only that command.