← Back to writing

Setting Up SSH Key Authentication for an Ubuntu Server

Create an Ed25519 SSH key, install it on an Ubuntu VM, define a clean host alias, and safely disable password authentication.

SSH key authentication removes repeated account-password entry and gives automation tools a safer, more manageable way to connect to Linux servers. The sequence is straightforward, but the order matters—especially if password authentication will eventually be disabled.

This guide is based on my ssh-ubuntu-server project, using a Linux host and an Ubuntu Server VM on a reachable network.

1. Prepare the Ubuntu server

Find the VM’s address:

hostname -I

Install OpenSSH Server and enable it immediately and at boot:

sudo apt update
sudo apt install -y openssh-server
sudo systemctl enable --now ssh
sudo systemctl status ssh

Confirm the service is active before continuing. Also verify that the host can reach the VM and that any local or cloud firewall permits TCP port 22 from the intended source.

2. Generate a dedicated Ed25519 key

On the client machine, create the SSH directory if necessary and generate a key:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -a 100 -C "ubuntu-server"

When prompted for the filename, use a full path such as:

/home/your-user/.ssh/ubuntu_server

This creates two files:

~/.ssh/ubuntu_server       # private key
~/.ssh/ubuntu_server.pub   # public key

The distinction is fundamental. The public key is installed on servers. The private key stays on the client and must never be pasted into documentation, uploaded to a server, or committed to Git.

Use secure permissions:

chmod 600 ~/.ssh/ubuntu_server
chmod 644 ~/.ssh/ubuntu_server.pub

A passphrase adds protection if the private key file is copied from the machine. An SSH agent can cache the unlocked key for the session.

3. Install the public key

Copy the public key using the VM account’s current password:

ssh-copy-id -i ~/.ssh/ubuntu_server.pub sam@192.168.x.x

Then test the exact identity file before changing any server authentication settings:

ssh -i ~/.ssh/ubuntu_server sam@192.168.x.x

Successful passwordless account authentication confirms that the public key reached ~/.ssh/authorized_keys on the VM and the client can use the matching private key.

4. Create a readable SSH alias

Repeated IP addresses and flags are easy to mistype. Add a host entry to ~/.ssh/config:

Host ubuntu-vm
    HostName 192.168.x.x
    User sam
    IdentityFile ~/.ssh/ubuntu_server
    IdentitiesOnly yes

Protect the configuration and connect using the alias:

chmod 600 ~/.ssh/config
ssh ubuntu-vm

IdentitiesOnly yes prevents the SSH client from offering every key loaded in an agent, which can otherwise cause authentication failures on servers with low attempt limits.

5. Use an SSH agent when helpful

Start an agent and add the key:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/ubuntu_server

This is most useful when the private key has a passphrase. The agent holds an unlocked identity in memory so the passphrase is not entered for every new connection.

6. Disable passwords only after verification

Keep the working SSH session open. In a second terminal, prove that ssh ubuntu-vm opens a new session with the key. Only then consider changing /etc/ssh/sshd_config:

PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no

Validate the effective configuration before restart where supported:

sudo sshd -t
sudo systemctl restart ssh

Test a new connection again before closing the original session. That open session is your recovery path if the configuration contains an error.

Troubleshooting methodically

Inspect the resolved client configuration:

ssh -G ubuntu-vm

For negotiation details, use verbose output:

ssh -vvv ubuntu-vm

On the server, verify ownership and permissions for the user’s home directory, .ssh, and authorized_keys. OpenSSH may reject keys when those files are writable too broadly.

For cloud servers, remember that SSH has two independent gates: the network path must allow port 22, and the operating system must accept the presented identity. Debug those layers separately.

The complete checklist and directory layout are available in the ssh-ubuntu-server repository.