env.dev

SSH Keys: Complete Guide to Generation and Usage

Learn how to generate SSH keys, configure ssh-agent, set up config files, tunnels, and ProxyJump for secure remote access.

Last updated:

SSH keys provide passwordless, cryptographically secure authentication for remote servers, Git hosting, and automated deployments. Ed25519 keys are the current recommended default — they are faster, smaller, and more secure than RSA. This guide covers key generation, agent management, the SSH config file, tunneling, and security hardening.

How Do You Generate an SSH Key?

Use ssh-keygen with the Ed25519 algorithm. It produces a 256-bit key that is more secure than a 3072-bit RSA key and generates/verifies signatures significantly faster.

Generate an Ed25519 key
# Generate a new Ed25519 key with a comment (usually your email)
ssh-keygen -t ed25519 -C "dev@example.com"

# You'll be prompted for:
#   File: ~/.ssh/id_ed25519 (default, press Enter)
#   Passphrase: use a strong passphrase (recommended)

# Result: two files
# ~/.ssh/id_ed25519       ← private key (never share this)
# ~/.ssh/id_ed25519.pub   ← public key (copy to servers)

# If you need RSA for legacy systems (4096-bit minimum)
ssh-keygen -t rsa -b 4096 -C "dev@example.com"

Why Ed25519? Ed25519 keys are 68 characters in the public key file vs 500+ for RSA-4096. They use the Curve25519 elliptic curve and are resistant to several classes of side-channel attacks that affect NIST curves. OpenSSH has supported Ed25519 since version 6.5 (2014).

How Do You Copy Your Key to a Server?

Use ssh-copy-id to install your public key on a remote server. This appends the key to ~/.ssh/authorized_keys on the server with correct permissions.

Install public key on a server
# Automatic method (recommended)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server.example.com

# Manual method (when ssh-copy-id is unavailable)
cat ~/.ssh/id_ed25519.pub | ssh user@server.example.com \
  'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

# For GitHub/GitLab — paste the public key in the web UI
cat ~/.ssh/id_ed25519.pub
# Copy the output and add it in Settings → SSH Keys

How Does ssh-agent Work?

The SSH agent holds decrypted private keys in memory so you only enter your passphrase once per session. It forwards keys to remote servers when configured, enabling multi-hop connections without copying private keys.

Using ssh-agent
# Start the agent (usually automatic on modern systems)
eval "$(ssh-agent -s)"

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

# List loaded keys
ssh-add -l

# On macOS — store passphrase in Keychain
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

# Remove all keys from agent
ssh-add -D

# Set key lifetime (auto-remove after 8 hours)
ssh-add -t 8h ~/.ssh/id_ed25519

How Should You Configure ~/.ssh/config?

The SSH config file lets you define aliases, set per-host options, and avoid repetitive command-line flags. It is read top-to-bottom — the first matching Host block wins for each directive.

~/.ssh/config example
# Global defaults
Host *
  AddKeysToAgent yes
  IdentitiesOnly yes
  ServerAliveInterval 60
  ServerAliveCountMax 3

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

# Staging via bastion/jump host
Host staging
  HostName 10.0.1.50
  User deploy
  ProxyJump bastion

Host bastion
  HostName bastion.example.com
  User jump
  IdentityFile ~/.ssh/id_ed25519
  ForwardAgent no

# GitHub — use a specific key
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_github

# Wildcard — all dev servers
Host dev-*
  User developer
  IdentityFile ~/.ssh/id_ed25519_dev

How Do SSH Tunnels and Port Forwarding Work?

SSH tunnels encrypt traffic between your machine and a remote server, letting you access services behind firewalls or on private networks.

SSH tunnel types
# Local port forwarding — access remote service on localhost
# Access remote PostgreSQL (port 5432) via localhost:15432
ssh -L 15432:localhost:5432 user@db-server.example.com

# Remote port forwarding — expose local service to remote network
# Make local port 3000 available on remote server's port 8080
ssh -R 8080:localhost:3000 user@remote.example.com

# Dynamic port forwarding — SOCKS5 proxy
# Route browser traffic through the SSH server
ssh -D 1080 user@proxy.example.com
# Then configure browser to use SOCKS5 proxy at localhost:1080

# Tunnel in background without a shell
ssh -fNL 15432:localhost:5432 user@db-server.example.com
# -f = background after auth, -N = no remote command

What Is ProxyJump and How Do You Use It?

ProxyJump (or -J) lets you connect through an intermediate bastion host without manually chaining SSH sessions. It replaces the older, more complex ProxyCommand.

ProxyJump examples
# Single jump host
ssh -J bastion.example.com user@internal-server

# Multiple jump hosts (chained)
ssh -J bastion1.example.com,bastion2.internal user@final-target

# Equivalent config file entry
# Host internal
#   HostName 10.0.1.50
#   User deploy
#   ProxyJump bastion.example.com

# Copy files through a jump host
scp -J bastion.example.com localfile.txt user@internal:/tmp/

What Are the SSH Security Best Practices?

Harden your SSH setup to reduce attack surface. Most breaches involve weak passwords, exposed keys, or default configurations.

Server-side hardening (/etc/ssh/sshd_config)
# Disable password authentication entirely
PasswordAuthentication no
ChallengeResponseAuthentication no

# Disable root login
PermitRootLogin no

# Use only Ed25519 host keys
HostKey /etc/ssh/ssh_host_ed25519_key

# Restrict to specific users/groups
AllowUsers deploy admin
# Or: AllowGroups ssh-users

# Change default port (reduces noise, not a security measure)
Port 2222

# Limit authentication attempts
MaxAuthTries 3

# Disable agent and X11 forwarding unless needed
AllowAgentForwarding no
X11Forwarding no

# Idle timeout
ClientAliveInterval 300
ClientAliveCountMax 2

Critical: Never add private keys to Git repositories, Docker images, or CI logs. Use ssh-agent forwarding or deploy keys with read-only access instead. Set file permissions to chmod 600 ~/.ssh/id_ed25519 and chmod 700 ~/.ssh/.

Key Takeaways

  • • Use Ed25519 keys by default — they are faster, smaller, and more secure than RSA
  • • Always set a passphrase on your private key and use ssh-agent to cache it
  • • Configure ~/.ssh/config with host aliases, identity files, and jump hosts
  • • Use ProxyJump for bastion hosts instead of the older ProxyCommand
  • • Local port forwarding (-L) accesses remote services; remote forwarding (-R) exposes local services
  • • Disable password auth and root login on servers — key-only authentication is the standard
  • • Private key permissions must be 600; the ~/.ssh directory must be 700

Frequently Asked Questions

Which SSH key type should I use?

Use Ed25519 (ssh-keygen -t ed25519) for the best security and performance. It produces shorter keys that are faster to generate and verify. Fall back to RSA 4096-bit only if Ed25519 is not supported.

How do I add my SSH key to a server?

Use ssh-copy-id user@host to automatically install your public key. Alternatively, manually append your ~/.ssh/id_ed25519.pub content to ~/.ssh/authorized_keys on the server.

What is SSH agent forwarding?

Agent forwarding lets you use your local SSH keys on a remote server without copying them. Enable with ssh -A or ForwardAgent yes in config. Use with caution — compromised servers could use your forwarded keys.

Was this helpful?

Stay up to date

Get notified about new guides, tools, and cheatsheets.