Quick answer
The comment after -C is just a label to help you recognise the key later; an email address or name@laptop are both common. Use a passphrase: it encrypts the private key on disk, so a stolen laptop backup does not hand over access to every server you use. With ssh-agent you only type it once per session.
ssh-keygen -t ed25519 -C "[email protected]"
# Enter file in which to save the key (/home/you/.ssh/id_ed25519): [Enter]
# Enter passphrase (empty for no passphrase): ********
cat ~/.ssh/id_ed25519.pub # this is the public key you shareEd25519 or RSA 4096?
Choose Ed25519 unless something prevents it. Ed25519 keys are short, fast and secure, and they are supported by GitHub, GitLab, Bitbucket, Azure DevOps and every OpenSSH server released since 2014. RSA is the fallback for old systems, some hardware appliances and legacy enterprise servers that do not accept Ed25519. If you need RSA, use at least 3072 bits; 4096 is the common choice. Avoid DSA and ECDSA keys for new setups: DSA is disabled by default in modern OpenSSH, and RSA keys signed with SHA-1 are rejected by GitHub and recent servers.
The optional -a flag increases the number of key-derivation rounds used to protect the passphrase, which slows brute-force attacks on a stolen key file. -f sets the file name, which is useful when you keep separate keys for work and personal accounts.
# Recommended
ssh-keygen -t ed25519 -a 100 -C "[email protected]"
# Legacy systems that need RSA
ssh-keygen -t rsa -b 4096 -C "[email protected]"
# A second key with its own file name
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_workGenerate an SSH key on macOS and Linux
Open Terminal and run ssh-keygen as above. The keys are written to ~/.ssh/id_ed25519 (private) and ~/.ssh/id_ed25519.pub (public). If a key with that name already exists, ssh-keygen asks before overwriting it. Say no unless you are sure: overwriting locks you out of every server that only knows the old key. On Linux, ssh-keygen comes with the openssh-client package, installed by default on nearly every desktop distribution (sudo apt install openssh-client on minimal Debian or Ubuntu images).
Generate an SSH key on Windows
Built-in OpenSSH (Windows 10 and 11)
Windows 10 version 1809 and later include the OpenSSH client, so ssh-keygen works in PowerShell, Command Prompt and Windows Terminal with no extra software. Keys are stored in C:\Users\<you>\.ssh. If the command is not found, add it under Settings, System, Optional features, OpenSSH Client. Git for Windows also bundles its own copy in Git Bash.
ssh-keygen -t ed25519 -C "[email protected]"
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | Set-Clipboard # copy public keyPuTTYgen
If you use PuTTY or WinSCP, generate keys with PuTTYgen. Choose EdDSA (Ed25519) or RSA with 4096 bits, click Generate and move the mouse to add randomness, enter a passphrase, then Save private key to get a .ppk file. Copy the text from the box labelled "Public key for pasting into OpenSSH authorized_keys file"; that is what GitHub and servers expect. To use the same key with OpenSSH tools, use Conversions, Export OpenSSH key.
Add your SSH key to GitHub and test it
Copy the contents of the .pub file, never the private key. On GitHub go to Settings, SSH and GPG keys, New SSH key, give it a title such as the laptop's name, leave the type as Authentication Key and paste the key. GitLab's equivalent is Preferences, SSH Keys.
Then test the connection. The first time, SSH asks you to confirm GitHub's host key fingerprint; compare it with the fingerprints GitHub publishes in its documentation before typing yes. A successful test prints a greeting with your username. Finally, make sure your repositories use the SSH URL rather than HTTPS.
# Copy the public key
pbcopy < ~/.ssh/id_ed25519.pub # macOS
xclip -sel clip < ~/.ssh/id_ed25519.pub # Linux (X11)
clip < %USERPROFILE%\.ssh\id_ed25519.pub # Windows cmd
# Test
ssh -T [email protected]
# Hi your-username! You've successfully authenticated, but GitHub does not provide shell access.
# Switch an existing clone from HTTPS to SSH
git remote set-url origin [email protected]:your-username/your-repo.gitWarning
Never paste, upload or commit your private key (the file without .pub). If it is ever exposed, delete the public key from GitHub and every server and generate a new pair.
Load the key into ssh-agent
ssh-agent keeps decrypted keys in memory so you do not retype the passphrase for every git push. Most Linux desktops and macOS start an agent automatically; on a server or in a plain shell, start one with eval "$(ssh-agent -s)". On macOS, --apple-use-keychain stores the passphrase in the Keychain (older macOS versions used -K), and the config lines below make SSH reload it after a reboot. On Windows, the agent is a service that is disabled by default; enable it once from an Administrator PowerShell.
macOS
eval "$(ssh-agent -s)"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519# ~/.ssh/config
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519Linux
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l # list loaded keysWindows (Administrator PowerShell)
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519Use ~/.ssh/config for multiple keys and servers
The SSH config file saves you from typing usernames, ports and key paths. Each Host block defines an alias. IdentitiesOnly yes tells SSH to offer only the listed key, which avoids "Too many authentication failures" when the agent holds several keys. A common pattern is a separate alias for a work GitHub account, used in the clone URL in place of github.com.
# ~/.ssh/config
Host prod
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yesssh prod # instead of ssh -p 2222 [email protected]
git clone git@github-work:acme/internal-api.git # uses the work keyFix SSH key permissions
OpenSSH refuses to use a private key that other users can read and prints "WARNING: UNPROTECTED PRIVATE KEY FILE!" followed by "bad permissions". The server side is just as strict: if ~/.ssh or authorized_keys is group- or world-writable, key login silently falls back to a password. Set the permissions below. Use our chmod calculator if the numbers are unfamiliar. On Windows, the private key must be readable only by your account; remove other users and inherited permissions in the file's Security tab if SSH complains.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/config ~/.ssh/authorized_keys
chmod 644 ~/.ssh/id_ed25519.pubCopy your public key to a server
To log in to a Linux server with your key, its public half must be appended to ~/.ssh/authorized_keys for the target user. ssh-copy-id does that, creates the directory with the right permissions, and asks for the password one last time. Windows has no ssh-copy-id, so pipe the key over SSH instead. Once key login works, consider setting PasswordAuthentication no in the server's sshd_config, but keep a second session open while you test so you cannot lock yourself out.
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
ssh [email protected] # should not ask for the account password now# Windows PowerShell
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | ssh [email protected] "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"Generate an SSH key: FAQ
Quick answers to common questions
Should I use Ed25519 or RSA for SSH keys?
Use Ed25519. It is shorter, faster and widely supported. Generate an RSA key with ssh-keygen -t rsa -b 4096 only for older servers or devices that do not accept Ed25519.
Where are SSH keys stored?
In the .ssh folder in your home directory: ~/.ssh on macOS and Linux, C:\Users\<you>\.ssh on Windows. The private key is id_ed25519 and the public key is id_ed25519.pub.
How do I check if I already have an SSH key?
Run ls -al ~/.ssh (or dir $env:USERPROFILE\.ssh on Windows) and look for files such as id_ed25519.pub or id_rsa.pub. If they exist, you can reuse them instead of generating a new pair.
Why does ssh -T [email protected] say Permission denied (publickey)?
GitHub did not receive a key it recognises. Check that the public key is added to your GitHub account, that the key is loaded with ssh-add -l, and run ssh -vT [email protected] to see which key files SSH tries.
How do I change the passphrase of an SSH key?
Run ssh-keygen -p -f ~/.ssh/id_ed25519. You enter the old passphrase and then the new one; the key itself does not change, so nothing needs updating on GitHub or servers.

