Learn › RHCSA (EX200) › Security
ssh-keygen - a hands-on Linux lab on a real virtual machine.
Replace typed passwords with a cryptographic key pair so logins, and scripts, work without a prompt. Generate the RHEL 10 default with ssh-keygen -t ed25519 -N '' -f, keep the private key locked to mode 600 while the .pub goes out at 644, then install the public half on a remote server with ssh-copy-id user@host for passwordless SSH. Serves EX200 security: configure key-based authentication for SSH.
It is 2 a.m. and a script needs to copy a file from servera to serverb, then restart a service there. It runs ssh serverb, and the terminal stops dead on one line: serverb's password:. The script cannot type a password. There is no human awake to type it either. The whole automated run hangs on a single prompt, and by morning nothing has deployed.
Passwords are fine for a person at a keyboard. They fall apart the moment a machine has to log in to another machine on its own. The fix is key-based authentication: you prove who you are with a cryptographic key instead of a typed secret, and the login just works, silently, every time. This lesson takes you from no keys at all to a passwordless login you could hand to a script. It is a named EX200 objective and a daily reality for anyone who runs more than one server.
The black boxes below are a practice terminal: a safe sandbox that checks the one command each step teaches. The outputs are from a real RHEL 10 machine (AlmaLinux 10.2). One thing is different here from every other lesson: a key pair is unique. The fingerprint and the long base64 key material you see are from one specific key generated on that machine. Yours will be different every single time you run ssh-keygen, and that is correct, not a fault. What is stable everywhere is the SHAPE: two files appear, the private one is mode 600, the public one is mode 644, and only the public one ever leaves your machine.
Key-based authentication replaces a shared password with a matched pair of files: a private key and a public key. They are generated together and are mathematically linked, but they are not interchangeable. Think of the public key as an open padlock and the private key as the only key that opens it. You can hand out copies of the open padlock to anyone. As long as you keep the one key to yourself, only you can open what those padlocks lock.
In practice the split is simple. The private key never leaves the machine it was made on. The public key gets copied onto every server you want to log in to. When you connect, the server uses your public key to pose a challenge that only the matching private key can answer. No password crosses the network, and the private secret never moves.
Three reasons make keys the standard, not the exception. First, automation: a script, a backup job, or a config tool like Ansible cannot type a password, but it can present a key. Second, security: a strong key is far harder to guess or brute-force than a password, and you never send a secret across the wire that could be sniffed. Third, convenience: once a key is in place, ssh serverb just logs you in, no prompt, no typing.
On the exam and on the job, the pattern is always the same. Generate a key pair once. Install the public half on each server you manage. From then on, logins to those servers are passwordless. The rest of this lesson walks that exact path.
The tool that creates a key pair is ssh-keygen. On RHEL 10 you generate an ed25519 key, a modern type that is small, fast, and strong. The flags you need are -t ed25519 to choose that type, -N '' to set an empty passphrase (two single quotes with nothing between them), and -f to name the output file. The private key is written to the path you give -f, and the public key to that same path with .pub added.
Before you run it, know what success looks like: it prints where it saved the two files and a fingerprint line. Generate the pair:
ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519
prompt: [root@servera ~]# answer: ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519 output: The key fingerprint is: SHA256:... root@servera (fingerprint value varies per key) hint: The key generator is ssh-keygen: -t ed25519 for the type, -N '' for no passphrase, -f for the file path.
ssh-keygen built two files and printed a fingerprint, a short SHA256 hash that uniquely names this key. -t ed25519 picked the modern key type that RHEL 10 defaults to. -N '' set an empty passphrase, so the key can be used without you typing anything, which is exactly what a script needs. -f /root/.ssh/id_ed25519 named the private key; the public key was written right next to it as /root/.ssh/id_ed25519.pub. The fingerprint you see will differ from this one and from every key you ever make. That uniqueness is the whole point: your key is yours alone.
The fingerprint and the key material are unique to every key. Run ssh-keygen twice and you get two completely different pairs. So do not expect your fingerprint to match the one printed above. What you SHOULD see match is the structure: a SHA256: fingerprint line, and two files named id_ed25519 and id_ed25519.pub in the .ssh directory.
The public key is a single line of text, safe to share. Its first field names the key type, ssh-ed25519, and the second is the long base64 key material. You can print just those two fields to confirm the type took. cut -d' ' -f1-2 splits the line on spaces and keeps fields one and two.
Read the public key's type and material:
cut -d' ' -f1-2 /root/.ssh/id_ed25519.pub
prompt: [root@servera ~]# answer: cut -d' ' -f1-2 /root/.ssh/id_ed25519.pub output: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXot56w5et/vsAjfUQ5EdXdYbS/1adcrxd4VT8vyV4t hint: cut splits on a delimiter: -d' ' is a space, -f1-2 keeps fields one and two, then the .pub path.
The first field, ssh-ed25519, confirms the key type is what you asked for. The second field is the public key material, a long base64 string. This is the half that is safe to share; it is what gets copied onto every server you want to reach. Your base64 string will be completely different, because it is derived from your unique key. The whole .pub line, including a trailing comment field this command trimmed off, is exactly what lands in a remote server's authorized_keys file.
SSH is strict about file permissions, and this is where most people get stuck. The private key must be readable by no one but its owner: mode 600 (-rw-------). If it is any looser, SSH refuses to use it and you are back to a password prompt. The public key is meant to be shared, so mode 644 (-rw-r--r--) is fine. ssh-keygen sets both correctly for you; ls -l lets you confirm.
Check the permissions on both keys:
ls -l /root/.ssh/id_ed25519 /root/.ssh/id_ed25519.pub
prompt: [root@servera ~]# answer: ls -l /root/.ssh/id_ed25519 /root/.ssh/id_ed25519.pub output: -rw-------. /root/.ssh/id_ed25519 (private key, 600) -rw-r--r--. /root/.ssh/id_ed25519.pub (public key, 644) hint: Long listing with ls -l on both paths: the private key must read -rw------- (600), the public -rw-r--r-- (644).
Two files, two very different permission strings. The private key id_ed25519 shows -rw-------, which is mode 600: read and write for the owner, nothing for anyone else. That secrecy is what keeps the key safe, and SSH enforces it. The public key id_ed25519.pub shows -rw-r--r--, mode 644: the owner can write it, everyone can read it, which is fine because it is meant to be shared. Remember the rule this way: the secret half is locked down to 600, the shareable half is open at 644.
If your private key is too readable, SSH silently ignores it and falls back to asking for a password. The classic symptom is a login that keeps prompting for a password even though you are sure the key is installed. The usual cause is a private key or a .ssh directory with permissions that are too open. Fix it with chmod 600 /root/.ssh/id_ed25519 and chmod 700 /root/.ssh. Never loosen the private key to make it readable by others; that defeats the entire point.
A key pair on your own machine does nothing until the public half is on the server you want to reach. The public key has to be appended to ~/.ssh/authorized_keys in the target user's home on the remote host. You could do that by hand, but there is a tool that does it correctly every time: ssh-copy-id. You give it user@host, it prompts for that user's password ONE last time to get in, then it copies your public key into their authorized_keys and sets the permissions right.
Install your public key on the remote server:
ssh-copy-id user@serverb
prompt: [root@servera ~]# answer: ssh-copy-id user@serverb output: hint: The installer is ssh-copy-id, then user@host: ssh-copy-id user@serverb appends your .pub to their authorized_keys.
That last password prompt is the trade you make: type the password once, so you never have to again. ssh-copy-id logged in to serverb as user, appended your id_ed25519.pub line to ~/.ssh/authorized_keys there, and fixed the permissions on that file and directory. From now on, ssh user@serverb uses your key and logs in with no prompt at all. That is the passwordless login the 2 a.m. script needed. Install the same public key on every server you manage and they are all reachable, silently, by key.
ssh-copy-id needs a password ONCE, on this first install, because that is the only way in before your key is trusted. After that install, logins to that server are key-based and never prompt again. You do not have to use the tool. The manual equivalent is to append the .pub line to the remote ~/.ssh/authorized_keys yourself and set it to mode 600. But ssh-copy-id handles those permissions for you, so it is the safer choice.
Scaffolding off. No command is printed this time. You have every piece you need.
A task hands you a fresh RHEL 10 server. It says: create a key pair for root, using the modern default key type, with no passphrase so a script can use it. Save the private key at /root/.ssh/id_ed25519. You need to name the tool, choose the type flag for the RHEL 10 default, set an empty passphrase, and point the output at that path. Which single command generates that pair?
prompt: [root@servera ~]# answer: ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519 output: The key fingerprint is: SHA256:... root@servera (fingerprint value varies per key) hint: The generator is ssh-keygen. -t ed25519 is the RHEL 10 default type, -N '' is the empty passphrase, -f is the path.
ssh-keygen -t ed25519 -N '' -f /root/.ssh/id_ed25519 builds the pair in one line: ssh-keygen is the tool, -t ed25519 picks the RHEL 10 default type, -N '' sets the empty passphrase a script needs, and -f names the private key path (the public key follows as .pub). That is the first move of every key-based-auth task on the exam. Generate the pair, then install the public half with ssh-copy-id, and the login is passwordless.
You earned this cheat sheet. Every row is a form you just ran or built:
The one thing to burn in for the exam: the private key (mode 600) NEVER leaves your machine, the public key (mode 644) is the only half you copy out, and ssh-copy-id user@host is how you copy it. ed25519 is the RHEL 10 default type.
The empty passphrase from -N '' is what makes a key usable by an unattended script. For a key you use yourself, a passphrase adds a layer of safety: even if the private key file is stolen, it is useless without the phrase. You can then load it once per session with ssh-add so you are not typing the passphrase on every connection. For the exam objective, the passwordless pattern shown here is the one to know cold.
The practice terminal has walked you through the whole loop. ssh-keygen -t ed25519 builds the pair, and you read the public half. ls -l confirms the 600 and 644 permissions that SSH insists on. ssh-copy-id user@host installs the public key on a remote server so the login goes passwordless. Every one of those you typed yourself.
Operation Lockdown, the security capstone, is where you run these against a real RHEL 10 VM. A full machine boots for you, and the mission hands you objectives that use exactly what you practiced here, alongside the firewall and SELinux work from the rest of this module. Set up key-based authentication for a user, confirm the private key is locked to 600, and prove a login works without a password. One difference from this lesson: the mission shows no commands. You read the objective, recall the ssh-keygen and ssh-copy-id forms, and type them. That recall is what makes it stick on exam day.
Finish the other security lessons, then go lock down a real server in Operation Lockdown.
Practice SSH Key-Based Authentication in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.