SSH Beginner's Guide
SSH is the standard way to connect to Linux servers. It provides encrypted remote shell access, file transfer, and port forwarding over any network. This guide covers the full workflow from generating your first key pair through advanced configuration.
Connecting to a remote server
# Basic connection (uses password or key if already set up)
ssh user@hostname
ssh user@192.168.1.10
# Specify a port (default is 22)
ssh -p 2222 user@hostname
# Specify a private key
ssh -i ~/.ssh/id_ed25519 user@hostname
# Run a single command without starting an interactive shell
ssh user@hostname 'ls -la /var/log/'
ssh user@hostname 'sudo systemctl restart nginx'
# Verbose output (useful for debugging connection issues)
ssh -v user@hostname
ssh -vv user@hostname # more verbose
ssh -vvv user@hostname # maximum verbosity
Key-based authentication
Key-based auth is strongly preferred over password auth. The setup is a one-time process.
Step 1: Generate a key pair
# Generate an Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "colton@workstation"
# Generate an RSA key (still widely supported, use 4096 bits)
ssh-keygen -t rsa -b 4096 -C "colton@workstation"
# Generate with a specific filename
ssh-keygen -t ed25519 -f ~/.ssh/my-server-key
# The command creates two files:
# ~/.ssh/id_ed25519 -- PRIVATE key (never share this)
# ~/.ssh/id_ed25519.pub -- PUBLIC key (this goes on servers)
A passphrase is optional but recommended. It encrypts the private key on disk, so it cannot be used even if stolen.
Step 2: Copy the public key to the server
# Easiest method
ssh-copy-id user@hostname
# Specify a key file
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostname
# Manual method (if ssh-copy-id is not available)
cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Step 3: Verify and disable password auth
After confirming key login works:
# On the remote server, edit the SSH daemon config
sudo nano /etc/ssh/sshd_config
# Set these options:
# PasswordAuthentication no
# PubkeyAuthentication yes
# PermitRootLogin no (optional but recommended)
# Reload the SSH daemon (do NOT disconnect your existing session yet)
sudo systemctl reload sshd
# Test from a new terminal before closing anything
ssh -i ~/.ssh/id_ed25519 user@hostname
The SSH config file
The ~/.ssh/config file saves you from typing long commands repeatedly.
# Create or edit ~/.ssh/config
nano ~/.ssh/config
Example config:
# Global settings (apply to all connections)
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
# A simple server alias
Host myserver
HostName 203.0.113.10
User colton
IdentityFile ~/.ssh/id_ed25519
# Server on a non-standard port
Host dev-box
HostName dev.example.com
User ubuntu
Port 2222
IdentityFile ~/.ssh/dev-key
# Jump host pattern (connect to internal server through a bastion)
Host internal-server
HostName 10.0.1.50
User admin
ProxyJump bastion.example.com
# Wildcard for all servers in a domain
Host *.example.com
User deploy
IdentityFile ~/.ssh/deploy-key
# Disable host key checking for local VMs (never do this for internet hosts)
Host 192.168.56.*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
With this config, ssh myserver connects using the right user, IP, and key automatically.
Managing keys with ssh-agent
ssh-agent holds your decrypted private keys in memory so you only need to enter your passphrase once per session.
# Start the agent (usually started automatically by your desktop session)
eval "$(ssh-agent -s)"
# Add a key to the agent
ssh-add ~/.ssh/id_ed25519
# Add with a timeout (key is removed after 4 hours)
ssh-add -t 4h ~/.ssh/id_ed25519
# List keys currently in the agent
ssh-add -l
# Remove all keys from the agent
ssh-add -D
# Remove a specific key
ssh-add -d ~/.ssh/id_ed25519
With AddKeysToAgent yes in ~/.ssh/config, keys are added to the agent automatically on first use.
Port forwarding (SSH tunneling)
Local forwarding: access a remote service locally
# Make remote_host:80 available at localhost:8080
ssh -L 8080:localhost:80 user@remote_host
# Tunnel to a third machine through the SSH server
ssh -L 8080:internal-server:80 user@jump-host
# Keep running in background
ssh -fN -L 8080:localhost:80 user@remote_host
# -f = background, -N = no command, just forward
# Multiple tunnels at once
ssh -L 8080:localhost:80 -L 5432:localhost:5432 user@remote_host
Remote forwarding: expose a local service on the remote server
# Make localhost:3000 accessible at remote_host:9000
ssh -R 9000:localhost:3000 user@remote_host
# For remote forwarding to be accessible from outside the server,
# set GatewayPorts yes in /etc/ssh/sshd_config on the remote server
Dynamic forwarding: SOCKS proxy
# Create a SOCKS5 proxy on port 1080
ssh -D 1080 user@remote_host
# Use it with curl
curl --socks5 localhost:1080 https://example.com
# Configure your browser to use localhost:1080 as a SOCKS5 proxy
# to route all browsing through the SSH connection
Jump hosts (bastion servers)
A jump host (or bastion) is a server used to reach other servers on a private network.
# Connect to internal-server through bastion
ssh -J user@bastion.example.com user@10.0.1.50
# Multiple jumps
ssh -J user@bastion1,user@bastion2 user@internal
# In ~/.ssh/config:
Host internal
HostName 10.0.1.50
User admin
ProxyJump bastion.example.com
Copying files with SSH
# Copy a local file to a remote server
scp localfile.txt user@hostname:/remote/path/
# Copy from remote to local
scp user@hostname:/remote/file.txt ./
# Copy a directory recursively
scp -r ./mydir user@hostname:/remote/path/
# Use a specific port or key
scp -P 2222 -i ~/.ssh/mykey file.txt user@hostname:/path/
# sftp: interactive file transfer
sftp user@hostname
sftp> ls
sftp> get remotefile.txt
sftp> put localfile.txt
sftp> exit
Troubleshooting SSH connections
# Connection refused
# - Is sshd running? On the server: systemctl status sshd
# - Is the port right? Try: nc -zv hostname 22
# - Is a firewall blocking port 22? Check with: nmap -p 22 hostname
# Permission denied (publickey)
# - Wrong key? Check: ssh -v user@hostname (look for "Trying private key")
# - Wrong user? Check the server's authorized_keys for the right user
# - Check permissions: ~/.ssh should be 700, authorized_keys should be 600
ssh -v user@hostname 2>&1 | grep -E 'key|auth|debug'
# Host key changed warning
# - The server was rebuilt, or you are connecting to a different machine
# - If expected, remove the old entry: ssh-keygen -R hostname
# - If unexpected, investigate before proceeding (possible MITM attack)
# Connection drops / timeout
# - Add to ~/.ssh/config: ServerAliveInterval 60
# - Or pass on command line: ssh -o ServerAliveInterval=60 user@hostname
# Debug the server-side
sudo journalctl -u sshd -f # watch SSH logs in real time
sudo tail -f /var/log/auth.log # Debian/Ubuntu
sudo tail -f /var/log/secure # Fedora/RHEL
File permissions that matter
SSH is strict about file permissions. If they are wrong, it silently ignores keys.
# Fix permissions on ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 # private key: owner read/write only
chmod 644 ~/.ssh/id_ed25519.pub # public key: world-readable is fine
chmod 600 ~/.ssh/authorized_keys # authorized keys: owner read/write only
chmod 600 ~/.ssh/config # config: owner read/write only
chmod 600 ~/.ssh/known_hosts # known hosts
# Check ownership (all should be owned by you)
ls -la ~/.ssh/
Frequently Asked Questions
What is SSH and what is it used for?
SSH (Secure Shell) is a cryptographic network protocol for securely connecting to remote systems over an unsecured network. It encrypts all traffic between the client and server, including passwords, commands, and data. SSH is used primarily for: remote shell access (logging into a Linux server to run commands), file transfer (via SCP or SFTP), and port forwarding (tunneling other protocols through an encrypted connection). It runs on port 22 by default and replaced older insecure protocols like Telnet and rsh.
What is the difference between password authentication and key-based SSH authentication?
Password authentication sends your username and password to the remote server for verification. It is convenient but vulnerable to brute force attacks. Key-based authentication uses a cryptographic key pair: a private key that stays on your machine and a public key that is installed on the remote server. The server challenges the client to prove it holds the private key without sending the key itself. Key-based auth is strongly preferred because private keys are much harder to compromise than passwords, and you can disable password auth entirely on a server to prevent brute force attempts.
How do I generate an SSH key pair?
Run ssh-keygen -t ed25519 -C “your comment here” and follow the prompts. This creates two files: ~/.ssh/id_ed25519 (the private key — keep this secret and never share it) and ~/.ssh/id_ed25519.pub (the public key — this is what you put on servers). Use ed25519 for new keys; it is faster and more secure than RSA. When prompted for a passphrase, adding one provides a second factor of protection: even if your private key file is stolen, the attacker also needs the passphrase to use it.
What is the SSH config file?
The SSH client configuration file at ~/.ssh/config lets you define connection shortcuts and settings for specific hosts. Instead of typing ssh -i ~/.ssh/mykey -p 2222 user@long.hostname.example.com each time, you can define a Host block in ~/.ssh/config with the hostname, user, port, and key, then just type ssh myalias. The config file also lets you set options globally (for all connections) or per-host, including keepalive settings, forwarding options, and connection multiplexing.
What is SSH port forwarding?
SSH port forwarding (also called SSH tunneling) routes traffic from one port through an encrypted SSH connection to a port on the remote side. Local forwarding (-L) makes a remote service available on your local machine: ssh -L 8080:localhost:80 user@server makes the remote server’s port 80 available at localhost:8080 on your machine. Remote forwarding (-R) makes a local service accessible from the remote server. Dynamic forwarding (-D) creates a SOCKS proxy that routes all traffic through the SSH connection, useful as a VPN alternative.
How do I copy my SSH public key to a remote server?
The easiest way is ssh-copy-id user@hostname, which appends your public key to ~/.ssh/authorized_keys on the remote server. If ssh-copy-id is not available, you can do it manually: cat ~/.ssh/id_ed25519.pub | ssh user@hostname “mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys”. Make sure ~/.ssh has permissions 700 and authorized_keys has permissions 600 on the remote server, otherwise SSH will ignore the key as a security precaution.