CoursesLinux essentialsConnecting with SSH

Connecting with SSH

ssh, keys, scp — reach a remote server.

Beginner12 min · lesson 11 of 25

Every server you will ever run lives somewhere you are not. It sits in a data center in another city, or it is a virtual machine (a whole computer that exists only as software running on shared hardware) in the cloud that you will never physically touch. You still have to type commands on it as if you were standing at its keyboard. SSH (Secure Shell, a way to open an encrypted command-line session on a distant computer) is how you do that. It is the front door to almost every Linux machine in operations, and you will use it every single day.

The simplest form is ssh user@host. You name who you want to be on the far machine and which machine to reach, and SSH opens a shell there. A shell is the program that reads your typed commands and runs them. Once you are connected, your terminal is that remote computer for as long as the session lasts.

~/secopslog — bash
The authenticity of host 'web-01.acme.internal (10.0.4.21)' can't be established. ED25519 key fingerprint is SHA256:uReM2l0vQ7c9k3Xb1n8pFhZ4tWqS6dJyaE0oNcgViUk. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'web-01.acme.internal' (ED25519) to the list of known hosts. [email protected]'s password: Linux web-01 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 Last login: Fri Jul 17 08:52:10 2026 from 10.0.4.10 deploy@web-01:~$

For those few seconds you are a user named deploy on a machine called web-01. Run hostname to prove it, then type exit (or press Ctrl-D) to hang up and land back on your own laptop.

~/secopslog — bash
$ deploy@web-01:~$ hostname deploy@web-01:~$ exit
web-01 logout Connection to web-01.acme.internal closed. $

Notice the one weak spot in that first login: a password prompt. Passwords can be guessed, phished, and reused. The next section replaces them with something far stronger.

Keys Beat Passwords

A password is a secret you both know, and you send it (encrypted) down the line every time you log in. A key pair works differently, more like a wax seal that only your signet ring can stamp. You hold a private key (a secret file that never leaves your laptop) and you hand out a public key (a matching file that is safe to show anyone). The server keeps your public key on file. When you connect, the server sends a puzzle that can only be answered by whoever holds the private key, and your machine answers it without ever sending the secret across the wire. You generate both files at once with ssh-keygen.

~/secopslog — bash
$ ssh-keygen -t ed25519 -C "you@laptop"
Generating public/private ed25519 key pair. Enter file in which to save the key (/home/you/.ssh/id_ed25519): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/you/.ssh/id_ed25519 Your public key has been saved in /home/you/.ssh/id_ed25519.pub The key fingerprint is: SHA256:H8kq2mVn7pLc0QwZaX4bR1tYsE9dJf3gUvB6nK5woXb you@laptop The key's randomart image is: +--[ED25519 256]--+ | . .. | | o . . | | o + o | | + = + | | o o S . | | o.+.o | | . *.B. | | E.= o | | ..o | +----[SHA256]-----+

The -t ed25519 flag picks the key type. ed25519 is a modern algorithm that makes short, fast, strong keys; prefer it over RSA (an older key type that has to be much longer to reach the same strength). You now have two files. id_ed25519 is the private key, the secret. id_ed25519.pub is the public key, safe to share. Install the public one on the server with ssh-copy-id, which asks for your password one last time.

~/secopslog — bash
$ ssh-copy-id [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/you/.ssh/id_ed25519.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys [email protected]'s password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh '[email protected]'" and check to make sure that only the key(s) you wanted were added.

Under the hood, ssh-copy-id appended your public key to a file named ~/.ssh/authorized_keys on the server. That file is the guest list: every public key in it is allowed to log in as that user. From now on, SSH answers the puzzle for you and no password is asked. If you set a passphrase on the key, your machine prompts for it once and a helper called ssh-agent (a small program that holds your decrypted key in memory) remembers it for the rest of your session.

~/secopslog — bash
deploy@web-01:~$
Your private key is the login
The file without the .pub ending (id_ed25519) is the credential itself. Anyone who copies it can log in as you, no password needed. Give it a passphrase when you generate it, keep its permissions at 600 (readable and writable only by you), never commit it to a git repository (a project's version-controlled folder), and never copy it onto a server. Only the .pub file belongs anywhere other than your own laptop.

SSH takes those permissions seriously enough to refuse a private key that the rest of the system can read. Loosen them by mistake and the login fails in a way that confuses a lot of newcomers.

~/secopslog — bash
$ chmod 644 ~/.ssh/id_ed25519 # too open, on purpose ssh [email protected]
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0644 for '/home/you/.ssh/id_ed25519' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. Load key "/home/you/.ssh/id_ed25519": bad permissions [email protected]: Permission denied (publickey).
$ chmod 600 ~/.ssh/id_ed25519 ls -l ~/.ssh/id_ed25519
-rw------- 1 you you 411 Jul 17 09:14 /home/you/.ssh/id_ed25519

Trust On First Connection

Go back to that first prompt asking you to confirm a fingerprint. Every server has its own key pair too, and when you first reach one, SSH shows you the server's host key fingerprint (a short, unique digest of the server's own public key) and asks whether you trust it. Say yes and SSH records that key in ~/.ssh/known_hosts. It is like memorizing a friend's voice on your first phone call so you notice at once if an impostor picks up later. Every future connection is checked against the saved key without asking again.

This check is what stands between you and a machine-in-the-middle attack, sometimes called man-in-the-middle, where someone sits on the network between you and the real server, pretends to be it, and quietly records everything you type, a typed password included. If the host key ever fails to match what you saved, SSH stops the connection cold and shows a loud warning. Read that warning. Do not paste a reflexive yes to make it go away.

Read the host-key-changed warning
If SSH refuses to connect and shouts REMOTE HOST IDENTIFICATION HAS CHANGED, it might be a legitimately rebuilt server, or it might be someone intercepting you right now. Confirm the real fingerprint through a separate, trusted channel before clearing the old entry with ssh-keygen -R web-01.acme.internal. Wiping it out of habit throws away the exact protection the check exists to give you.
What happens when you run ssh
1You run ssh user@host
your laptop opens a connection to the server
2The two machines agree on encryption
a key exchange scrambles all traffic from here on
3The server proves who it is
its host key is checked against known_hosts
4You prove who you are
your private key answers the server's challenge, over the encrypted link
5A shell starts
you type commands on the remote machine

Moving Files With scp

SSH does not only carry keystrokes, it can carry files down the same protected connection. scp (secure copy, a file-transfer tool built on SSH) works like cp (the ordinary local copy command), except one side is a remote machine. You write the remote location as host:path, with the path after the colon.

~/secopslog — bash
$ scp report.tar.gz [email protected]:/opt/app/
report.tar.gz 100% 14MB 38.7MB/s 00:00

To pull a file back the other way, put the remote side first and a local destination last.

~/secopslog — bash
$ scp [email protected]:/var/log/app/error.log ./
error.log 100% 2183KB 21.4MB/s 00:00

For large or repeated transfers, most engineers reach for rsync (a copy tool that sends only the parts that changed), but scp is on every machine and fine for a one-off file.

An Address Book For Servers

Typing [email protected] over and over gets old fast, and real infrastructure has dozens of hosts. The file ~/.ssh/config is your address book. You give each server a short nickname and record its real address, the login user, and which key to use, the way saved contacts on a phone let you tap a name instead of dialing a number.

~/.ssh/config
Host web01
HostName web-01.acme.internal
User deploy
IdentityFile ~/.ssh/id_ed25519
Host bastion
HostName jump.acme.internal
User deploy
# reach db01 by hopping through the bastion first
Host db01
HostName db-01.internal
User deploy
ProxyJump bastion

Now ssh web01 expands into the full command with the right user and key. The last entry shows a jump host (a hardened gateway that is the only machine allowed to reach the private servers behind it). ProxyJump tells SSH to tunnel through bastion to get to db01. Real networks hide their database and application servers from the public internet and force every login through one audited entry point, which is both cleaner and safer.

~/secopslog — bash
$ ssh web01
deploy@web-01:~$

scp reads the same nicknames, so scp report.tar.gz web01:/opt/app/ does the full transfer with no long hostname to remember.

Quick check
01The first time you connect to a new server, SSH prints a fingerprint and asks you to confirm before letting you in. What does saying yes actually protect you from on later connections?
Correct — The saved host key lets SSH notice if a future connection is really an impostor sitting in the middle.
Incorrect — No. Password strength is a separate concern; the fingerprint check is about the server's identity, not the strength of your secret.
Incorrect — No. That risk is handled by file permissions and a passphrase, not by the host key prompt.
Incorrect — No. SSH encrypts the session either way; the check decides who you are encrypting with.
02You run ssh-keygen and end up with two files, id_ed25519 and id_ed25519.pub. To log in without a password, which file goes on the server, and how does it get there?
Incorrect — the private key is the credential itself and must never leave your laptop; copying it to a server is exactly the mistake to avoid.
Incorrect — the server only ever needs the public key; the private key stays secret on your own machine.
Correct — ssh-copy-id adds your public key to the server's authorized_keys, the guest list of keys allowed to log in.
Incorrect — the passphrase only unlocks your local private key; the server authenticates against the public key it holds.
03You try to log in and SSH prints: 'UNPROTECTED PRIVATE KEY FILE! ... Permissions 0644 for id_ed25519 are too open ... This private key will be ignored ... Permission denied (publickey).' What happened, and what fixes it?
Incorrect — nothing was deleted; SSH simply refused to use a key file that other accounts can read.
Correct — SSH ignores a private key whose permissions let anyone else read it, and restoring 600 (owner-only) lets the login proceed.
Incorrect — that is the separate REMOTE HOST IDENTIFICATION HAS CHANGED warning, not this file-permissions error.
Incorrect — the message is about the local key file's permissions, not a missing key on the server.

One habit closes the loop on all of this. Every public key in a server's authorized_keys file is a live, working login, and keys tend to outlive the people who added them. Read that file now and then on any machine you run.

~/secopslog — bash
$ deploy@web-01:~$ cat ~/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8kq2m...9tRv you@laptop ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB2pLc0...QwZa contractor@oldlaptop

That second line belongs to a contractor who left months ago, and it still opens the door. Deleting the stale lines that no longer belong is one of the cheapest security wins you have on any server you touch. Open the file, remove the line, save, and that key is no longer a way in.

Try this

Work through “An Address Book For Servers” yourself on a sandbox you can throw away, following the commands above in order. Then break one step deliberately and re-run, so you have seen the failure before it finds you.

Takeaway

The trap worth remembering here: your private key is the login. Check that on your own systems before you need to, because it is cheaper to find on a quiet afternoon than during an incident.

Related