# SSH

***

### What is SSH?

[Visual explanation](https://www.youtube.com/watch?v=rlMfRa7vfO8)

**SSH (Secure Shell)** is a protocol that lets you securely access and control remote computers over a network. Think of it as a secure way to log into another computer and run commands as if you were sitting right in front of it.

**What Problem Does SSH Solve?**

Before SSH, people used **Telnet** and **rlogin** to remotely access computers. Just like FTP and HTTP, these sent everything in **plain text** - including passwords! SSH was created in 1995 to fix this massive security problem.

**What SSH Does**

SSH provides three main services:

**Remote Command Execution** - Run commands on another computer

**Secure File Transfer** - Transfer files (this is what SFTP uses)

**Port Forwarding/Tunneling** - Securely connect to services through an encrypted tunnel

<figure><img src="https://2332658533-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FG5fhKjYnbaQlTPTcaO85%2Fuploads%2FOOan8u14dZUq668V8KeC%2Fssh-overview-diagram.svg?alt=media&#x26;token=505e8ab0-2854-4f81-878a-c92942740ce0" alt=""><figcaption></figcaption></figure>

***

#### How SSH Authentication Works

SSH offers two main ways to authenticate:

**1. Password Authentication (Simple but less secure)**

You type your password each time you connect. The password is encrypted, unlike Telnet.

**2. Key-Based Authentication (More secure, no password needed!)**

Uses a pair of cryptographic keys:

* **Private key** - Stays on your computer (never share this!)
* **Public key** - Goes on the server (safe to share)

Think of it like a lock and key: the server has the lock (public key), and only your key (private key) can open it.

***

### Basic SSH Commands in Bash

Let me show you practical examples:

#### Example 1: Basic SSH Connection

```bash
# Connect to a remote server
ssh username@server.com

# Example with specific user
ssh john@192.168.1.100

# Specify a different port (default is 22)
ssh -p 2222 admin@example.com
```

**What happens:**

1. You run the command
2. SSH connects to the server
3. You're prompted for a password (or uses your SSH key)
4. You get a remote shell - you're now "inside" the remote computer!
5. Type `exit` or press `Ctrl+D` to disconnect

#### Example 2: Run a Single Command Remotely

```bash
# Execute one command and return to your local terminal
ssh user@server.com "uptime"

# Check disk space on remote server
ssh admin@server.com "df -h"

# Restart a service remotely
ssh root@webserver.com "systemctl restart nginx"

# Get list of running processes
ssh user@server.com "ps aux | grep python"
```

#### Example 3: Generate SSH Keys

```bash
# Generate a new SSH key pair
ssh-keygen -t ed25519 -C "your_email@example.com"

# You'll be prompted:
# Enter file in which to save the key (/home/user/.ssh/id_ed25519): [press Enter]
# Enter passphrase (empty for no passphrase): [type passphrase or press Enter]

# This creates two files:
# ~/.ssh/id_ed25519      (private key - keep secret!)
# ~/.ssh/id_ed25519.pub  (public key - share this)
```

#### Example 4: Copy Your Public Key to a Server

```bash
# Easy way: use ssh-copy-id
ssh-copy-id username@server.com

# This copies your public key to the server's ~/.ssh/authorized_keys file
# After this, you can log in without a password!

# Manual way (if ssh-copy-id isn't available):
cat ~/.ssh/id_ed25519.pub | ssh username@server.com "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
```

#### Example 5: File Transfer with SCP (SSH Copy)

```bash
# Copy file FROM local TO remote
scp document.pdf user@server.com:/home/user/documents/

# Copy file FROM remote TO local
scp user@server.com:/var/log/app.log ./local-folder/

# Copy entire directory (recursive)
scp -r ./website/ user@server.com:/var/www/html/

# Copy with different port
scp -P 2222 file.txt user@server.com:/tmp/
```

#### Example 6: Interactive File Transfer with SFTP

```bash
# Start an SFTP session
sftp user@server.com

# Once connected, you can use commands:
sftp> ls                    # List remote files
sftp> pwd                   # Show remote directory
sftp> lpwd                  # Show local directory
sftp> cd /var/www          # Change remote directory
sftp> lcd ~/Desktop        # Change local directory
sftp> get remote-file.txt  # Download file
sftp> put local-file.txt   # Upload file
sftp> exit                 # Disconnect
```

#### Example 7: SSH Config File (Save Connection Details)

```bash
# Edit your SSH config file
nano ~/.ssh/config

# Add server shortcuts:
Host webserver
    HostName 192.168.1.100
    User admin
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Host production
    HostName prod.example.com
    User deploy
    Port 2222
    
# Now you can just type:
ssh webserver
# Instead of: ssh admin@192.168.1.100
```

#### Example 8: SSH Tunneling (Port Forwarding)

```bash
# Local port forwarding - access remote service locally
# Access remote database on your local port 3307
ssh -L 3307:localhost:3306 user@dbserver.com

# Now connect to localhost:3307 on your machine,
# and it forwards to port 3306 on the remote server

# Dynamic port forwarding (SOCKS proxy)
ssh -D 8080 user@server.com
# Now configure your browser to use localhost:8080 as a SOCKS proxy
# All your traffic goes through the SSH tunnel!
```

#### Example 9: Keep SSH Connection Alive

```bash
# Add to ~/.ssh/config to prevent timeouts
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

# Or use this flag when connecting:
ssh -o ServerAliveInterval=60 user@server.com
```

#### Example 10: Real-World Deployment Script

```bash
#!/bin/bash
# Deploy website to production server

SERVER="user@production-server.com"
REMOTE_PATH="/var/www/mysite"
LOCAL_PATH="./build"

echo "Deploying to production..."

# Connect via SSH and run multiple commands
ssh $SERVER << 'EOF'
    echo "Backing up current version..."
    cd /var/www
    tar -czf mysite-backup-$(date +%Y%m%d).tar.gz mysite/
    
    echo "Stopping web server..."
    sudo systemctl stop nginx
EOF

# Copy new files
echo "Uploading new files..."
scp -r $LOCAL_PATH/* $SERVER:$REMOTE_PATH/

# Restart services
ssh $SERVER << 'EOF'
    echo "Starting web server..."
    sudo systemctl start nginx
    
    echo "Deployment complete!"
    echo "Current time on server:"
    date
EOF

echo "Local deployment script finished!"
```

***

#### SSH Security Best Practices

**Use key-based authentication** instead of passwords

**Disable root login** - edit `/etc/ssh/sshd_config` and set `PermitRootLogin no`

**Change default port** from 22 to something else (security through obscurity)

**Use strong passphrases** for your private keys

**Keep your private key private** - never share it or commit it to Git!

**Disable password authentication** once keys are set up: `PasswordAuthentication no`

#### Where SSH is Used

**System Administration** - Managing Linux/Unix servers

**Web Development** - Deploying websites and applications

**Cloud Computing** - Accessing AWS EC2, Digital Ocean droplets, etc.

**Git Operations** - GitHub, GitLab use SSH for secure code push/pull

**DevOps** - Automated deployments, CI/CD pipelines

**IoT Devices** - Managing Raspberry Pi, routers, embedded systems

**Database Management** - Secure remote database access

***

#### SSH vs Telnet: Why SSH Won

| Feature        | Telnet                | SSH                        |
| -------------- | --------------------- | -------------------------- |
| Encryption     | None                  | Full                       |
| Authentication | Plain text password   | Keys or encrypted password |
| Port           | 23                    | 22                         |
| Security       | ❌ Completely insecure | ✅ Industry standard        |
| Status         | Dead/deprecated       | Actively used everywhere   |

**Telnet is to SSH what HTTP is to HTTPS** - the old, insecure version that should never be used anymore.

***

#### Quick Troubleshooting

```bash
# Check if SSH service is running
sudo systemctl status ssh

# Test SSH connection with verbose output
ssh -v user@server.com

# Check SSH key permissions (must be 600)
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

# View SSH logs on server
sudo tail -f /var/log/auth.log
```

SSH is the backbone of modern server management and secure remote access. Once you get comfortable with it, you'll wonder how anyone ever managed servers without it!

***

**Replaces older protocols:** SSH was designed to replace older, less secure protocols like [Telnet](https://www.google.com/search?q=Telnet\&oq=is+ssh+part+of+networking\&gs_lcrp=EgZjaHJvbWUyBggAEEUYOdIBCDM0NjVqMGoxqAIAsAIA\&sourceid=chrome\&ie=UTF-8\&sei=AfgSafnYN86J9u8PxcCb6Ak\&mstk=AUtExfApdQlE_6W7zfNqYDFoAaHf5zRHO_is1QVv_tznKoYZwXqsG_TMkWhB1lOxxWw9bMYd0aFJBF0kYT0BszUSyFh55lxcucXDZYOaXxqC0o9mEO9qYMZmE8MOtLEeGzvETdQ\&csui=3\&ved=2ahUKEwiSmMuG2-mQAxWt97sIHX3CPUUQgK4QegQIAxAE) and [FTP](https://www.google.com/search?q=FTP\&oq=is+ssh+part+of+networking\&gs_lcrp=EgZjaHJvbWUyBggAEEUYOdIBCDM0NjVqMGoxqAIAsAIA\&sourceid=chrome\&ie=UTF-8\&sei=AfgSafnYN86J9u8PxcCb6Ak\&mstk=AUtExfApdQlE_6W7zfNqYDFoAaHf5zRHO_is1QVv_tznKoYZwXqsG_TMkWhB1lOxxWw9bMYd0aFJBF0kYT0BszUSyFh55lxcucXDZYOaXxqC0o9mEO9qYMZmE8MOtLEeGzvETdQ\&csui=3\&ved=2ahUKEwiSmMuG2-mQAxWt97sIHX3CPUUQgK4QegQIAxAF) that transmit data in plain text.

***

### Explainer video

{% embed url="<https://www.youtube.com/watch?v=WwGRGfLy6q8&t=190s&pp=ugUEEgJlbg%3D%3D>" %}

***
