← Back to blog

Daniel Garcia

SSH without repeated password prompts: from Windows to Linux with keys

Versão portuguesa →

A public key on the server, a protected private key on Windows and a short name for the connection. Let us see how these pieces allow us to administer a Linux server in fewer steps while keeping authentication in place.

Illustration of a laptop and a server connected by a protected channel, with a private key stored beside the laptop and an authorised key on the server.
In this article

The password again?

When we use a Linux server regularly, opening an SSH connection becomes routine: open the terminal, enter the username and server address, type the password and get to work.

It works. But repeating the same sequence several times a day is a good reason to improve the process.

In August 2026, I configured key-based access to my HomeLab from Windows. The client was OpenSSH, used through PowerShell, and the server was running Ubuntu. The aim was to simplify connections without giving up authentication.

In this article, we will follow that scenario, using the username dgarcia, the address 192.168.1.75 and the name homelab. These are the details of the reference setup: anyone following the tutorial should replace them with those of their own environment.

There is a distinction worth making at the outset: no longer typing the server password does not mean leaving the private key unprotected. We can use a passphrase and an authentication agent to combine protection with convenience.

What we need before we start

SSH, short for Secure Shell, lets us open a remote terminal session over an encrypted connection. In our case, Windows initiates the connection and Ubuntu receives it.

On Windows, we need the OpenSSH client, which includes the commands ssh, ssh-keygen and ssh-add. We can check that the client responds in PowerShell:

ssh -V

If the command is not available, see the official OpenSSH installation guide for Windows. To initiate connections from Windows to Ubuntu, we only need the client component on Windows.

On Ubuntu, the OpenSSH server must be installed, running and accessible over the network, with an account we can already sign in to. We will assume the default port, 22, and a configuration that allows public key authentication. The Ubuntu documentation explains how to prepare the server.

This tutorial starts with an SSH connection already available on the local network. It does not require exposing the SSH port to the Internet. If we cannot communicate with the server at all, we need to resolve connectivity first; the article on diagnosing a Wi-Fi connection with no Internet access helps explain part of that process.

1. Make the first connection and verify the server

In PowerShell on Windows:

ssh dgarcia@192.168.1.75

ssh starts the client, dgarcia is the username on Ubuntu and the address after @ identifies the server.

On the first connection, we will usually be asked to confirm the server’s identity, alongside a fingerprint: a summary that identifies its public key.

Before accepting, compare that fingerprint with one obtained through a trusted channel, such as the local Ubuntu console or the server’s management console. To display the fingerprint of the server’s Ed25519 host key, run this in that console:

ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

We must compare the same key and algorithm shown in the prompt. If the connection presents an RSA or ECDSA key, check the corresponding public key file instead.

Only accept once we have confirmed a match. The client saves that identity in known_hosts so it can recognise it on subsequent connections. If a warning later says the identity has changed, we should investigate before bypassing it. The ssh manual explains this verification.

The server may then ask for the password of the dgarcia account. As we type it, the terminal may display neither characters nor asterisks; this is normal.

Once signed in, keep this session open. We will use it to prepare Ubuntu while carrying out other steps in a second Windows terminal.

2. Create the key pair on Windows

In a second PowerShell window, still on Windows, run:

ssh-keygen -t ed25519

The command creates a key pair using the Ed25519 algorithm. When it asks where to save it, the usual location is the Windows user’s .ssh folder.

If a key already exists at that path, do not replace it without knowing where it is used. We can reuse a suitable pair or choose a different name for the new one. In that case, we need to adjust the paths in the examples that follow.

If we accept the usual name, we get:

File on Windows Purpose
C:\Users\<username>\.ssh\id_ed25519 Private key: must remain protected on the client.
C:\Users\<username>\.ssh\id_ed25519.pub Public key: will be authorised on the server.

The files are mathematically related. During authentication, the client demonstrates that it can use the private key corresponding to the authorised public key, through a digital signature, as described in the SSH authentication protocol. The private key does not need to be sent to Ubuntu.

ssh-keygen also asks for a passphrase, a phrase or password that protects the private key file. I recommend setting one: if someone copies the file, this protection adds a barrier to its use.

The passphrase is local and does not have to match the Linux account password. If we lose it, there is no recovery button; we need another way to access the server and authorise a new pair. The ssh-keygen manual describes key generation and protection.

3. Prepare the permissions on Ubuntu

Return to the SSH session already open on Ubuntu, signed in as dgarcia, and run:

umask 077
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
echo >> ~/.ssh/authorized_keys

Here, ~ refers to the home directory of dgarcia on Ubuntu. On Windows, the home directory is different, even though we may see similar notation.

If any command reports an error, resolve the cause before continuing to send the key.

mkdir -p creates the directory if it does not already exist. touch creates authorized_keys if it is missing, without erasing the contents of an existing file. The final line ensures a separator before the key we are about to append, even if the existing last line does not end with a newline.

umask 077 restricts the permissions of files created in that session. chmod 700 reserves access to the directory for its owner; chmod 600 allows the owner to read and write the file, removing access for the group and other users.

We are preparing the remote user’s files, so these commands do not require sudo. If the existing files belong to another account, that needs to be resolved with the administrator rather than worked around by loosening permissions.

The sshd manual explains the recommended permissions and why the server may reject files that other users can modify. It is also important that the home directory is not writable by others.

4. Send only the public key

In the second PowerShell window on Windows:

Get-Content -LiteralPath "$env:USERPROFILE\.ssh\id_ed25519.pub" |
    ssh dgarcia@192.168.1.75 'cat >> ~/.ssh/authorized_keys'

This command preserves the logic used in the reference setup, where type read the public key file. In PowerShell, type is an alias for Get-Content; here, we use the full name to make the operation clearer.

$env:USERPROFILE identifies the Windows user’s profile folder. The contents of the .pub file pass through the | operator to the SSH client. Once the connection is authenticated, the remote cat command receives those contents and appends them to the authorized_keys file for dgarcia.

The >> operator appends. Using a single > would overwrite the file and could remove other authorised keys.

At this stage, the server may still ask for the account password. It is precisely this already authorised connection that lets us install the new public key. Run the copy once; repeating it may create duplicate entries.

On Ubuntu, check the permissions and list the fingerprints of the authorised keys:

ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys
ssh-keygen -lf ~/.ssh/authorized_keys

We expect permissions of drwx------ on the directory and -rw------- on the file, with dgarcia as the owner. To compare the fingerprint of the local public key, run this on Windows:

ssh-keygen -lf "$env:USERPROFILE\.ssh\id_ed25519.pub"

A matching fingerprint should appear in the remote file. Never copy the file without .pub into this list. Each entry authorises a public key, as explained in the authorized_keys format.

5. Confirm that the key is actually being used

Opening another ordinary connection is useful, but it can hide a detail: if the key fails, the client may try another method and eventually sign in with the password.

To test key authentication specifically, on Windows:

ssh -v -i "$env:USERPROFILE\.ssh\id_ed25519" -o IdentitiesOnly=yes -o PreferredAuthentications=publickey dgarcia@192.168.1.75

-i specifies the key file, IdentitiesOnly=yes limits the identities to those configured and PreferredAuthentications=publickey restricts the methods attempted to public key authentication. The -v option displays diagnostic information, including the method used to authenticate the connection.

This test should not fall back to the Linux account password. It may still ask for the private key’s passphrase, which is expected before we make the key available through the agent.

If the server requires multiple factors, a key alone may not be enough: this test assumes the simple configuration described at the start. The options are documented in ssh_config.

If it fails, check the username, the key that was sent, and the ownership and permissions of the files. Messages such as Permission denied (publickey) point to authentication; a connection that never reaches the server requires investigating the service, network or port.

6. Use ssh-agent without removing the passphrase

ssh-agent makes the key available to the client for authentication operations, reducing the need to enter the passphrase again. It is a component on the client computer, not a key we need to copy to the server.

On Windows, open PowerShell as an administrator and configure the service:

Set-Service -Name ssh-agent -StartupType Automatic
Start-Service ssh-agent
Get-Service ssh-agent

The expected status is Running. Close that window and, in a normal PowerShell window under the Windows account that will use SSH, load the key:

ssh-add "$env:USERPROFILE\.ssh\id_ed25519"
ssh-add -l

The first command may ask for the passphrase. The second lists the fingerprints of the identities available in the agent. If it reports that there are no identities, we need to load the key.

Microsoft documents the configuration of ssh-agent on Windows; the ssh-add manual explains how to load and list identities.

While the key is available in the agent and the configuration allows its use, the client can authenticate without asking for the passphrase again. This does not remove the need to protect the Windows session, lock the computer and keep protected backups of the key.

We do not need to enable agent forwarding to Ubuntu for this scenario. The ssh-agent manual distinguishes the local agent from that forwarding.

7. Replace the address with a short name

On Windows, edit C:\Users\<username>\.ssh\config, whose location is described in Microsoft’s OpenSSH configuration documentation. If it already exists, add the block without deleting the other entries; save it as config, without .txt:

Host homelab
    HostName 192.168.1.75
    User dgarcia
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Host defines the local alias, HostName specifies the actual address, User stores the remote username and IdentityFile selects the private key on the client. IdentitiesOnly helps prevent the agent from offering other identities unnecessarily.

Now, in PowerShell:

ssh homelab

The alias does not change Ubuntu’s hostname or create a DNS record. It is a configuration entry read by the SSH client. If the server’s IP address changes, we need to update HostName or use a name the network can resolve.

If the file contains a general Host * block, place the specific entry before it: for many options, the client uses the first value it finds.

We can also reuse this entry in VS Code Remote-SSH, selecting homelab through Remote-SSH: Connect to Host…, provided the extension uses this same configuration file. The VS Code documentation explains how to choose and manage hosts.

What if I lose the computer or want to revoke access?

Using another trusted way to access Ubuntu, identify the key by its fingerprint and remove only the corresponding line from ~/.ssh/authorized_keys with a text editor. Avoid deleting the entire file: it may contain access for other computers.

Using different key pairs on different computers is good practice. That way, we can revoke one device’s authorisation without replacing all the other keys.

Removing a key from this list prevents new authentications through that entry, but it does not terminate sessions that are already open. If we suspect a compromise, we also need to assess existing sessions and other possible routes of access.

On Windows, removing an identity from the agent does not remove its authorisation on the server either. These are different operations: one controls local use of the key, while the other controls access to the remote account.

Should we disable password authentication?

It may be a later step, but it is not necessary to start using keys. Before considering it, we need to have tested key-based access in a new session, backed up the configuration and ensured an alternative recovery route, such as the local console.

On Ubuntu, settings may be in /etc/ssh/sshd_config and in included files under /etc/ssh/sshd_config.d/. Changing a line without understanding the effective configuration may not produce the expected result.

The PasswordAuthentication option controls one specific method; interactive authentication, configured through KbdInteractiveAuthentication, is separate and may be part of additional mechanisms. We should not disable options indiscriminately, particularly when multifactor authentication is in use. The server configuration manual describes these differences.

After a planned change, validate the configuration on Ubuntu before applying the change to the service:

sudo sshd -t

This command checks the configuration and the consistency of the host keys; it does not prove that our next login will work. The Ubuntu documentation recommends this validation and warns about the risk of losing access.

Keep a session open and confirm a new connection after applying any change. Disabling SSH password authentication also does not remove the account password or any password prompts from sudo.

A short command, with the right pieces behind it

In everyday use, the result is simple: open Windows Terminal and type ssh homelab.

Several checks still take place behind that command: recognising the server, selecting the account, presenting an authorised identity and demonstrating access to the private key. The alias avoids repeating the connection details; the agent helps us use the protected key.

That combination makes access more convenient. The password no longer appears at every connection, but authentication is still there — and we now know which file does what, where it belongs and how to revoke authorisation when necessary.