</>StackKit
</>StackKit

Developer tutorials & guides

SSH Keys Explained: How to Set Up Passwordless Authentication

Learn how SSH keys work, how to generate them, add them to remote servers and GitHub, and manage multiple keys across different services.

N

Nitheesh DR

Founder & Full-Stack Engineer

7 min read830 words
#ssh#linux#security#github#devops

What Are SSH Keys?

SSH (Secure Shell) keys are a pair of cryptographic keys used for authentication. Instead of typing a password every time you connect to a server or push to GitHub, your machine proves its identity using a private key — and the server verifies it with the matching public key.

The pair:

  • Private key (~/.ssh/id_ed25519) — stays on your machine. Never share it.
  • Public key (~/.ssh/id_ed25519.pub) — goes on the server. Safe to share.

When you connect, your client signs a challenge with the private key. The server verifies the signature with the public key. No password needed.


Generating an SSH Key Pair

Modern systems should use Ed25519 (faster and more secure than RSA):

ssh-keygen -t ed25519 -C "your_email@example.com"

The -C flag adds a comment (usually your email) to identify the key.

Prompts:

Enter file in which to save the key (/home/you/.ssh/id_ed25519): [Press Enter]
Enter passphrase (empty for no passphrase): [Enter a strong passphrase]
Enter same passphrase again: [Repeat it]

Use a passphrase. It encrypts your private key on disk — if your machine is compromised, the attacker still can't use the key without the passphrase. You won't need to type it every time if you use ssh-agent (covered below).

This creates two files:

~/.ssh/id_ed25519      ← private key (never share)
~/.ssh/id_ed25519.pub  ← public key (copy this to servers)

Legacy RSA (use only if Ed25519 isn't supported):

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Adding Your Public Key to a Remote Server

Method 1: ssh-copy-id (easiest)

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server-ip
# Enter your password one last time
# From now on, no password needed

Method 2: Manual

# View your public key
cat ~/.ssh/id_ed25519.pub

# On the server, append it to authorized_keys
echo "your-public-key-content" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

Test the connection:

ssh user@server-ip
# Should connect without asking for a password

Adding SSH Keys to GitHub

  1. Copy your public key:
# macOS
cat ~/.ssh/id_ed25519.pub | pbcopy

# Linux
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard

# Or just print and copy manually
cat ~/.ssh/id_ed25519.pub
  1. Go to GitHub → Settings → SSH and GPG keys → New SSH key

  2. Give it a title (e.g., "MacBook Pro 2024"), paste the public key, save

  3. Test:

ssh -T git@github.com
# Hi username! You've successfully authenticated...

Now use SSH URLs instead of HTTPS for your repos:

git clone git@github.com:username/repo.git
# Instead of: git clone https://github.com/username/repo.git

Using ssh-agent (No Repeated Passphrase)

ssh-agent holds your decrypted key in memory so you only type the passphrase once per session.

# Start the agent
eval "$(ssh-agent -s)"

# Add your key (prompts for passphrase once)
ssh-add ~/.ssh/id_ed25519

# List added keys
ssh-add -l

macOS — persist across reboots by adding to ~/.ssh/config:

Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

Then:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Managing Multiple Keys with ~/.ssh/config

When you have multiple keys for different services, use the SSH config file to keep things organized:

# ~/.ssh/config

# Personal GitHub
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519

# Work GitHub
Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work

# Production server
Host prod
  HostName 203.0.113.10
  User ubuntu
  IdentityFile ~/.ssh/id_ed25519_prod
  Port 2222

# Staging server
Host staging
  HostName 203.0.113.20
  User ubuntu
  IdentityFile ~/.ssh/id_ed25519_staging

Now you can connect with shortcuts:

ssh prod         # instead of: ssh -i ~/.ssh/id_ed25519_prod -p 2222 ubuntu@203.0.113.10
ssh staging

# For work GitHub repos
git clone git@github-work:company/repo.git

SSH Key Security Best Practices

Always use a passphrase on your private key. A key without a passphrase is as risky as a password written on a sticky note.

Set correct file permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519        # private key — owner read/write only
chmod 644 ~/.ssh/id_ed25519.pub    # public key
chmod 600 ~/.ssh/authorized_keys   # on the server
chmod 600 ~/.ssh/config

Disable password authentication on servers once SSH keys are working:

# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
sudo systemctl restart sshd

Use different keys for different services — don't reuse one key everywhere. If one service is compromised, the others aren't affected.

Rotate keys periodically — especially when a team member leaves.


Troubleshooting

Permission denied (publickey):

ssh -v user@server  # verbose output shows exactly where auth fails

Check that authorized_keys has the right permissions (600) and the key is exactly one line.

Key not being offered:

ssh-add -l  # check if key is loaded in agent
ssh-add ~/.ssh/id_ed25519  # add it

Conclusion

SSH keys eliminate passwords from your workflow entirely — more secure and more convenient. Generate an Ed25519 key, add a passphrase, configure ssh-agent to avoid typing it repeatedly, and use ~/.ssh/config to manage multiple identities cleanly. Once set up, you'll wonder how you ever worked without them.

Tagged

#ssh#linux#security#github#devops
N

Written by

Nitheesh DR

Founder & Full-Stack Engineer

Nitheesh is a full-stack software engineer based in Tamil Nadu, India, with hands-on experience building production SaaS applications using Next.js, TypeScript, React, Node.js, and cloud infrastructure. He founded StackKit to share the practical knowledge he uses every day — not just theory, but the real-world techniques that help developers ship better software faster.