How to Create an SSH Key: ssh-keygen Ed25519 on Linux, Mac and Windows
CodexFuse Team · 2026-11-04T10:44:24.554Z · 13 min read min read
Create your first SSH key in minutes: the ssh-keygen Ed25519 workflow on Linux, macOS and Windows, ssh-copy-id server install, and ssh-agent so you never retype your passphrase.
Learning how to create an SSH key is the single most useful security upgrade a new server admin can make: one command replaces password logins with a cryptographic key pair, and it takes under a minute. You run ssh-keygen, accept the default file location, choose a passphrase, and copy the public half to your server — from then on you log in without typing a password, and bots cannot brute-force a key. If you would rather skip the terminal, CodexFuse's SSH key generator builds an Ed25519 pair in your browser (client-side, so the private key never leaves your machine); the rest of this guide uses ssh-keygen itself, because server work lives in the terminal. Once your key works, the natural follow-up is key-only logins — our Fail2ban guide completes that arc — and everything below is written for the place SSH keys matter most: a headless VPS hosting instance where the terminal is the only interface.
How do you create an SSH key?
You create an SSH key by running ssh-keygen, pressing Enter to accept the default location, and setting a passphrase. The whole path from zero to logging in with the key is six steps, and most people finish in a few minutes:
- Open a terminal. Terminal on Linux and macOS, PowerShell on Windows with the OpenSSH client installed (see below).
- Generate the pair. Run
ssh-keygen -t ed25519 -C "[email protected]". Since OpenSSH 9.5 (October 2023) the-t ed25519flag is technically redundant —ssh-keygengenerates an Ed25519 key with no arguments — but being explicit keeps scripts and tutorials unambiguous. - Accept the location. Press Enter to save to
~/.ssh/id_ed25519(private) and~/.ssh/id_ed25519.pub(public). - Set a passphrase. Type one you can remember. It encrypts the private key on disk, so a stolen key file alone is useless without it.
- Copy the public key to your server. Run
ssh-copy-id user@your-serverand enter your password one last time. - Log in with the key. Run
ssh user@your-server— you are asked for the passphrase, not the server password.
The ssh-keygen ed25519 workflow is the same on all three operating systems; only the install step differs. The steps to generate SSH key Linux users follow are identical across distributions, and the fastest way to add SSH key to server authorized_keys files is the ssh-copy-id route below. The ssh-copy-id Ubuntu package is openssh-client — the same install from the Linux section above. These ssh public key permissions are enforced by both ends of the connection: once you ssh-agent add passphrase-protected keys, the agent answers SSH's challenges without re-prompting.
What does ssh-keygen actually do?
ssh-keygen "generates, manages and converts authentication keys for ssh(1)" and "can create keys for use by SSH protocol version 2," per its man page. When you want to generate an SSH key on Linux, macOS, or Windows, it is the standard tool on all three. The algorithm flag -t accepts dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | mldsa44-ed25519 | rsa, but in practice you only need to know two of them:
| Flag | What it does | When to use it |
|---|---|---|
-t ed25519 | Selects the Ed25519 algorithm (fixed 256-bit key) | Every new key — the current default and recommendation |
-t rsa -b 4096 | Selects RSA with a 4096-bit key | Only for old systems that predate Ed25519 support |
-C "comment" | Attaches a label to the public key | Your email, so you can recognize the key later |
-f filename | Chooses where the key files are written | Named keys for specific hosts or projects |
-a rounds | Sets bcrypt KDF rounds for passphrase protection (default 16) | High-security keys where slower unlocking is acceptable |
-p | Changes the passphrase on an existing key | When you want a new passphrase without a new key |
Ed25519 has a short history worth knowing. Support landed in OpenSSH 6.5 on 30 January 2014 (LWN's release notes), along with the bcrypt-protected private key format. On 4 October 2023, OpenSSH 9.5 made Ed25519 the default — the man page now states "If invoked without any arguments, ssh-keygen will generate an Ed25519 key." Why the consensus? The key is fixed-length, so you cannot accidentally generate an undersized one; it is fast; and an Ed25519 public key is 68 characters versus 544 for an RSA 3072 key (marcofranssen.nl), so it pastes cleanly into key fields. For RSA the man page notes the minimum is 1024 bits with a 3072-bit default, and -b is ignored entirely for Ed25519.
How do you generate an SSH key on Linux?
Run ssh-keygen -t ed25519 -C "[email protected]" in a terminal — Linux needs no new concepts, just the OpenSSH client, which most distributions ship. Minimal installs may need it: sudo apt install openssh-client on Debian and Ubuntu (the openssh-client package provides ssh, scp, sftp, ssh-keygen and ssh-copy-id, per linuxcapable.com), or sudo dnf install openssh-clients on RHEL, CentOS, Fedora, AlmaLinux and Rocky (note the plural package name on RHEL-family systems, per cyberciti.biz).
The interactive flow looks like this (prompt text from Hetzner's 2026 "Add SSH Keys" guide, verified against OpenSSH 9.6 on a live Ubuntu box this run):
ssh-keygen -t ed25519 -C "[email protected]" 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
Two things are worth noticing in that transcript. First, the private key lands at ~/.ssh/id_ed25519 and the public key is the same name with .pub appended — the man page's exact wording. Second, ssh-keygen creates the files with safe modes on its own: on the live box the private key arrived at mode 600 automatically, and the file header -----BEGIN OPENSSH PRIVATE KEY----- marks the modern openssh-key-v1 format that stores the bcrypt-encrypted key material.
How do you generate an SSH key on macOS?
The same command works on macOS — Terminal.app ships with the OpenSSH command-line client, so there is nothing to install (swiftserver.app, 2026). macOS also handles the "type my passphrase every time" problem better than Linux out of the box: launchd starts an ssh-agent for you at login, so there is nothing to launch yourself. Apple ships one extra flag that matters here:
/usr/bin/ssh-add --apple-use-keychain ~/.ssh/id_ed25519
The --apple-use-keychain option stores the key's passphrase in your login keychain when you add it to the agent, per GitHub's docs; on macOS versions before Monterey (12.0), the same thing was done with ssh-add -K. To get the public key into a paste buffer, run pbcopy < ~/.ssh/id_ed25519.pub. Keys live in ~/.ssh on macOS, exactly as on Linux.
How do you generate an SSH key on Windows?
On Windows, the OpenSSH client is available on Windows 10 (version 1809 and later), Windows 11, and Windows Server as an optional feature (umatechnology.org). Open Settings > Apps > Optional features on Windows 10 or System > Optional features on Windows 11 and add the OpenSSH Client — on Windows 11 it is often installed by default. Then open PowerShell and run the same command:
ssh-keygen -t ed25519 -C "[email protected]"
Verify the client first with ssh -V, which prints something like OpenSSH_for_Windows_9.5p1, LibreSSL 3.8.2. Keys live in %USERPROFILE%\.ssh on Windows (techearl.com) — the Windows equivalent of ~/.ssh — and from there ssh-copy-id and ssh work as on Linux. If you use PuTTY rather than the built-in client, its PuTTYgen tool generates keys through a graphical interface instead.
Should you set a passphrase on your SSH key?
Yes. A passphrase encrypts the private key on disk: "If an attacker gains access to your ~/.ssh/ directory, they cannot use the key without the passphrase" (tools.wyattau.com git docs, 2026). Without one, anyone who can read the file can use it — and the file is just 411 bytes of base64.
The protection is concrete, not hand-waving. Modern keys use the openssh-key-v1 private-key format, introduced in 2014 and now the default; with a passphrase it encrypts the key material with AES-256-CTR, deriving the encryption key from your passphrase with the bcrypt KDF at 16 rounds by default (copyprogramming.com's 2026 format guide, confirmed by a byte-level decode on gist.github.com showing the magic string openssh-key-v1, cipher aes256-ctr and KDF bcrypt in a real key file). The man page's own passphrase guidance: good passphrases are 10–30 characters, not simple sentences, mixing upper and lowercase letters, numbers, and symbols. Two operations cover the passphrase lifecycle: ssh-keygen -p changes the passphrase on an existing key, and -a raises the KDF round count for keys that need to resist offline brute force longer.
What permissions must your SSH files have?
Your ~/.ssh directory must be mode 700 and your private key mode 600 — ssh-keygen sets both correctly at creation, and SSH refuses to use a private key that is readable by anyone else. The complete table (values from techearl.com's permissions guide and cloudbolt.io's SSH hardening guide, both 2026):
| File or directory | Mode | Why |
|---|---|---|
~/.ssh | 700 | Only you can enter the directory |
~/.ssh/id_ed25519 (private) | 600 | Only you can read or write the key |
~/.ssh/id_ed25519.pub (public) | 644 | Public — safe for anyone to read |
~/.ssh/authorized_keys (server) | 600 | The keys allowed to log in as you |
Get the private-key mode wrong and SSH tells you exactly why: it prints WARNING: UNPROTECTED PRIVATE KEY FILE! followed by Permissions 0644 for '/path/to/key' are too open, then ignores the key and usually fails with Permission denied (publickey) (cloudbolt.io). Fix it with chmod 600 on the key. Server-side, sshd enforces the same idea with StrictModes yes (the default), logging Authentication refused: bad ownership or modes for file when authorized_keys is at fault — and note your server home directory itself must not be group- or world-writable, or the same refusal happens (techcommune.org).
How do you add your SSH key to a server?
The fastest way is ssh-copy-id user@your-server. The tool's man page defines it as a program to "use locally available keys to authorise logins on a remote machine," invoked as ssh-copy-id [options] [user@]hostname; by default it appends your keys "to the remote user's ~/.ssh/authorized_keys (creating the file, and directory, if necessary)." It logs in with your password one last time, installs the key, and you never type that password again. On Ubuntu the package providing it is openssh-client — the same install from the Linux section above.
Three routes cover every situation; pick one:
| Route | How | Best for |
|---|---|---|
| ssh-copy-id | ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host | Any Linux/macOS workstation talking to a server — the standard path |
| Manual append | cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys on the server | Machines without ssh-copy-id (minimal installs, some Windows setups) |
| GitHub / Git hosting | github.com/settings/keys → SSH and GPG keys → New SSH key, paste the public key | Git over SSH instead of HTTPS |
The manual route deserves one caution: append (>>), never overwrite — one public key occupies exactly one line of authorized_keys, and a clobbered file locks out every key it held. The GitHub route follows GitHub's own docs: profile picture → Settings → SSH and GPG keys → New SSH key, paste the public key in the Key field, click Add SSH key. Whichever route you take, remember the split that makes the whole system safe: the public key can be pasted anywhere, but the private key never leaves your device — never paste a real private key into a website, chat, or email.
How do you stop typing your passphrase every time?
Add the key to ssh-agent once with ssh-add — the agent holds the decrypted key in memory and answers SSH's challenges for you. On Linux, start the agent and load the key:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519
On macOS launchd already runs an agent from login, so you only need the ssh-add line (use --apple-use-keychain to persist the passphrase in the keychain). Two flags round out the workflow: ssh-add -l lists the fingerprints of the identities the agent currently holds, and ssh-add -t 3600 ~/.ssh/id_ed25519 loads a key for one hour only, so a forgotten terminal session does not hold the key forever (dev.to, 2026). This is also where ssh-add enforces the permission rule itself: "Identity files should not be readable by anyone but the user. Note that ssh-add ignores identity files if they are accessible by others" (ssh-add(1) man page).
What should you do after your first key works?
Turn off password logins. Your key is now the stronger factor, and password authentication is exactly what brute-force bots hammer — which is why our Fail2ban setup guide is the natural next read after this one. In sshd_config, PasswordAuthentication defaults to yes and PubkeyAuthentication defaults to yes (protocol version 2 only), per the sshd_config(5) man page. The hardening recipe, per tuts.kandz.me's 2026 SSH server guide: set PasswordAuthentication no, validate the syntax with sshd -t before touching anything, then sudo systemctl reload sshd — reload rereads the config without dropping established connections, and the unit is named ssh on Debian/Ubuntu but sshd on RHEL-family systems. Two companion reads keep the key healthy afterward: our guide to rotating your SSH keys when it is time to replace one, and the guide to watching failed SSH login attempts so you can see the attacks your password-free server now shrugs off.
Sources
- ssh-keygen(1) man page — mankier.com (current OpenSSH manual)
- ssh-copy-id(1) man page — man7.org
- sshd_config(5) man page — linux.die.net
- ssh-add(1) man page — leancrew.com (macOS build)
- LWN, "What's new in OpenSSH 6.5 (and 6.6)" (2014)
- safeguard.sh, OpenSSH release history (9.5 — 4 October 2023)
- Hetzner Docs, "Add SSH Keys" (2026-09-18)
- Heroku Dev Center, "Managing SSH Keys" (July 2026)
- GitHub Docs, "Adding a new SSH key to your GitHub account" and "Error: ssh-add: illegal option -- apple-use-keychain"
- techearl.com, SSH key guides (2026)
- cloudbolt.io, "How to login with an SSH private key" (2026)
- techcommune.org, SSH permissions guidance
- LRZ documentation (collab.dvb.bayern), SSH key management
- copyprogramming.com, "OpenSSH Private Key Format and Latest Best Practices 2026"
- gist.github.com/JPvRiel, openssh-key-v1 byte decode
- swiftserver.app, "Best Native SSH Client for Mac" (2026-09-24)
- cyberciti.biz, Ubuntu/RHEL OpenSSH install guides
- linuxcapable.com, Debian openssh-client package contents
- umatechnology.org, OpenSSH on Windows 10/11
- techbloat.com, "How to Install OpenSSH on Windows" (2026)
- marcofranssen.nl, "Upgrade your SSH security with RSA and Ed25519 keys" (2026-10-02)
- dev.to/masitings, "ssh-keygen Best Practices for 2026" (October 2026)
- dev.to/susumun, "SSH key types (RSA / ED25519 / ECDSA)" (2026-09-03)
- dev.to/wolfhound1995, "ssh-agent and ssh-add, in practice" (2026)
- dev.to, "SSH Agent: Use Passphrase-Protected Keys Without Repeated Prompts" (2026)
- tools.wyattau.com, git documentation (2026)
- tuts.kandz.me, "LFCS 111 — SSH Server Configuration" (2026)
Frequently Asked Questions
What happens if I run ssh-keygen and already have a key?
ssh-keygen warns that the file exists and asks whether to overwrite it — say no. Overwriting destroys the old key, and anything trusting it stops working. Use ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "[email protected]" to create a second, named key instead.
Is Ed25519 supported by my server?
If the server runs OpenSSH 6.5 or newer (January 2014 onward), yes — and so do GitHub, GitLab, and the major cloud providers. For an older device that predates Ed25519, fall back to ssh-keygen -t rsa -b 4096.
What if ssh-copy-id is not available on my machine?
Install openssh-client (Debian/Ubuntu) or openssh-clients (RHEL-family) to get it, or append the key manually: copy ~/.ssh/id_ed25519.pub to the server and run cat id_ed25519.pub >> ~/.ssh/authorized_keys, then set chmod 600 ~/.ssh/authorized_keys and chmod 700 ~/.ssh.
Can I use the same SSH key on all my devices?
One public key can be installed on many servers, and it will work. For better control, use a separate key per device: if a laptop is lost, you revoke one public key instead of re-keying everything.
I forgot my passphrase — can I recover the key?
No. A passphrase is not stored anywhere and cannot be recovered; ssh-keygen -p only changes a passphrase you already know. Generate a fresh key pair, install the new public key, and retire the old one — the same add-first-verify-then-retire order our key rotation guide walks through.

