Connecting to a server via SSH: Windows, macOS and Linux
The first SSH connection step by step: PuTTY and OpenSSH on Windows, Terminal on macOS and Linux, checking the fingerprint properly, transferring files and fixing the usual error messages.
A freshly ordered server arrives without a monitor and without a keyboard. The only way in is SSH, the Secure Shell protocol. This article walks you through the first connection from three operating systems, explains the fingerprint prompt (the one almost every beginner clicks away without reading) and shows how to transfer files. At the end comes the part most guides leave out: what to do when it does not work, and how to tell that it really did work.
Everything here has been verified on Debian 13, Debian 12, Ubuntu 24.04 LTS and Ubuntu 22.04 LTS. Wherever the four differ, it is stated explicitly. The commands on the server run as root. On your own machine you work with a normal user account instead, which is why every command that changes the system is prefixed with sudo there.
What you need before the first connection
Three pieces of information are enough: the IP address of the server, the user name and either the password or the private key. At KernelHost you find the IP and the login details in the customer panel once the server has been provisioned. On a freshly installed KVM root server or dedicated server the default user is almost always root.
The port is the fourth item. The default is 22. You only need a different number if you changed it yourself or the image moved it. Memorize one trap right now, it saves time later: ssh writes the port in lower case (-p), scp writes it in upper case (-P).
All examples use 203.0.113.10. That address is officially reserved for documentation and does not exist. Replace it with the IP of your server.
The first connection on Linux and macOS
Both systems ship with the OpenSSH client. On macOS you open Terminal (in the Utilities folder), on Linux any terminal window. The command is identical on both:
ssh root@203.0.113.10
If SSH runs on a different port:
ssh -p 2222 root@203.0.113.10
If your system does not know ssh at all, which happens on very lean container or minimal installations, this is how you check and install it:
ssh -V
sudo apt update
apt-cache policy openssh-client
sudo apt install -y openssh-client
The order is deliberate. ssh -V is the check, not the proof of success: if the shell answers with bash: ssh: command not found, the openssh-client package is missing and you install it afterwards with sudo apt install -y openssh-client. sudo apt update belongs before apt-cache policy openssh-client, because without freshly read package lists that command stays empty or only reports Installed: (none). And the sudo is not decoration: without administrator rights apt aborts with Could not open lock file /var/lib/apt/lists/lock.
ssh -V prints the version to standard error, not to standard output. That is not a bug, it has always worked that way. On Debian 13 you see OpenSSH_10.0p2, on Debian 12 OpenSSH_9.2p1, on Ubuntu 24.04 OpenSSH_9.6p1 and on Ubuntu 22.04 OpenSSH_8.9p1. These numbers matter later, because the behavior of scp changed exactly between those versions.
The fingerprint, and why you should not click it away
On the very first connection attempt, SSH asks:
The authenticity of host '203.0.113.10 (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:qWU2Zx9mF7hLtHkQ4gRXn0aVbC3sYpJ8dKe1TmNoPU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
What happens here: every SSH server generates its own key pair during installation, the so called host key. The fingerprint is a short checksum of the public part. Your client does not know this server yet and therefore cannot guarantee that the machine at the other end really is your server, and not somebody who has slipped in between.
If you type yes, the fingerprint is stored in ~/.ssh/known_hosts. From then on your client silently checks on every further connection whether the server presents the same key. This single question is the moment when the entire trust model is established. Nobody asks again after that.
You can only verify it properly over a second, independent channel. On a KVM server the console in the customer panel is the obvious choice: you log in locally there, completely without the network, and print the fingerprint.
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
The output looks like this:
256 SHA256:qWU2Zx9mF7hLtHkQ4gRXn0aVbC3sYpJ8dKe1TmNoPU root@server (ED25519)
If the part after SHA256: matches what your client shows, everything is in order. If you want to try the format out safely, generate a throwaway key locally:
ssh-keygen -t ed25519 -f /tmp/demo -N "" -C demo
ssh-keygen -lf /tmp/demo.pub
Two remarks from practice. First: a server usually has several host keys (ED25519, ECDSA, RSA). The ED25519 key is normally the one displayed, because modern clients prefer it. If you accidentally compare against ssh_host_rsa_key.pub, nothing matches even though everything is correct. Second: StrictHostKeyChecking=no switches the check off completely and is no solution, it simply disables the security feature. If you need automation, -o StrictHostKeyChecking=accept-new is the right choice: it accepts unknown servers automatically, but still warns you when a key changes.
Windows: the built-in OpenSSH client
Since Windows 10 version 1809, Microsoft ships the same OpenSSH client that Linux and macOS use. You no longer need an extra program. Open PowerShell, the Command Prompt or Windows Terminal and type the same command as above:
ssh root@203.0.113.10
On Windows 10 and Windows 11 the client is an optional component that is already active on most installations. If it is not, you check and install it in a PowerShell with administrator rights:
Get-WindowsCapability -Online -Name OpenSSH.Client*
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Alternatively through Settings, System, Optional features. The programs then live in C:\Windows\System32\OpenSSH\, your configuration and the known host keys in %USERPROFILE%\.ssh\, so typically C:\Users\Name\.ssh\known_hosts.
The Windows version lags behind the Linux version. On current Windows 11 installations ssh -V usually reports OpenSSH_for_Windows_9.5p2. For everyday work that is perfectly sufficient.
There is one peculiarity after all: Windows file permissions. If you store a private key that other accounts are allowed to read as well, SSH refuses to work and answers with Permissions for 'C:\Users\Name\.ssh\id_ed25519' are too open. This is how you repair it:
icacls "$env:USERPROFILE\.ssh\id_ed25519" /inheritance:r /grant:r "$($env:USERNAME):(R)"
Windows: PuTTY
PuTTY was the standard route on Windows for years, and it has stayed that way for many people. The current release is version 0.84 from May 2026. Download it exclusively from the author's own page (chiark.greenend.org.uk) and not from download portals, because forged PuTTY builds with built-in password theft have shown up several times in the past.
The procedure: in Host Name (or IP address) you enter the IP, at Port 22, connection type SSH, then Open. If you want to keep the connection, write a name into Saved Sessions first and click Save. PuTTY asks for the user name inside the session window, or you store it under Connection, Data, Auto-login username.
On the first connection the PuTTY Security Alert window appears with the note that the host key is not cached. It shows the same SHA256 fingerprint that OpenSSH displays, so you can compare the two one to one. Accept stores the key permanently, Connect Once connects this one time without storing anything, Cancel aborts.
An important difference to OpenSSH: PuTTY has no known_hosts file. The keys end up in the registry under HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys. If you want to clean up there after reinstalling your server, open regedit and delete the matching entry. And one more trap: PuTTY uses its own key format (.ppk). An OpenSSH key has to be converted with PuTTYgen via Conversions, Import key before PuTTY can use it.
Transferring files with scp and sftp
scp copies files just like cp, only across the network. Uploading a file:
scp backup.tar.gz root@203.0.113.10:/root/
Downloading a file (the dot at the end means: into the current directory):
scp root@203.0.113.10:/var/log/syslog .
A whole directory, and with a non-standard port:
scp -r website root@203.0.113.10:/var/www/
scp -P 2222 backup.tar.gz root@203.0.113.10:/root/
sftp is the interactive variant, handy when you first want to look around and see what is where:
sftp root@203.0.113.10
After that you work with ls, cd, get file, put file on the remote side and with lls, lcd on your own machine. bye ends the session. Both programs exist on Windows too, they are part of the same installation. PuTTY brings its own counterparts along as pscp and psftp, and anyone who wants a graphical interface takes WinSCP.
And here is the difference that trips up a lot of people: since OpenSSH 9.0, scp no longer transfers over the old SCP protocol internally but over SFTP. That affects Debian 13, Debian 12 and Ubuntu 24.04. Ubuntu 22.04 with OpenSSH 8.9 still uses the old method. In practice you notice it in two places. Wildcards such as *.log in a remote path are evaluated differently, and if the remote side offers no SFTP (network devices, for example, or a restricted chroot), the transfer aborts with:
subsystem request failed on channel 0
scp: Connection closed
The stopgap for this is scp -O, which forces the old protocol. The clean solution is to enable the line Subsystem sftp /usr/lib/openssh/sftp-server in /etc/ssh/sshd_config on the server. On Debian and Ubuntu the required package openssh-sftp-server is pulled in as a dependency of openssh-server, so it is only missing on very idiosyncratically assembled installations.
The known_hosts warning after a reinstall
You reinstall your server, connect, and instead of the shell prompt a wall of exclamation marks appears:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
Offending ED25519 key in /home/tom/.ssh/known_hosts:7
Host key for 203.0.113.10 has changed and you have requested strict checking.
Host key verification failed.
This is not an error, it is exactly the feature you typed yes for the first time round. On a reinstall the server generates new host keys, so the old entry no longer matches. Incidentally, the same message also appears when the same IP address has been passed on to another customer, or when you have started a copy of the server.
Before you delete the entry, think for a moment: did you really just reinstall? If so, remove the old line:
ssh-keygen -R 203.0.113.10
With a non-standard port the entry belongs in square brackets, otherwise the command finds nothing:
ssh-keygen -R "[203.0.113.10]:2222"
Whether an entry exists at all is revealed by ssh-keygen -F 203.0.113.10. Looking with a text editor rarely helps, because Debian and Ubuntu store the host names in known_hosts as hashes by default. You cannot search there, which is exactly why the two commands above exist.
On the next connection attempt SSH asks for the fingerprint again. That is the moment to check it once more against the console in the customer panel, instead of typing yes reflexively. This second chance is the whole point of the warning.
On Windows, ssh-keygen -R works exactly the same way in PowerShell. If you use PuTTY, delete the registry entry instead, or confirm in the WARNING - POTENTIAL SECURITY BREACH! window with Accept that the new key should be stored.
Error messages verbatim, and what is behind them
In our experience the following messages cover the vast majority of all cases.
- Connection refused: the connection reached the server, but nobody is listening on that port. Either the SSH service is not running, or it listens on a different port. Through the console you check with
systemctl status sshandss -tlnpwhether port 22 is in use. - Connection timed out: no answer came back at all. Typical for a wrong IP, a powered off server or a firewall that drops packets instead of rejecting them. Check the IP address character by character, then the firewall rules.
- Permission denied, please try again.: user name or password are wrong. The most common cause is the wrong user, for example
rootinstead ofubuntuor the other way round. - Permission denied (publickey).: the server accepts no passwords at all, only keys. On many cloud images that is the default. Either you install your public key, or you temporarily allow
PasswordAuthentication yesthrough the console. - Too many authentication failures: your agent offers too many keys one after another and the server gives up first. Remedy:
ssh -o IdentitiesOnly=yes -i ~/.ssh/my_key root@203.0.113.10. - WARNING: UNPROTECTED PRIVATE KEY FILE! together with Permissions 0644 for ... are too open: the private key is readable by others and is therefore ignored. On Linux and macOS
chmod 600on the key file helps, on Windows theicaclscommand further up. - Bad owner or permissions on ~/.ssh/config: the same cause, only for the configuration file.
chmod 600 ~/.ssh/config. - kex_exchange_identification: read: Connection reset by peer: the connection was cut in the middle of the handshake. In practice this is almost always an automatic ban after several failed attempts, for instance by fail2ban. Wait out the ban time, or lift it through the console with
fail2ban-client unban IPADDRESS. - no matching host key type found. Their offer: ssh-rsa: the server only offers RSA keys signed with SHA-1. Those have been rejected since OpenSSH 8.8, which affects all four systems covered here in their role as client. The right answer is to update the old server, not to weaken the client.
- client_loop: send disconnect: Broken pipe: the session fell asleep and was cleaned up by a firewall or a router. Add
ServerAliveInterval 60to~/.ssh/configand the line stays warm.
Ground rule for all work on the SSH configuration: keep a working session open while you test. Restarting the SSH service does not throw existing connections out. If you lock yourself out with a broken configuration, that second session or the console in the customer panel gets you back in.
Differences between Debian 13, Debian 12, Ubuntu 24.04 and 22.04
For establishing the connection itself, all four behave the same. As soon as you change something on the server, they diverge.
Socket activation instead of a permanent service
Since 22.10, Ubuntu no longer runs the SSH service permanently but starts it on the first incoming connection. The unit responsible is ssh.socket, not ssh.service. This applies to Ubuntu 24.04 and, on freshly installed systems, to Debian 13 as well. Debian 12 still uses the classic permanent service.
Two consequences. First, a Port 2222 in /etc/ssh/sshd_config changes nothing there, because it is no longer sshd that listens on the port but systemd. The port then belongs in a drop-in file that you create with systemctl edit ssh.socket, with ListenStream= to reset the default and a second line ListenStream=2222. Second, systemctl reload ssh can abort with fatal: Cannot bind any address on freshly installed Debian 13 systems. In that case use systemctl restart ssh.service, or switch socket activation off entirely with systemctl disable --now ssh.socket.
Algorithms and legacy baggage
Debian 13 ships OpenSSH 10.0 and no longer knows DSA keys at all, not even through a compatibility switch. If you still have an ancient key in use, generate a new one beforehand. Very recent clients (macOS 26.3 and newer with OpenSSH 10.1 or higher) also print a notice when the server offers no post-quantum key exchange:
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
That is a warning, not an error, and the connection is established anyway. It disappears as soon as the server is recent enough. Debian 12 and Ubuntu 24.04 meet the requirement, Ubuntu 22.04 with OpenSSH 8.9 does not in its default configuration.
A word about older versions
Debian 10 has been out of support since June 2024, Ubuntu 20.04 since May 2025. Neither receives security updates for OpenSSH any more. A server that is reachable over SSH from the internet should no longer run on either of them.
Less typing with ~/.ssh/config
As soon as you look after more than one server, the configuration file pays off. Create it and set the permissions, otherwise SSH refuses to use it:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config
An entry in it looks like this:
Host web1
HostName 203.0.113.10
User root
Port 2222
ServerAliveInterval 60
After that ssh web1 is enough, and scp file web1:/root/ works with it too. The Windows client understands the same file, where it lives under %USERPROFILE%\.ssh\config.
You do not have to guess whether your block actually takes effect. ssh -G shows the final configuration without opening a connection:
ssh -G localhost
Replace localhost with your short name, and the lines hostname, user and port tell you in black and white what SSH is about to use. A typo in the Host name shows up within two seconds this way, instead of after twenty minutes of troubleshooting.
How to tell that it really worked
A shell prompt that appears is not proof yet. With several windows open, more than one admin has fired an rm on the wrong server. Four short commands create clarity:
hostname
id
cat /etc/os-release
uptime
hostname has to show the name of your server, not the name of your laptop. id shows uid=0(root) when you are working as root. cat /etc/os-release names the distribution and the version, so something like Debian GNU/Linux 13 (trixie) or Ubuntu 24.04.3 LTS. And uptime fits the runtime of a server, not that of a workstation that gets shut down every evening.
The fastest test of whether you are really on SSH and not sitting in a local terminal:
echo $SSH_CONNECTION
If a line with four values comes back (your IP, your source port, the server IP, the destination port), you are logged in. If it stays empty, you are typing on your own machine. The session is ended with exit or the key combination Ctrl and D.
Where to go from here
The next sensible step is the move from passwords to keys. An SSH key cannot be guessed, and afterwards you can switch password login off completely, which makes the bulk of automated attack attempts run into nothing. How that works is described in Setting up SSH key authentication. After that come the firewall and automatic banning, covered in Securing a server after installation.
For a start: once you are in, have verified the fingerprint and know how to get back in after a reinstall, the hardest part is done. Everything else happens in a window that you can open right now.
Frequently asked questions
How do I connect via SSH on Windows without installing PuTTY?
What does the fingerprint prompt on the first connection mean?
After a reinstall SSH reports REMOTE HOST IDENTIFICATION HAS CHANGED. What now?
Why does ssh use -p and scp use -P, but not the other way round?
scp aborts with subsystem request failed on channel 0. What causes that?
Why does the port change in sshd_config have no effect on Ubuntu 24.04?
How do I know that I really landed on the right server?
2026 KernelHost GmbH. All rights reserved. This guide is protected by copyright. Republishing it on other websites, in whole, in part or in edited form, is not permitted without our written consent. Quoting with a source credit and a link is expressly welcome.

