If you've been following along in this series, you already know how I like to do things: terminal-first, no GUI crutches, and every setting explained rather than copy-pasted blindly. Same rules apply here.

Every guide I've written that touches a remote box - the AlmaLinux + Podman + Caddy VPS behind Cloudflare, the Debian 13 workstation I run day to day - eventually assumes you already have SSH keys set up and just... works. I've never actually stopped to explain why I generate keys the way I do, or why I picked the type I picked. So this is that post: the one everyone skips because they've run ssh-keygen a hundred times and stopped thinking about it around the tenth.

Turns out the -t flag you barely glance at actually matters - for security, for performance, and for how much pain you'll have logging into that crusty old appliance nobody's touched since 2019.


The Short Version

If you don't read another word: use Ed25519.

ssh-keygen -t ed25519 -C "you@device-2026"

It's fast, it's small, and nothing about it is cryptographically shaky. Keep RSA-4096 around as your fallback for legacy systems, skip ECDSA entirely for anything new, and if you've got a YubiKey, look at ed25519-sk for hardware-backed logins. Everything below explains the "why."


What ssh-keygen Actually Gives You

ssh-keygen generates a matched pair of files: a private key and a public key. Think of the public key as a lock you hand out to every server you want access to, and the private key as the one physical key that opens all of them. The server never needs to see your private key - it just checks whether whoever's knocking can prove they hold the matching key, using math instead of a password.

That's the whole reason key-based auth beats passwords: nothing secret ever crosses the wire, and there's nothing for a brute-force attempt to guess against.


Generating the Key

ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519

Quick flag breakdown:

  • -t - the algorithm type (this is the part this whole post is about)
  • -C - a comment, usually your email or a label like deploy@prod-2026, so you can tell keys apart later
  • -f - where to save it; skip this and it'll prompt you, defaulting to ~/.ssh/id_ed25519

You'll be asked for a passphrase. Use one. More on that in a second.

Two files get created: id_ed25519 (private) and id_ed25519.pub (public). Only one of them is meant to leave your machine.


The Public Key Goes to the Server - That's the Whole Point

This is the part I see people get backwards more often than you'd expect: the .pub file is the one you copy to the remote machine. The name is your hint - it's public by design. It's meant to be shared.

On any server you want to log into, that public key gets appended to ~/.ssh/authorized_keys for the account you're connecting as. The easiest way to do this:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server

No ssh-copy-id available, or you're bootstrapping a fresh AlmaLinux VPS where password auth is still open for the first login? Do it manually:

cat ~/.ssh/id_ed25519.pub | ssh user@your-server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Once that's in place, the server can verify you without ever needing your private key - it just checks that whoever's connecting can produce a valid signature matching the public key it already has on file.


The Private Key Stays Home - Guard It

The private key (id_ed25519, no .pub extension) is the one thing that should never leave your machine. Not in a Slack message, not in a repo, not attached to a support ticket, not synced to some random cloud drive "just to be safe." If it leaks, anyone with a copy of it can authenticate as you on every server that trusts the matching public key.

A few habits that actually matter:

  • Set a passphrase when you generate it. An unencrypted private key sitting on disk is one stolen laptop away from a full compromise.
  • Lock down permissions. chmod 600 ~/.ssh/id_ed25519 - SSH will straight-up refuse to use a key with overly loose permissions anyway.
  • Use ssh-agent so you're not retyping your passphrase for every connection:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
  • Never generate the key on the server and copy it down to your laptop. Generate locally, ship the public key up. Private keys should be born on the machine that's going to use them.
  • Rotate and revoke. If a key's compromised, pull it from authorized_keys on every host it touched and generate a fresh pair.

So Why Ed25519, Specifically?

Ed25519 (EdDSA over Curve25519) has been OpenSSH's recommended default since 2015, and by 2026 there's honestly no good reason to reach for anything else on a new deployment:

  • Fixed 256-bit key - no size decision to agonize over
  • Deterministic signatures, so there's no reliance on your system's random number generator at signing time
  • Constant-time by design, which closes off an entire category of timing side-channel attacks
  • A 68-byte public key versus roughly 740 bytes for RSA-4096
  • Meaningfully faster signing - useful if you're scripting a lot of connections through Ansible or similar
ssh-keygen -t ed25519 -C "deploy@prod-2026"

GitHub, GitLab, AWS, GCP, Azure, and every VPS provider I've touched support it without complaint.


RSA - Your Legacy Escape Hatch, Not Your Default

RSA has been around for 25 years, and 4096-bit keys are still perfectly secure. But it's slower, the public key is bulkier, and honestly the only reason to reach for it in 2026 is compatibility:

ssh-keygen -t rsa -b 4096 -C "legacy@system"

Keep this one in your back pocket for old appliances, enterprise gear stuck on ancient OpenSSH builds, or anything running something older than RHEL/CentOS 7. If you're not sure why a device needs it, it's probably RSA because nobody's touched its SSH stack in years.


ECDSA - Just Skip It

ECDSA is faster and smaller than RSA on paper, but it comes with baggage I don't think is worth taking on for a brand-new key:

  1. Nonce-reuse risk. A weak or reused random number during signing can leak your private key outright - this isn't hypothetical; it's how the PS3 signing key got pulled in 2010, and it's bitten Bitcoin wallets since.
  2. NIST curve distrust. The P-256 curve parameters have unexplained origins. No proven backdoor, but enough opacity that plenty of security folks avoid it on principle.

There's basically one legitimate reason to touch it in 2026: an old YubiKey whose firmware doesn't support ed25519-sk yet, in which case ecdsa-sk becomes your fallback - not the software-only ecdsa type.


A Quick Word on Quantum

Yes, it's on people's minds, so here's the honest state of things: classical algorithms (RSA, ECDSA, Ed25519) would eventually fall to a sufficiently powerful quantum computer via Shor's algorithm. That computer doesn't exist yet. What's more relevant today is "harvest now, decrypt later" - traffic captured now could theoretically be decrypted down the road.

The good news: key exchange is already handled. OpenSSH has defaulted to post-quantum-resistant key exchange (sntrup761x25519-sha512, and more recently mlkem768x25519-sha256) for a while now - this negotiates automatically and you don't have to do anything.

What's not quantum-resistant yet is the signature side - the actual keys you generate with ssh-keygen. OpenSSH 10.4 added experimental mldsa44-ed25519 hybrid support, but it's not enabled by default and standardization is still moving. For now: use Ed25519, keep an eye on this space, and don't lose sleep over it.


Decision Matrix

Scenario Key Type Command
New deployment (default) Ed25519 ssh-keygen -t ed25519 -C "user@host"
Legacy server (pre-OpenSSH 6.5) RSA-4096 ssh-keygen -t rsa -b 4096 -C "user@host"
Hardware-backed, modern YubiKey ed25519-sk ssh-keygen -t ed25519-sk -O resident
Hardware-backed, older YubiKey ecdsa-sk ssh-keygen -t ecdsa-sk -C "user@host"
High-security interactive login ed25519-sk + verify-required ssh-keygen -t ed25519-sk -O resident -O verify-required

Wrap-Up

The algorithm wars are pretty much settled. Ed25519 won. Generate it, ship the .pub file to whatever server you're logging into, lock the private key down with a passphrase and correct permissions, and keep RSA-4096 around purely as a fallback for the stuff that hasn't caught up yet.