Generate SSH Key (Ed25519): Complete Setup Guide
SSH keys are the standard way to authenticate with servers, GitHub, and cloud infrastructure. Ed25519 is the modern algorithm of choice - faster and more secure than RSA. This guide covers key generation, copying to servers, SSH config setup, GitHub integration, and troubleshooting on macOS, Linux, and Windows.
Why Ed25519 Instead of RSA?
For many years, RSA-4096 was the recommended SSH key type. Ed25519 has replaced it as the modern standard for several reasons:
- Smaller keys: An Ed25519 public key is 68 characters. An RSA-4096 public key is over 700 characters.
- Faster operations: Ed25519 signing and verification are significantly faster than RSA, which matters when you SSH frequently or have many keys in
authorized_keys. - Better security properties: Ed25519 uses elliptic curve cryptography (Curve25519) which is resistant to timing attacks by design. RSA implementations require careful side-channel mitigation.
- No weak key risk: RSA security degrades with a bad random number generator. Ed25519's deterministic signing means a weak RNG does not compromise the key.
The only reason to still use RSA is compatibility with very old SSH servers (OpenSSH before 6.5, from 2014). For anything modern, use Ed25519.
Step 1: Generate the Key Pair
The command is the same on macOS, Linux, and Windows (via Git Bash, WSL, or Windows OpenSSH).
# Generate an Ed25519 key pair
ssh-keygen -t ed25519 -C "your.email@example.com"
# With a custom file name (recommended when you have multiple keys)
ssh-keygen -t ed25519 -C "your.email@example.com" -f ~/.ssh/id_ed25519_github
# Non-interactive (no passphrase, for CI/CD)
ssh-keygen -t ed25519 -C "deploy-bot" -f ~/.ssh/deploy_key -N ""
When prompted for a file location, press Enter to accept the default (~/.ssh/id_ed25519) or enter a custom path. When prompted for a passphrase, enter a strong passphrase to encrypt the private key on disk. For production servers and CI/CD, keys without passphrases are common but understand the trade-off: if the private key file is stolen, it can be used immediately.
After generation, you will have two files:
~/.ssh/id_ed25519- Private key. Never share this. Never copy this to a server.~/.ssh/id_ed25519.pub- Public key. This is what you share with servers and services like GitHub.
Step 2: View Your Public Key
# Print the public key to copy it
cat ~/.ssh/id_ed25519.pub
# Output looks like:
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your.email@example.com
# Copy to clipboard on macOS
cat ~/.ssh/id_ed25519.pub | pbcopy
# Copy to clipboard on Linux (requires xclip)
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard
# Copy to clipboard on Windows
cat ~/.ssh/id_ed25519.pub | clip
Step 3: Copy the Public Key to a Server
The standard tool is ssh-copy-id, which appends your public key to the server's ~/.ssh/authorized_keys file with correct permissions.
# Copy your default key to a server
ssh-copy-id user@server-ip
# Copy a specific key
ssh-copy-id -i ~/.ssh/id_ed25519_myserver.pub user@server-ip
# If using a non-standard port
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 user@server-ip
If ssh-copy-id is not available (Windows, some macOS setups), do it manually:
# Manual method: append the public key to authorized_keys on the server
cat ~/.ssh/id_ed25519.pub | ssh user@server-ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
File permissions on the server matter. The
~/.sshdirectory must be700(owner only) and~/.ssh/authorized_keysmust be600(owner read/write only). SSH refuses to authenticate if permissions are too open.
Step 4: Test the Connection
# Test SSH login with the key
ssh user@server-ip
# Test with a specific key file
ssh -i ~/.ssh/id_ed25519_myserver user@server-ip
# Test with verbose output (shows which key was used and why authentication succeeded/failed)
ssh -v user@server-ip
# Even more verbose for deep debugging
ssh -vvv user@server-ip
Step 5: Set Up the SSH Config File
The ~/.ssh/config file lets you define aliases, default users, key files, and ports for each host. This means you type ssh myserver instead of ssh -i ~/.ssh/id_ed25519_myserver ubuntu@192.168.1.100 -p 2222.
# ~/.ssh/config
# Default settings for all connections
Host *
AddKeysToAgent yes
IdentitiesOnly yes
# Production server
Host prod
HostName 192.168.1.100
User ubuntu
Port 22
IdentityFile ~/.ssh/id_ed25519_prod
# GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
# AWS EC2 with a .pem key file
Host aws-dev
HostName ec2-12-34-56-78.compute-1.amazonaws.com
User ec2-user
IdentityFile ~/.pem/my-key.pem
StrictHostKeyChecking accept-new
# Jump host / bastion pattern
Host internal-server
HostName 10.0.1.50
User ubuntu
ProxyJump bastion
IdentityFile ~/.ssh/id_ed25519_internal
Host bastion
HostName bastion.example.com
User ubuntu
IdentityFile ~/.ssh/id_ed25519_bastion
Generate Your SSH Config File Instantly
Use our free SSH Config Generator to build a complete ~/.ssh/config with proper syntax for all your hosts, keys, and jump hosts.
Step 6: Add the Key to GitHub
- Copy your public key:
cat ~/.ssh/id_ed25519_github.pub | pbcopy - Go to GitHub → Settings → SSH and GPG keys → New SSH key
- Give it a descriptive title (e.g., "MacBook Pro 2026") and paste the public key
- Click Add SSH key
- Test:
ssh -T git@github.com
You should see: Hi username! You've successfully authenticated, but GitHub does not provide shell access.
If you have multiple GitHub accounts (personal + work), use different key files and the SSH config Host alias trick:
# ~/.ssh/config
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
# Then clone using the alias:
# git clone git@github-work:company/repo.git
Managing the SSH Agent
The SSH agent holds decrypted private keys in memory so you do not have to enter your passphrase on every connection. On macOS the agent runs automatically. On Linux you may need to start it.
# Start the agent (Linux)
eval "$(ssh-agent -s)"
# Add a key to the agent
ssh-add ~/.ssh/id_ed25519
# Add with passphrase stored in macOS Keychain
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
# List keys currently loaded in the agent
ssh-add -l
# Remove all keys from agent
ssh-add -D
Windows Setup
Windows 10 and later include OpenSSH. Enable it and start the service:
# PowerShell (as Administrator): check if OpenSSH is installed
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
# Install OpenSSH client
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
# Start the SSH agent service
Start-Service ssh-agent
Set-Service -Name ssh-agent -StartupType Automatic
# Add a key
ssh-add C:\Users\YourName\.ssh\id_ed25519
Build Your SSH Config in Seconds
Our SSH Config Generator creates properly formatted ~/.ssh/config entries with all the right options for your servers, GitHub, and bastion hosts.
Frequently Asked Questions
Should I use a passphrase on my SSH key?
Yes, for any key used by a human. A passphrase encrypts the private key file so that stealing the file is not enough - the attacker also needs the passphrase. Use the SSH agent to avoid typing the passphrase repeatedly. The only exception is automated systems (CI/CD pipelines, deploy bots) where interactive passphrase entry is not possible. For those, use passphrase-less keys and store them in a secrets manager, not on disk in plaintext.
What is the difference between Ed25519 and ECDSA?
Both are elliptic curve algorithms. Ed25519 uses the Edwards25519 curve, which has better security properties and faster implementation. ECDSA using NIST curves (P-256, P-384) has some concerns about the curve parameters and requires a random nonce in each signature - a weak RNG in the signing operation can leak the private key. Ed25519 uses deterministic signing, eliminating that risk. For new keys, always choose Ed25519 over ECDSA.
How do I check which SSH key was used to connect?
On the client side, run ssh -v user@host and look for lines like debug1: Offering public key and debug1: Server accepts key. On the server side, check /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL/CentOS) for lines containing the key fingerprint. You can print the fingerprint of a key with ssh-keygen -l -f ~/.ssh/id_ed25519.pub.
How do I rotate an SSH key on a server I still have access to?
Generate a new key pair, copy the new public key to the server's authorized_keys (keeping the old one), test the new key works, then remove the old public key from authorized_keys. Never remove the old key before verifying the new one works - you could lock yourself out.
Why is SSH asking for my password even after I copied the public key?
The most common causes are: wrong file permissions on ~/.ssh or authorized_keys on the server (must be 700 and 600 respectively); the key was added to the wrong user's authorized_keys; the server's sshd_config has PubkeyAuthentication no; or SSH is using a different key than you expect (use ssh -v to see which key is being offered). Also check /var/log/auth.log on the server for the exact rejection reason.
Summary
Generating an Ed25519 SSH key takes one command. The full workflow is: ssh-keygen -t ed25519, copy the public key to your server with ssh-copy-id, create aliases in ~/.ssh/config for hosts you connect to frequently, and add the public key to GitHub for repository access. Use passphrases on personal keys and the SSH agent to avoid typing them repeatedly.
For a complete, correctly formatted SSH config without manual editing, use our generator below.
Generate your SSH config instantly → Use our free SSH Config Generator here
Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.