Home / Alt manpages / authorized_keys(5)

  • authorized_keys(5)
  • File format
  • linux

Lock Down authorized_keys Without Losing Access

One bad line in authorized_keys can lock you out of the only account that gets you back in. This walk-through installs one SSH public key for one account, locks down file permissions, and adds a restricted example fit for an automated job. The final checks confirm sshd can parse the server configuration before you close your existing session.

Allow about 10 minutes if you already have a public key. You need an account that can log in, the matching private key on the client, and elevated access on the server for the first setup. Keep your current SSH session open until a second login has succeeded. An error in this file can remove your only route in.

1. Identify the file and the key

On this Ubuntu machine, OpenSSH comes from openssh-server version 1:9.6p1-3ubuntu13.19. The local authorized_keys(5) page says that the default files are ~/.ssh/authorized_keys and the older ~/.ssh/authorized_keys2, unless AuthorizedKeysFile changes that setting in sshd_config. Check the effective value rather than assuming it:

sudo sshd -T | grep '^authorizedkeysfile '

Typical output is:

authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2

The path is relative to the user's home directory. A line in the file contains an optional comma-separated options field, a key type, the base64 public key, and an optional comment. Do not retype the long middle field. Copy the public half produced by ssh-keygen:

ssh-keygen -lf ~/.ssh/id_ed25519.pub
cat ~/.ssh/id_ed25519.pub

Run those commands on the client that holds the private key. The fingerprint helps you distinguish several keys; the complete one-line output from the second command is what belongs on the server. A comment such as alice@laptop is only a label. It does not grant access and sshd does not use it for authentication.

2. Install an ordinary login key

On the server, replace alice with the account that should receive the key. The commands below create the directory if needed, append the public key, and set the usual restrictive modes. The sudo commands require elevated privileges.

sudo install -d -m 700 -o alice -g alice /home/alice/.ssh
cat /path/to/id_ed25519.pub | sudo tee -a /home/alice/.ssh/authorized_keys > /dev/null
sudo chown alice:alice /home/alice/.ssh/authorized_keys
sudo chmod 600 /home/alice/.ssh/authorized_keys

Use the real home directory from getent passwd alice if it is not /home/alice. Appending is deliberate: overwriting the file can revoke other working keys. If you accidentally add the wrong key, remove only that complete line while logged in through a known-good session.

Check both the file metadata and the key fingerprint:

sudo stat -c '%U:%G %a %n' /home/alice/.ssh /home/alice/.ssh/authorized_keys
ssh-keygen -lf /home/alice/.ssh/authorized_keys

Checkpoint

On a normal installation, the first command reports ownership by alice, mode 700 for the directory and 600 for the file, and the fingerprint matches the public key you intended to install.

3. Restrict a key for one job

A plain key usually permits an interactive session and, depending on the server policy, forwarding requests. For an automated backup or deployment key, put restrictions before the key type. There must be no spaces between comma-separated options, except inside a quoted option value.

restrict,command="/usr/local/bin/backup-receiver",no-pty ssh-ed25519 AAAA... backup-job
  • command= replaces the command requested by the client. The original request is still available to the forced program in SSH_ORIGINAL_COMMAND, useful if the program needs to validate a protocol request. It applies to shell, command and subsystem execution. Make the program validate its inputs and use an absolute path.
  • restrict disables port forwarding, agent forwarding, X11 forwarding, pseudo-terminal allocation and the user's ~/.ssh/rc. The explicit no-pty above is redundant but makes the no-terminal requirement obvious to a reader.
  • permitopen="host:port" allows one narrow local forwarding exception; permitlisten="host:port" does the same for remote forwarding. Add only the one destination the job needs.
  • from="192.0.2.10" requires the connection to come from that address or matching hostname, but this only adds dependence on address and name resolution. It does not replace possession of the private key.

Do not use a forced command as a substitute for checking what the command itself can alter: it still runs with the account's normal filesystem permissions.

4. Test before changing the daemon

Adding a line to authorized_keys normally needs no daemon restart. If you also change /etc/ssh/sshd_config, validate it before reloading the service.

Warning

This is a security-sensitive, service-disrupting step. Keep the current session open and have console access or another administrator's key available before you touch the daemon.

sudo sshd -t
sudo sshd -T | grep -E '^(authorizedkeysfile|pubkeyauthentication) '

No output from sshd -t and exit status zero mean that the configuration and key sanity checks passed. The second command prints effective settings, not comments from the file. If the configuration uses Match, add connection details to -T when checking a particular account, for example:

sudo sshd -T -C user=alice,addr=192.0.2.10,host=client.example,laddr=192.0.2.20,lport=22 \
  | grep -E '^(authorizedkeysfile|pubkeyauthentication) '

Only after the check succeeds should you reload a changed daemon configuration. On a system managed by systemd, use the service manager rather than starting a second daemon by hand:

sudo systemctl reload ssh

Recovery

If the reload fails, do not close your working session. Read sudo systemctl status ssh and the journal, restore the last known-good configuration, run sudo sshd -t again, then reload once the test is clean. An authorized_keys edit alone does not require this reload.

5. Verify the login from another terminal

From the client, specify the key and account explicitly so that an agent or a different default key cannot hide a mistake:

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 [email protected] 'printf "authenticated\n"'

Expected output is:

authenticated

For a restricted key, test the permitted operation and then test a forbidden one. A rejected forwarding request or the absence of a pseudo-terminal is evidence that the restriction was applied, but inspect the server's authentication log if the result is unclear.

  • Wrapped key line. A public key copied with line wrapping is the most common single-key failure.
  • Wrong home directory. Check it with getent passwd rather than assuming /home/<user>.
  • Line over 8 KiB. The manual imposes a limit; a key line beyond it is rejected.
  • Ownership too loose. Strict mode checks fail quietly if permissions are wrong.
  • AuthorizedKeysFile elsewhere. Confirm the effective path with sshd -T rather than guessing.

The locally installed page lists Ed25519, ECDSA and security-key types, among others, and imposes a minimum RSA modulus of 1024 bits. Prefer a current key type supported by both ends, usually Ed25519 or a hardware-backed security key. Do not remove an older working key until the replacement has been tested in a separate session and its recovery path is documented.

Done means

  • Key installed: the intended public key is in the effective authorised-keys file, on one line.
  • Permissions correct: the SSH directory is mode 700, the file is mode 600, and both have the expected owner.
  • Config valid: sudo sshd -t passes after any daemon configuration change.
  • Login proven: a second terminal authenticates with the intended private key.
  • Least privilege: service keys use a forced command and only the forwarding or terminal permissions they genuinely need.