Linux / Tutorial

Securing SSH access to a Linux server

Switch to SSH keys, forbid root login and passwords, without ever locking yourself out.

Linux Tutorial Intermediate Published October 16, 2026 Translated October 27, 2026 12 min read Tested on: Ubuntu 24.04 (OpenSSH 9.6). Same method on Debian 12 and 13. Version française
Screen showing code
Photo: Pankaj Patel on Unsplash

Before you start

  • A Linux server reachable over SSH, with an account that has sudo rights
  • A terminal on your computer: Terminal (macOS, Linux) or PowerShell (Windows 10 and 11)
  • A fallback console (screen and keyboard, hypervisor or hosting provider console) in case something goes wrong

In plain words

A password is a door code that anyone can try to guess, thousands of times a day. An SSH key is a real physical key: the server keeps the lock (the public key), you keep the key (the private key) in your pocket. You fit the new lock, check that the key turns, and only then do you brick up the old coded door.

A server exposed over SSH constantly receives automated login attempts trying thousands of user name and password pairs. The most effective defence: accept SSH keys only, and forbid direct root login.

This tutorial follows a precise order so you never lock yourself out: you install and test the key before disabling passwords.

1. Create a key pair on your computer

On your computer (not on the server):

ssh-keygen -t ed25519 -C "spo@office-pc"
  • Accept the suggested location (~/.ssh/id_ed25519).
  • Choose a passphrase: it protects the key if your computer is stolen. The SSH agent remembers it for the session.

Two files are created:

File Role Share it?
id_ed25519 Private key Never, it does not leave your computer
id_ed25519.pub Public key Yes, this is the one you copy to servers

2. Install the public key on the server

Linux and macOS:

ssh-copy-id spo@192.168.1.50

Windows (PowerShell), where ssh-copy-id does not exist:

Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | ssh spo@192.168.1.50 "umask 077; mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Replace spo with your user and the address with the server's.

3. Test key-based login

ssh spo@192.168.1.50

The login must succeed without asking for the account password (only the key's passphrase, if you set one).

Warning

Do not move on to the next step if this test fails. Check the permissions on the server: chmod 700 ~/.ssh and chmod 600 ~/.ssh/authorized_keys; the home folder must not be writable by other users.

4. Harden the server configuration

Rather than editing the main file /etc/ssh/sshd_config, create a dedicated file in /etc/ssh/sshd_config.d/. It survives package updates and is easy to find.

sudo nano /etc/ssh/sshd_config.d/00-hardening.conf

Contents:

# Key-based authentication only
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
AuthenticationMethods publickey

# No direct root login: log in, then use sudo
PermitRootLogin no

# Limit attempts and login time
MaxAuthTries 3
LoginGraceTime 30

# Features a server does not need
X11Forwarding no

# Only these accounts may log in (separated by spaces)
AllowUsers spo

Why the "00-" prefix?

For OpenSSH, the first value read wins. Files in sshd_config.d/ are read in alphabetical order, before the rest of sshd_config. A file such as 50-cloud-init.conf, created by some cloud images, can turn PasswordAuthentication yes back on: the 00- prefix makes sure your settings come first.

5. Check, then apply, without closing your session

Check the syntax. The command must print nothing:

sudo sshd -t

Check the configuration actually in effect:

sudo sshd -T | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|permitrootlogin|allowusers)'

Expected result:

permitrootlogin no
passwordauthentication no
kbdinteractiveauthentication no
allowusers spo

Reload the service:

sudo systemctl reload ssh       # Debian, Ubuntu
sudo systemctl reload sshd      # Fedora, RHEL, Rocky, Alma, Arch

Danger

Keep your current session open. Open a second terminal and test a new login. If it fails, fix things from the first session, which is still connected.

6. Check that passwords are really refused

From your computer, force a password attempt:

ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password spo@192.168.1.50

Expected answer: Permission denied (publickey). The server no longer even offers password login.

Going further

  • Firewall: only allow port 22 from your management networks or your VPN. That beats every other measure.
  • Fail2ban or CrowdSec: temporarily ban addresses that pile up failures. Useful on a server exposed to the internet, less essential once passwords are disabled.
  • Changing the port: reduces noise in the logs, but brings no real security. On Ubuntu 24.04 and later, SSH is started by ssh.socket: after changing Port, run sudo systemctl daemon-reload then sudo systemctl restart ssh.socket, otherwise the old port keeps listening.
  • Logs: sudo journalctl -u ssh --since today (or -u sshd) shows logins and failures.

Troubleshooting

Symptom Likely cause Fix
Permission denied (publickey) with your key Wrong permissions on ~/.ssh, or key missing from authorized_keys Fix the permissions (step 3), check the file's contents
Passwords are still accepted Another file in sshd_config.d/ is read before yours Check with sudo sshd -T, rename your file with a lower prefix
No access at all Configuration error and session closed Log in through the fallback console, delete 00-hardening.conf, reload the service

Read next