SSH Essentials

Master secure shell access — from basic connections and key authentication to essential Linux commands, file transfers, and server hardening.

What Is SSH?

SSH (Secure Shell) is a cryptographic network protocol for securely accessing and managing remote servers over an unsecured network. Unlike FTP which only transfers files, SSH gives you a full command-line interface on the remote machine — you can edit files, restart services, view logs, manage databases, and do virtually anything the server can do.

SSH vs FTP

SSH/SFTP encrypts everything — credentials and data. Gives you a full terminal. Runs on port 22.
FTP sends credentials in plain text (unless using FTPS). File transfers only. Runs on port 21.
For modern server management, SSH is always the preferred choice. See our FTP guide for when FTP is still necessary.

Connecting via SSH

The basic SSH connection command:

# Basic connection
ssh username@hostname

# Specify a custom port
ssh username@hostname -p 2222

# Connect to a server by IP
ssh root@192.168.1.100

# Connect with verbose output (for debugging)
ssh -v username@hostname

On Windows, you can use the built-in OpenSSH client (Windows 10+), PuTTY, or Windows Terminal. On macOS and Linux, SSH is built into the terminal.

SSH Key Authentication

Password authentication is convenient but vulnerable to brute-force attacks. SSH keys are significantly more secure — they use public-key cryptography to authenticate without sending a password over the network.

Generate an SSH Key Pair

# Generate a 4096-bit RSA key pair
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# Or use the newer Ed25519 algorithm (recommended)
ssh-keygen -t ed25519 -C "your_email@example.com"

# You'll be prompted for a save location and passphrase
# Default location: ~/.ssh/id_rsa or ~/.ssh/id_ed25519

Copy Your Public Key to the Server

# The easy way (Linux/macOS)
ssh-copy-id username@hostname

# Manual method (works everywhere)
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Test Key-Based Login

# Should connect without asking for password
ssh username@hostname

# If it still asks for a password, check permissions:
# ~/.ssh directory: 700
# ~/.ssh/authorized_keys: 600

Essential Linux Commands via SSH

Navigation & File Inspection

# Where am I?
pwd

# List files with details
ls -la

# List files sorted by modification time
ls -lt

# Change directory
cd /var/www/html

# Show disk usage of current directory
du -sh *

# Find files by name
find /var/www -name "*.php" -type f

File Operations

# Copy files
cp source.txt destination.txt
cp -r source_dir/ destination_dir/

# Move or rename
mv old_name.txt new_name.txt

# Delete files (use with caution!)
rm filename.txt
rm -rf directory_name/

# Create directories
mkdir -p /path/to/new/directory

# Edit files with nano (beginner-friendly)
nano /etc/nginx/nginx.conf

# Edit files with vim (powerful)
vim /etc/apache2/apache2.conf

Permissions & Ownership

# Change file permissions
chmod 644 file.txt        # rw-r--r--
chmod 755 directory/      # rwxr-xr-x
chmod +x script.sh        # Make executable

# Change ownership
chown www-data:www-data file.txt
chown -R www-data:www-data /var/www/html/

Service Management (systemd)

# Check service status
systemctl status nginx
systemctl status apache2
systemctl status mysql

# Start / Stop / Restart
systemctl start nginx
systemctl stop nginx
systemctl restart nginx

# Reload config without downtime
systemctl reload nginx

# Enable service to start on boot
systemctl enable nginx

Log Viewing

# View last 50 lines of a log
tail -50 /var/log/apache2/error.log

# Watch a log in real-time
tail -f /var/log/nginx/access.log

# View systemd service logs
journalctl -u nginx --since "1 hour ago"
journalctl -u apache2 -f    # follow in real-time

# Search logs for a pattern
grep "error" /var/log/syslog | tail -20

Process Management

# List all running processes
ps aux

# Find a specific process
ps aux | grep nginx

# Interactive process monitor
top
htop    # (more user-friendly, may need to install)

# Kill a process by PID
kill 12345
kill -9 12345    # Force kill

SCP File Transfers

SCP (Secure Copy) lets you transfer files over SSH without needing a separate FTP connection:

# Upload a file to the server
scp local_file.txt user@host:/remote/path/

# Download a file from the server
scp user@host:/remote/path/file.txt ./local_destination/

# Upload an entire directory
scp -r local_directory/ user@host:/remote/path/

# Use a custom port
scp -P 2222 file.txt user@host:/path/

SSH Config File

Create ~/.ssh/config to save connection settings and connect with short aliases:

# ~/.ssh/config
Host myserver
    HostName 192.168.1.100
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host production
    HostName prod.example.com
    User deploy
    IdentityFile ~/.ssh/deploy_key

# Now you can simply type:
# ssh myserver
# ssh production

SSH Tunneling & Port Forwarding

SSH tunnels let you securely access remote services through an encrypted connection:

# Local port forwarding: access remote MySQL on localhost:3307
ssh -L 3307:localhost:3306 user@server

# Access a remote web panel on localhost:8080
ssh -L 8080:localhost:8080 user@server

# Dynamic SOCKS proxy (browse through the server)
ssh -D 9090 user@server

SSH Troubleshooting

  • Permission denied (publickey) — your key isn't on the server or permissions are wrong on ~/.ssh (must be 700) and authorized_keys (must be 600)
  • Connection refused — SSH service isn't running (systemctl start sshd) or the port is blocked by a firewall
  • Connection timed out — wrong IP/hostname, network issue, or firewall blocking port 22
  • Host key verification failed — the server's fingerprint changed (reinstall or IP change). Remove the old entry: ssh-keygen -R hostname

Security Best Practices

Harden Your SSH Server

Edit /etc/ssh/sshd_config and apply these settings:

# /etc/ssh/sshd_config

# Disable root login
PermitRootLogin no

# Disable password authentication (key-only)
PasswordAuthentication no

# Change default port (obscurity, not security alone)
Port 2222

# Allow only specific users
AllowUsers deploy admin

# Set idle timeout (disconnect after 10 min inactive)
ClientAliveInterval 300
ClientAliveCountMax 2

After editing, restart SSH: systemctl restart sshd

Additional security measures:

  • Install fail2ban to automatically block IPs with too many failed login attempts
  • Use UFW or iptables to restrict SSH access to specific IPs
  • Set up two-factor authentication with Google Authenticator PAM module
  • Keep your server's SSH software updated
# Install and enable fail2ban
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# Basic UFW firewall setup
sudo ufw allow 2222/tcp    # Allow SSH on custom port
sudo ufw enable
Pro Tip

Always test your new SSH configuration in a separate terminal session before closing your current one. If something is misconfigured, you'll still have access through the existing connection to fix it.