The format
# Deploy key, added for the release job
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINH9eelf0P7eT5ue6SualUXFrh1c9p3Maaem93iZtC2Q you@laptop
from="203.0.113.10",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINxDNsPpUAbI52nc1OduztL+ backup-job
Reading a line from left to right:
- Options, optional. Separated by commas, with no spaces unless they are inside double quotes.
- Key type, such as
ssh-ed25519orssh-rsa. - The key, a long base64 string.
- A comment, optional. It is only for you.
Blank lines and lines starting with # are ignored. A line that makes no sense is skipped, and the lines after it still work.
These mistakes silently cost you the key, and you see only Permission denied:
- A key broken over two lines, usually by pasting into an editor that wraps text. Each key must be on one line.
- A key without its type at the start.
- A space after a comma in the options, as in
from="203.0.113.10", restrict.
Need a key to put there? See how to generate an Ed25519 SSH key.
Useful options
| Option | Effect |
|---|---|
restrict | Turns off port, agent and X11 forwarding, terminals and ~/.ssh/rc. |
command="..." | Runs this command whatever the client asked for. |
from="..." | The login must come from one of these addresses or names. CIDR and patterns work. |
permitopen="host:port" | Limits ssh -L to this destination. |
expiry-time="20991231" | The key stops working after this date. |
cert-authority | The line is a certificate authority, not a user key. See SSH certificates. |
verify-required | For FIDO keys: every signature must include a PIN or similar check. |
For working examples, see how to restrict a key to one command.
Permissions
The safe settings, run as the user on the server:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
If you created them as root, fix the owner too:
sudo chown -R user:user /home/user/.ssh
Here is what happened in our tests, and what the server log said:
| Setting | Result |
|---|---|
authorized_keys mode 600 or 644 | Works |
authorized_keys mode 666 | Refused: Authentication refused: bad ownership or modes for file /home/user/.ssh/authorized_keys |
~/.ssh mode 700 or 755 | Works |
~/.ssh mode 777 | Refused: Authentication refused: bad ownership or modes for directory /home/user/.ssh |
| File owned by root, mode 644 | Works, because the user can read it |
| File owned by root, mode 600 | Refused: Could not open user 'user' authorized keys '/home/user/.ssh/authorized_keys': Permission denied |
The check is called StrictModes and it is on by default. Leave it on. A home directory with mode 775 passed on our Debian system, where the group holds only that user, but that is a Debian change, so other systems can refuse it. The client sees only Permission denied, so always read the server log. See how to debug an SSH connection.
Which line wins
When a key appears more than once, sshd reads from top to bottom and uses the first line that lets the login through. Only the options of that line apply. This gives two results worth knowing:
- A plain line above a restricted one defeats it. With the key listed plainly first and with
command="..."second, the login gets a normal, unrestricted session. - A line whose condition fails does not stop the search. If the first line has a
from=that does not match, or anexpiry-timein the past, the next line with the same key can still let the login through. To cut off a key, delete all its lines.
Changing where the file lives
The server setting AuthorizedKeysFile says where to look. See the current value with:
sudo sshd -T | grep -i authorizedkeysfile
The default is .ssh/authorized_keys .ssh/authorized_keys2, so a key in a forgotten authorized_keys2 also works. Check for one when you remove access.
A common change is to keep the files outside home directories, where only root can edit them:
# /etc/ssh/sshd_config.d/10-keys.conf
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
%u is the user name and %h the home directory. Relative paths start from the home directory. Each user must be able to read their own file, for example with mode 644 and root as the owner. Create those files before you reload sshd, and keep a session open while you test.
To fetch keys from somewhere else, such as a directory service, use AuthorizedKeysCommand. See sshd_config(5).
See what is in the file
ssh-keygen -lf ~/.ssh/authorized_keys
This prints a fingerprint for each key. On a line with options, the option text appears where you would expect the comment, for example 256 SHA256:NxFS... restrict,command="/usr/local/bin/ssh-allow" (ED25519). The fingerprint is still correct.
Questions
Where is the authorized_keys file?
By default in ~/.ssh/authorized_keys, in the home directory of the account you log in to. The server setting AuthorizedKeysFile can point elsewhere; check it with sudo sshd -T | grep -i authorizedkeysfile.
Do I need to restart sshd after editing authorized_keys?
No. sshd reads the file at each login, so a change applies to the next connection.
Why does SSH still ask for a password after I added my key?
Usually the permissions are too open, the key is split over two lines, or it went into the wrong account. The server log names the reason; the client only shows the password prompt or Permission denied.