Skip to main content
  1. Posts/

How to Harden SSH on Ubuntu with Public Key Authentication

Table of Contents

Introduction
#

Public-key SSH authentication is much more secure than password-only login. This guide shows how to generate a key pair, install your public key on a Linux server, and safely disable password authentication.

Generate an SSH key pair on Windows
#

Run the following command in PowerShell:

ssh-keygen -t rsa -b 4096

Follow the prompts to save your keys. You can set an optional passphrase to protect the private key.

Copy your public key to the Linux server
#

From PowerShell, copy your key to the target server:

cat ~/.ssh/id_rsa.pub | ssh username@remote_host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Replace username@remote_host with your actual SSH username and host.

Configure the SSH daemon for key-based authentication
#

Back up and update the SSH daemon configuration.

Back up the original config (optional but recommended):

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

Apply key-based auth settings:

sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config

This sets the PasswordAuthentication, PubkeyAuthentication, and PermitRootLogin values required for key-based authentication.

Add any missing directives if sed did not find them (this can usually be skipped):

grep -q '^PasswordAuthentication' /etc/ssh/sshd_config || echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config
grep -q '^PubkeyAuthentication' /etc/ssh/sshd_config || echo 'PubkeyAuthentication yes' >> /etc/ssh/sshd_config
grep -q '^PermitRootLogin' /etc/ssh/sshd_config || echo 'PermitRootLogin no' >> /etc/ssh/sshd_config

You can manually inspect the file if needed:

sudo nano /etc/ssh/sshd_config

Restart SSH to apply the changes:

sudo systemctl restart ssh

Ground-truth effective SSH settings
#

Do not rely only on file contents. Ask ssh which values are actually active:

sudo sshd -T | grep -E "passwordauthentication|permitrootlogin|kbdinteractiveauthentication"

Expected output should include:

passwordauthentication no
permitrootlogin no
kbdinteractiveauthentication no

Check override files if values are not correct
#

If the output is not as expected, another file is overriding your settings, usually under /etc/ssh/sshd_config.d/.

Example file to edit:

sudo nano /etc/ssh/sshd_config.d/50-cloud-init.conf

Inside that file, set:

  • PasswordAuthentication no
  • PermitRootLogin no

Then restart and verify again:

sudo systemctl restart ssh
sudo sshd -T | grep -E "passwordauthentication|permitrootlogin|kbdinteractiveauthentication"

Safety test before disconnecting
#

From a new local terminal, confirm password login is blocked:

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@remote_host

Expected result:

Permission denied (publickey)

If you still get a password prompt, keep your existing session open, fix the override file, and test again.

Conclusion
#

Your server is now configured for public-key SSH authentication with password logins disabled. This significantly reduces brute-force and credential-guessing risk while keeping remote access reliable.