May 2026 · Devops · 7 min read

Learn SSH early, thank yourself later

One of the first things I picked up, and one of the few I still reach for every single day. From your first connection to logging in with a single word.

the ticket queue · prerequisite
sshkeyslinuxfoundations
before you start: you need two things. A terminal (macOS and Linux already have one; on Windows, use Windows Terminal or WSL) and a machine to connect to. No server yet? The Build your server1 post stands one up in a few minutes. For now, anything you can reach works.

Here’s the thing nobody mentions on day one: the servers you’ll spend a career fixing are almost never in the room with you. They’re in a rack in another building, a data center in another state, a cloud region you will never physically see. You don’t walk up to them. You SSH in.

SSH is an encrypted tunnel to a shell on another machine. You type on your laptop, the commands run over there, the output comes back. Every job on a remote server opens the same way: get into the box, then fix the box. So before any of that, this.

First, where is the machine?

You can’t SSH somewhere without knowing where it is. When you spin up a VM or get handed a server, the first thing you need is its IP address. Run this on the machine itself, at its console:

bash
hostname -I
# 192.168.1.50

hostname -I prints just the address, nothing else. If you want the fuller picture, including which interface it’s on:

bash
ip a
# find the 'inet' line under your main interface.
# ignore 'lo' / 127.0.0.1 -- that's loopback, it only ever
# means "this machine talking to itself."

The address that isn’t 127.0.0.1 is the one you connect to. Write it down. That’s your destination for the next step.

If SSH isn’t even running yet

A fresh server doesn’t always have SSH turned on, especially a minimal install. If your connection gets Connection refused, the service probably isn’t running. You fix that from the machine’s own console, because you can’t SSH into a box whose SSH is off. That’s the chicken and egg of it.

First, check what state it’s in:

bash
systemctl status sshd

Three things can be true. It’s running, in which case your problem is elsewhere. It’s installed but stopped. Or it isn’t installed at all.

// installed but stopped: turn it on
bash
systemctl enable --now sshd

enable means start at every boot. —now means also start it this second. You want both, so it survives a reboot and you never think about it again.

// not installed: get it, then turn it on
bash
dnf install -y openssh-server
systemctl enable --now sshd
// let it through the firewall

RHEL usually allows SSH by default, but on a locked-down box you may have to add it:

bash
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload

—permanent writes the rule so it survives a reboot. —reload applies it right now. Skip the reload and the rule exists but isn’t live yet.

// confirm it’s listening
bash
ss -tlnp | grep :22
# LISTEN  0  128  0.0.0.0:22  ...   -> sshd is up and accepting connections

Once you see something listening on port 22, go back to your laptop and connect.

not on RHEL? On Debian or Ubuntu the package is also openssh-server, but the service is usually named ssh, and the firewall is ufw (ufw allow ssh). The idea is identical: install it, enable it, let it through the firewall.

The first connection

The whole thing is one command. A user, an @ sign, and where the machine lives.

bash
ssh op@192.168.1.50
# ssh <user>@<machine>
# user    = the account you're logging in as
# machine = an IP address (here) or a hostname

The very first time you connect to a machine, SSH stops and asks you something that looks alarming and isn’t:

output
The authenticity of host '192.168.1.50' can't be established.
ED25519 key fingerprint is SHA256:Xy3...9aQ.
Are you sure you want to continue connecting (yes/no)?

That’s SSH showing you the server’s fingerprint and asking if you recognize it. Type yes. It writes the fingerprint to a file called ~/.ssh/known_hosts and never asks again for that machine. From now on, if that fingerprint ever changes, SSH will refuse to connect and warn you loudly, which is the point. More on that in a minute.

Wait, which box am I on?

Once you can hop between machines, you will eventually lose track of which one you’re standing on. This sounds harmless. It is not. The classic outage is someone running a cleanup command they meant for a test box while logged into production. Two commands keep you honest.

bash
whoami
# op        -> the account you're logged in as

hostname
# db01      -> the machine you're currently on

Your prompt is usually already telling you both. A prompt like op@db01:~$ reads as: user op, on host db01, sitting in the home directory. Glance at it before you run anything destructive. On the day it matters, that half-second look is the difference between a closed ticket and a brand new, much worse one.

Stop typing your password: keys

You can log in with a password, but you shouldn’t, and once your keys are set up you won’t want to. Instead you make a key pair once, hand the public half to the server, and never type a password into that box again.

// 1. make the key pair
bash
ssh-keygen -t ed25519 -C "op@projectpattie"

This makes two files in ~/.ssh/. id_ed25519 is your private key. It never leaves your machine, you never share it, you never paste it anywhere. id_ed25519.pub is the public half, which is safe to hand out. It’ll ask where to save and whether you want a passphrase. Defaults are fine; a passphrase adds one more layer if your laptop ever walks off.

// 2. put the public key on the server
bash
ssh-copy-id op@192.168.1.50

This logs in once with your password and appends your public key to the server’s ~/.ssh/authorized_keys. That’s the list of keys the server trusts. Do it once per machine.

// 3. log in with no password
bash
ssh op@192.168.1.50
# straight in. no password prompt.
// deep dive: why a key beats a password

A password is a secret you send to the server every single time you log in. Anything sitting between you and the server that can read that exchange now has your password, and people pick guessable ones anyway. A key pair works differently. The private key never leaves your laptop. The server only ever sees the public half, which is useless on its own. Logging in becomes a math problem the server poses and only your private key can answer, so there is nothing worth stealing in transit. That’s the real reason to set up keys: once it’s done, you stop thinking about logging in and start thinking about the actual problem.

Make it one word: the config file

Typing ssh op@192.168.1.50 forty times a day gets old, and you’ll have more than one machine. So you save the details once. Open (or create) ~/.ssh/config and add a block:

~/.ssh/config
Host db01
    HostName 192.168.1.50
    User op
    IdentityFile ~/.ssh/id_ed25519

Now the whole command is just the nickname:

bash
ssh db01

This is why a single short word like db01 is enough to connect. The machine, the user, and the key are all saved here. Set it up once per box and every login after that is just the nickname.

When it won’t connect

It will not always work on the first try. Here are the four you’ll actually hit, and what each one is really telling you.

What you seeWhat it meansWhat to do
Connection refusedNothing is listening on port 22. The SSH service is down, or a firewall is blocking it.Turn the service on from the console. See “If SSH isn’t even running yet” above.
Permission denied (publickey,password)Wrong username, wrong password, or your key isn’t on the server.Recheck the user, or run ssh-copy-id again.
REMOTE HOST IDENTIFICATION HAS CHANGEDThe server’s fingerprint changed. Usually a rebuilt machine. Occasionally something hostile.If you trust the change: ssh-keygen -R 192.168.1.50, then reconnect.
Could not resolve hostnameA typo, or DNS doesn’t know that name.Check the spelling, or try the raw IP address.

Command reference

The whole post in one table. Copy from here.

CommandWhat it does
ssh user@hostOpen an encrypted shell on a remote machine.
hostname -IPrint the machine’s IP address, so you know where to connect.
ip aShow every network interface and its address (ignore lo, that’s loopback).
whoamiPrint which user you’re logged in as.
hostnamePrint which machine you’re currently on.
systemctl status sshdCheck whether the SSH service is running on the server.
systemctl enable —now sshdTurn SSH on right now and at every boot.
firewall-cmd —permanent —add-service=sshLet SSH through the firewall (follow with —reload).
ss -tlnp | grep :22Confirm something is listening on the SSH port.
ssh-keygen -t ed25519Make a key pair: a private half you keep, a public half you share.
ssh-copy-id user@hostInstall your public key on the server so it stops asking for a password.
ssh db01Connect using a saved ~/.ssh/config alias, no long command.
ssh-keygen -R hostForget a server’s old fingerprint after it legitimately changes.
ssh -v user@hostConnect with verbose output, for when you need to see why it fails.
exitClose the remote shell and land back on your own machine.
you’re ready when: you can run ssh db01, land on the server with no password prompt, and get back out with exit. That’s the door. Everything else you do on a server happens on the other side of it.
// put this to use
This is the door to the Ticket Queue: real help-desk tickets you work on one RHEL 9 box. Build your server1, then take the first ticket.