What it is
SSH (Secure Shell) is a protocol and a suite of tools for securely connecting to remote servers, executing commands, and transferring files. You reach for it whenever you need to manage a server, access a remote shell, or securely copy data.
Installation
Linux: SSH client and server are usually pre-installed on most Linux distributions. If not:
sudo apt update && sudo apt install openssh-client openssh-server # Debian/Ubuntu
sudo yum update && sudo yum install openssh-clients openssh-server # CentOS/RHEL
sudo dnf update && sudo dnf install openssh-clients openssh-server # Fedora
macOS: SSH client is pre-installed. To install the server:
# Install Homebrew if you don't have it:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install openssh
brew install openssh
# Follow instructions to configure and start the SSH server.
Windows: Windows 10/11 and Server 2019+: The OpenSSH client and server are available as optional features.
- Go to Settings > Apps > Optional features.
- Click Add a feature.
- Find OpenSSH Client and OpenSSH Server in the list, click Install.
- To start the server: Open PowerShell as Administrator and run
Start-Service sshd. - To set it to start automatically:
Set-Service -Name sshd -StartupType 'Automatic'.
Older Windows: Use third-party clients like PuTTY, MobaXterm, or the Windows Subsystem for Linux (WSL).
Core Concepts
- Client/Server Model: An SSH client connects to an SSH server.
- Authentication: Verifies the identity of the user and the server. Common methods include password authentication and public-key authentication.
- Encryption: All communication between client and server is encrypted to prevent eavesdropping.
- Port Forwarding (Tunneling): Allows you to securely forward network traffic from one machine to another through the SSH connection.
Commands / Usage
Connecting to a Remote Server
Basic Connection:
ssh user@hostname
Connects to hostname as user. You’ll be prompted for a password or use keys.
Connection with Specific Port:
ssh -p 2222 user@hostname
Connects to hostname on port 2222 as user.
Connection with Identity File (Private Key):
ssh -i ~/.ssh/id_rsa_prod user@hostname
Connects using the private key located at ~/.ssh/id_rsa_prod for authentication.
Connection with Verbose Output (Debugging):
ssh -v user@hostname
Shows detailed debugging information about the connection process. Use -vv or -vvv for even more detail.
Connection with KeepAlive:
ssh -o ServerAliveInterval=60 user@hostname
Sends a "keep-alive" message every 60 seconds to prevent the connection from timing out due to inactivity.
Connection with Specific SSH Configuration:
ssh -F ~/.ssh/config_prod user@hostname
Uses the SSH configuration file located at ~/.ssh/config_prod instead of the default ~/.ssh/config.
Executing Commands Remotely
Single Command Execution:
ssh user@hostname 'ls -l /home/user'
Connects to hostname, executes ls -l /home/user, prints the output, and disconnects.
Multiple Commands (using semicolon):
ssh user@hostname 'cd /var/www/html; git pull; systemctl restart apache2'
Executes a sequence of commands on the remote server.
Executing a Local Script Remotely:
ssh user@hostname 'bash -s' < /path/to/local/script.sh
Sends the content of script.sh to the remote server’s standard input and executes it using bash.
File Transfers (SCP - Secure Copy)
Copying a File from Local to Remote:
scp /path/to/local/file.txt user@hostname:/path/to/remote/directory/
Copies file.txt from your local machine to the specified directory on the remote server.
Copying a File from Remote to Local:
scp user@hostname:/path/to/remote/file.txt /path/to/local/directory/
Copies file.txt from the remote server to your local machine.
Copying a Directory Recursively (Local to Remote):
scp -r /path/to/local/directory/ user@hostname:/path/to/remote/parent/
Copies the entire local directory and its contents to the remote server.
Copying a Directory Recursively (Remote to Local):
scp -r user@hostname:/path/to/remote/directory/ /path/to/local/parent/
Copies the entire remote directory and its contents to your local machine.
Copying with Specific Port and Identity File:
scp -P 2222 -i ~/.ssh/id_rsa_prod /path/to/local/file.txt user@hostname:/path/to/remote/
Uses port 2222, the specified private key, and copies the file. Note: -P (uppercase) for port with scp, -p (lowercase) for preserving modification times with scp.
SSH Configuration File (~/.ssh/config)
This file allows you to define aliases and default settings for hosts.
Example ~/.ssh/config:
Host production
HostName 192.168.1.100
User deployer
Port 2200
IdentityFile ~/.ssh/deploy_key_prod
Host staging
HostName staging.example.com
User admin
ForwardAgent yes
Host github.com
IdentityFile ~/.ssh/github_id_rsa
Usage with Config:
ssh production
# Connects to 192.168.1.100 as deployer on port 2200 using ~/.ssh/deploy_key_prod
ssh staging
# Connects to staging.example.com as admin, forwarding your local SSH agent
git clone git@github.com:user/repo.git
# Uses ~/.ssh/github_id_rsa for authentication with GitHub
SSH Agent (for key management)
Start the SSH Agent:
eval "$(ssh-agent -s)"
Starts the agent and sets environment variables.
Add a Private Key to the Agent:
ssh-add ~/.ssh/id_rsa_prod
Adds your private key to the running agent. You’ll be prompted for the key’s passphrase if it has one.
List Keys in the Agent:
ssh-add -l
Shows the fingerprints of keys currently loaded in the agent.
Port Forwarding (Tunneling)
Local Port Forwarding (-L):
Forward a local port to a remote service accessible from the server.
ssh -L 8080:localhost:80 user@remote-server.com
Connects to remote-server.com. Any traffic sent to your local port 8080 will be forwarded to port 80 on remote-server.com. Useful for accessing web interfaces running on a server that aren’t directly exposed.
Remote Port Forwarding (-R):
Forward a port on the remote server to a local service.
ssh -R 9090:localhost:3000 user@remote-server.com
Connects to remote-server.com. Any traffic sent to port 9090 on remote-server.com will be forwarded to port 3000 on your local machine. Useful for exposing a local development server to the outside world via a remote server.
Dynamic Port Forwarding (SOCKS Proxy) (-D):
Create a SOCKS proxy on your local machine.
ssh -D 1080 user@remote-server.com
Connects to remote-server.com. Configure your browser or application to use localhost:1080 as a SOCKS proxy. All traffic routed through this proxy will exit from remote-server.com.
SSH Keys Management
Generate SSH Key Pair:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
Creates a new SSH key pair (id_rsa and id_rsa.pub by default). -t specifies the type (e.g., rsa, ed25519), -b specifies the bit size, -C adds a comment.
Copy Public Key to Remote Server:
ssh-copy-id user@hostname
Appends your default public key (~/.ssh/id_rsa.pub) to the remote user’s ~/.ssh/authorized_keys file. You’ll be prompted for the user’s password.
Copy Public Key to Remote Server (Specific Key):
ssh-copy-id -i ~/.ssh/my_other_key.pub user@hostname
Copies the specified public key.
Manually Add Public Key to authorized_keys:
- Copy the content of your local
~/.ssh/id_rsa.pubfile. - SSH into the remote server using password authentication.
- Create the
~/.sshdirectory if it doesn’t exist:mkdir -p ~/.ssh - Set correct permissions:
chmod 700 ~/.ssh - Append the public key content to
~/.ssh/authorized_keys:echo "ssh-rsa AAAAB3NzaC1yc2E..." >> ~/.ssh/authorized_keys - Set correct permissions:
chmod 600 ~/.ssh/authorized_keys
Other Useful Flags
-A: Enable agent forwarding. Allows you to use your local SSH keys on intermediate servers without copying them. Use with caution.-X/-Y: Enable X11 forwarding. Allows you to run graphical applications on the remote server and display them on your local machine.-Yis generally preferred for trusted connections.-N: Do not execute a remote command. Useful for just setting up port forwarding.-f: Requests ssh to go to background just before command execution. Useful when used with port forwarding.-t: Force pseudo-terminal allocation. Often needed when running interactive commands or scripts that expect a TTY.
Common Patterns
Transferring a directory using tar and ssh:
tar czf - /path/to/local/directory | ssh user@hostname 'tar xzf - -C /path/to/remote/destination'
Compresses a local directory, pipes it over SSH, and uncompresses it on the remote server. Faster than scp -r for large directories.
Syncing directories using rsync over SSH:
rsync -avz -e "ssh -p 2222 -i ~/.ssh/id_rsa_prod" /path/to/local/source/ user@hostname:/path/to/remote/destination/
Efficiently synchronizes files and directories. -a archive mode, -v verbose, -z compress, -e specifies the remote shell command.
Executing a local script on a remote server and capturing output:
REMOTE_USER="user"
REMOTE_HOST="hostname"
LOCAL_SCRIPT="/path/to/local/script.sh"
ssh ${REMOTE_USER}@${REMOTE_HOST} 'bash -s' < ${LOCAL_SCRIPT} > /tmp/remote_output.log
Setting up a persistent SSH tunnel for database access:
ssh -f -N -L 5432:localhost:5432 user@db-server.com
Runs in the background (-f -N) and forwards local port 5432 (PostgreSQL default) to the remote database port 5432. You can then connect your local DB client to localhost:5432.
Disabling password authentication and enabling key-only auth:
- Generate keys and copy the public key to the server (
ssh-keygen,ssh-copy-id). - Test key authentication:
ssh user@hostname. - Edit the SSH server configuration on the remote machine:
sudo nano /etc/ssh/sshd_config. - Set
PasswordAuthentication no. - Restart the SSH service:
sudo systemctl restart sshd(orsudo service ssh restart).
Gotchas
- Permissions on
~/.sshandauthorized_keys: Incorrect permissions (e.g., world-writable) on your local~/.sshdirectory, private key files, or the remote~/.sshdirectory andauthorized_keysfile will cause SSH to refuse authentication. They should typically be700for directories and600for files. ssh-agentnot running or key not added: If you get "Permission denied (publickey)" errors even with keys set up, ensuressh-agentis running and your key has been added usingssh-add.- Firewall issues: Ensure the SSH port (default 22) is open on the server’s firewall and any intermediate network firewalls.
- Host Key Verification: The first time you connect to a server, SSH will ask you to verify the server’s host key. If this prompt appears unexpectedly later, it might indicate a man-in-the-middle attack or that the server’s IP has been reassigned.
- Agent Forwarding (
-A): While convenient, agent forwarding can be a security risk if the remote host is compromised. An attacker on the remote host could potentially use your forwarded agent connection to access other servers you have access to. scpvsrsync:scpcopies files directly.rsyncis more efficient for repeated transfers or large files/directories as it only transfers differences.- Pseudo-terminal allocation (
-t): Some commands or scripts require a TTY (terminal). If a remote command fails unexpectedly, try adding the-tflag (e.g.,ssh -t user@host 'sudo apt update').