# WEBONICTECH — INTERNAL SERVER & DEPLOYMENT HANDBOOK
## Complete Training Guide for Freshers, Interns & Junior Developers

---

> **Document Version:** 1.0  
> **Prepared By:** Senior DevOps & Linux Administration Team  
> **Organization:** WEBONICTECH  
> **Audience:** Freshers, Web Development Interns, Junior PHP/Node.js/WordPress/Laravel/React Developers  
> **Last Updated:** 2026  

---

> **READ THIS FIRST:**  
> This handbook is your companion on the server. Treat it like a recipe book. You do not need to memorize everything. You need to know WHERE to find things and HOW to think when something breaks. Every senior developer was once confused by a 502 error. The goal of this handbook is to make sure you never panic — you just follow the process.

---

# TABLE OF CONTENTS

| Section | Title |
|---------|-------|
| 1 | Introduction to Servers |
| 2 | Linux Fundamentals |
| 3 | Apache2 Complete Guide |
| 4 | Nginx Complete Guide |
| 5 | Node.js Server Deployment |
| 6 | PHP Ecosystem |
| 7 | Database Management |
| 8 | WordPress Server Management |
| 9 | SSL, Domains, DNS |
| 10 | File Permissions & Security |
| 11 | Server Troubleshooting Master Guide |
| 12 | Deployment Workflows |
| 13 | Best Practices |
| 14 | Real-World Scenarios |
| 15 | Final Checklists |
| 16 | Glossary |
| — | Learning Roadmap for Freshers |
| — | Daily Practice Plan for Interns |
| — | Interview Questions & Answers |
| — | Mini Labs & Practice Tasks |

---

---

# SECTION 1 — INTRODUCTION TO SERVERS

---

## 1.1 What Is a Server?

Think of a server as a **powerful computer that runs 24/7**, waiting for people to connect and ask for things — web pages, images, database data, etc.

Your laptop is a computer. A server is also just a computer. The difference?

| Your Laptop | A Server |
|-------------|----------|
| Turned off at night | Runs 24 hours a day, 7 days a week |
| Used by 1 person | Used by hundreds to millions of people simultaneously |
| Has a screen, keyboard | Usually has no screen — managed remotely |
| Consumer hardware | High-performance hardware (more RAM, CPU cores, RAID storage) |
| Runs Windows or macOS | Usually runs Linux |
| Located at your desk | Located in a Data Center |

**Real-world analogy:** A restaurant kitchen. The client is the customer. The server is the kitchen. When the customer (browser) orders food (a web page), the kitchen (server) prepares it and sends it to the table (browser).

---

## 1.2 What Is Linux?

Linux is an **operating system** — just like Windows or macOS, but:

- It is **free and open source**
- It is **extremely stable** — servers run for years without rebooting
- It is **lightweight** — no fancy GUI needed
- It is **secure** — designed from the ground up for multi-user environments
- **90%+ of all web servers in the world run Linux**

Linux comes in different "flavors" called **distributions (distros)**:

| Distribution | Used For |
|--------------|----------|
| Ubuntu | Web servers, development (most popular for beginners) |
| Debian | Stable production servers |
| CentOS / AlmaLinux | Enterprise environments |
| Fedora | Development machines |
| Alpine | Docker containers |
| Kali Linux | Security testing |

> **At WEBONICTECH, we primarily use Ubuntu 20.04 LTS or Ubuntu 22.04 LTS on our servers.**

---

## 1.3 What Is Ubuntu?

Ubuntu is the **most popular Linux distribution** for servers. It is developed by Canonical. LTS means "Long-Term Support" — meaning it gets security updates for 5 years.

Ubuntu is beginner-friendly because:
- Huge community support
- Excellent documentation
- Easy package management (`apt`)
- Compatible with most server software

---

## 1.4 What Is a VPS?

**VPS = Virtual Private Server**

A VPS is a virtual machine hosted in a data center. You rent it from providers like:
- **DigitalOcean** (Droplets)
- **AWS EC2** (Amazon)
- **Linode / Akamai**
- **Vultr**
- **Hetzner**
- **Hostinger VPS**
- **Contabo**

**How it works:** A physical server in a data center is divided into multiple virtual servers using virtualization software (like KVM or VMware). Each virtual server acts like a completely independent machine.

```
Physical Server (e.g., 64GB RAM, 32 CPU cores)
├── VPS 1 (4GB RAM, 2 CPU) → Your client's server
├── VPS 2 (8GB RAM, 4 CPU) → Another client's server
├── VPS 3 (2GB RAM, 1 CPU) → Staging server
└── VPS 4 (16GB RAM, 8 CPU) → Large e-commerce server
```

**What you get with a VPS:**
- A dedicated IP address
- Root access (full control)
- Choose your OS (Ubuntu, CentOS, etc.)
- Specific RAM, CPU, and storage
- You manage everything yourself

---

## 1.5 What Is Shared Hosting?

Shared hosting is the cheapest option. **Hundreds of websites share the same server**.

| Feature | Shared Hosting | VPS |
|---------|----------------|-----|
| Control | Very Limited | Full Root Access |
| Performance | Affected by other users | Dedicated resources |
| Price | Cheapest ($3-$10/month) | Moderate ($5-$80/month) |
| Customization | Almost none | Fully customizable |
| Use case | Simple WordPress sites | Business apps, custom setups |

**Limitation:** If another website on your shared server sends spam emails, YOUR domain might also get blacklisted. You share the same IP.

---

## 1.6 What Is Cloud Hosting?

Cloud hosting uses **a network of virtual servers** instead of one physical server. Your website can scale up automatically.

Examples:
- **AWS (Amazon Web Services)** — EC2, S3, RDS
- **Google Cloud Platform (GCP)**
- **Microsoft Azure**
- **Cloudflare Pages / Workers**
- **Vercel, Netlify** — Frontend cloud hosting

**Key concept:** Cloud = scalable, pay-as-you-go, distributed infrastructure.

---

## 1.7 Local Machine vs Production Server

This is one of the most important concepts for a fresher to understand.

```
Your Local Machine                    Production Server
─────────────────                     ──────────────────
Windows / macOS / Ubuntu              Ubuntu Linux (headless)
XAMPP / Laragon / WAMP                Apache2 / Nginx + PHP-FPM
MySQL (local)                         MySQL (production, secured)
localhost:8000                        yourdomain.com
Only you access it                    Thousands of users access it
You can break and fix quickly         Breaking it = customer downtime
.env has debug=true                   .env has debug=false (NEVER expose)
Loose file permissions (777 OK here)  Strict permissions (644, 755)
No SSL needed                         SSL mandatory
```

> **Golden Rule for Freshers:** What works on your local machine may NOT work on the server immediately. Always check permissions, paths, environment variables, and PHP versions.

---

## 1.8 Client-Server Architecture

Every website interaction follows this pattern:

```
┌──────────────┐         HTTP Request          ┌──────────────────────┐
│              │ ─────────────────────────────► │                      │
│   Browser    │                                │   Web Server         │
│  (Client)    │ ◄───────────────────────────── │  (Apache2 / Nginx)   │
│              │         HTTP Response          │                      │
└──────────────┘                                └──────────────────────┘
                                                          │
                                                          │ (if dynamic)
                                                          ▼
                                               ┌──────────────────────┐
                                               │  Application Layer   │
                                               │  PHP / Node.js /     │
                                               │  Python / etc.       │
                                               └──────────────────────┘
                                                          │
                                                          │
                                                          ▼
                                               ┌──────────────────────┐
                                               │   Database           │
                                               │   MySQL / MongoDB /  │
                                               │   PostgreSQL         │
                                               └──────────────────────┘
```

---

## 1.9 What Happens When You Type a Domain in the Browser?

This is one of the most asked interview questions. Know this process deeply.

```
User types: https://www.example.com
          │
          ▼
1. Browser Cache Check
   └── Has the browser seen this domain before? If yes, skip DNS.
          │
          ▼
2. OS Cache / hosts file Check
   └── /etc/hosts on Linux, C:\Windows\System32\drivers\etc\hosts on Windows
          │
          ▼
3. DNS Resolver (ISP or Google 8.8.8.8)
   └── "Who is example.com? Where does it live?"
          │
          ▼
4. Root DNS Server → TLD Server (.com) → Authoritative DNS Server
   └── Returns IP address: 203.0.113.42
          │
          ▼
5. Browser connects to 203.0.113.42 on Port 443 (HTTPS) or Port 80 (HTTP)
          │
          ▼
6. TCP Handshake (SYN → SYN-ACK → ACK)
          │
          ▼
7. SSL/TLS Handshake (HTTPS only)
   └── Server sends certificate, browser verifies it
          │
          ▼
8. HTTP Request sent:
   GET / HTTP/1.1
   Host: www.example.com
   User-Agent: Chrome/120
          │
          ▼
9. Web Server (Apache2 / Nginx) receives request
   └── Matches the correct Virtual Host / Server Block
          │
          ▼
10. Application processes request (PHP, Node.js, etc.)
    └── Queries database if needed
          │
          ▼
11. Response is sent back:
    HTTP/1.1 200 OK
    Content-Type: text/html
    <html>...</html>
          │
          ▼
12. Browser renders the HTML, downloads CSS/JS/images
    └── Page is visible to the user
```

---

## 1.10 DNS Basics

**DNS = Domain Name System** — The phone book of the internet.

Key record types you need to know:

| Record Type | Purpose | Example |
|-------------|---------|---------|
| **A Record** | Maps domain to IPv4 | `example.com → 203.0.113.42` |
| **AAAA Record** | Maps domain to IPv6 | `example.com → 2001:db8::1` |
| **CNAME Record** | Alias to another domain | `www → example.com` |
| **MX Record** | Mail server | `example.com → mail.example.com` |
| **TXT Record** | Verification, SPF, DKIM | Various |
| **NS Record** | Nameservers for domain | `ns1.cloudflare.com` |

**DNS Propagation:** When you change DNS records, it can take **up to 48 hours** to update worldwide. Usually it's 15 minutes to 2 hours with Cloudflare.

---

## 1.11 HTTP and HTTPS Basics

**HTTP (Hypertext Transfer Protocol):**
- Data travels in **plain text**
- Port **80**
- Not secure — anyone on the same network can read the data

**HTTPS (HTTP Secure):**
- Data is **encrypted** using SSL/TLS
- Port **443**
- Mandatory for all production websites in 2026
- Required by browsers (Chrome shows "Not Secure" without it)

**HTTP Methods you must know:**

| Method | Use |
|--------|-----|
| GET | Fetch data (loading a page) |
| POST | Send data (form submission) |
| PUT | Update a resource completely |
| PATCH | Update part of a resource |
| DELETE | Delete a resource |
| OPTIONS | Check what methods are allowed |

---

## 1.12 SSL/TLS Basics

**SSL (Secure Sockets Layer)** — now technically called **TLS (Transport Layer Security)**, but we still call it SSL informally.

SSL does three things:
1. **Encryption** — Data is scrambled so nobody can read it in transit
2. **Authentication** — Verifies the server is who it says it is
3. **Integrity** — Ensures data wasn't tampered with

SSL certificates are issued by **Certificate Authorities (CA)**:
- Let's Encrypt (free, automated — what we use)
- DigiCert, Comodo, GlobalSign (paid)

> **Fresher Tip:** Always use HTTPS. Let's Encrypt gives free SSL. Use Certbot to set it up. We'll cover this fully in Section 9.

---

## 1.13 Ports and Protocols

Every service on a server listens on a **port** (a numbered door).

| Port | Protocol/Service |
|------|-----------------|
| 22 | SSH (remote access) |
| 80 | HTTP (web) |
| 443 | HTTPS (secure web) |
| 21 | FTP (file transfer — avoid on production) |
| 3306 | MySQL database |
| 5432 | PostgreSQL database |
| 27017 | MongoDB |
| 6379 | Redis |
| 25 | SMTP (email sending) |
| 587 | SMTP (email, authenticated) |
| 3000 | Node.js apps (common default) |
| 8000 | Python/PHP dev servers |
| 9000 | PHP-FPM |

> **Security Rule:** Only open ports you actually need. Use a firewall (`ufw`) to block everything else.

---

## 1.14 Frontend / Backend / Database / Server — The Layers

```
┌────────────────────────────────────────────────────────────┐
│                        SERVER                              │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              WEB SERVER LAYER                       │   │
│  │         Apache2 / Nginx                             │   │
│  │   (Handles HTTP requests, SSL, routing)             │   │
│  └─────────────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │             BACKEND / APPLICATION LAYER             │   │
│  │   PHP (Laravel/WordPress) / Node.js / Python        │   │
│  │   (Business logic, authentication, processing)      │   │
│  └─────────────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              DATABASE LAYER                         │   │
│  │          MySQL / MongoDB / Redis                    │   │
│  │       (Stores and retrieves data)                   │   │
│  └─────────────────────────────────────────────────────┘   │
└────────────────────────────────────────────────────────────┘
         ▲
         │  HTTP/HTTPS
         ▼
┌────────────────────┐
│   FRONTEND         │
│   HTML/CSS/JS      │
│   React/Vue        │
│   (Runs in browser)│
└────────────────────┘
```

---

---

# SECTION 2 — LINUX FUNDAMENTALS

---

## 2.1 The Linux Directory Structure

Unlike Windows (C:\, D:\), Linux has ONE root directory: `/`

Everything branches from `/`.

```
/                          ← Root (top of everything)
├── bin/                   ← Essential binaries (ls, cat, echo)
├── boot/                  ← Boot loader files (don't touch)
├── dev/                   ← Device files (hard drives, USB)
├── etc/                   ← All system configuration files
│   ├── apache2/           ← Apache config
│   ├── nginx/             ← Nginx config
│   ├── mysql/             ← MySQL config
│   ├── ssh/               ← SSH config
│   └── crontab            ← System cron jobs
├── home/                  ← Home folders for regular users
│   ├── ubuntu/            ← User "ubuntu"
│   └── developer/         ← User "developer"
├── lib/                   ← Shared libraries
├── media/                 ← Mounted drives (USB etc)
├── mnt/                   ← Temporarily mounted filesystems
├── opt/                   ← Optional/third-party software
├── proc/                  ← Virtual filesystem — running processes
├── root/                  ← Home folder for the root user
├── run/                   ← Runtime data
├── sbin/                  ← System admin binaries
├── srv/                   ← Service data (FTP, web data sometimes)
├── sys/                   ← Kernel and hardware info
├── tmp/                   ← Temporary files (cleared on reboot)
├── usr/                   ← User programs and data
│   ├── bin/               ← Most user commands live here
│   ├── lib/               ← Libraries
│   └── local/             ← Manually installed programs
└── var/                   ← Variable data (logs, mail, databases)
    ├── log/               ← ALL system logs live here
    │   ├── apache2/       ← Apache access and error logs
    │   ├── nginx/         ← Nginx logs
    │   ├── mysql/         ← MySQL logs
    │   └── syslog         ← General system log
    └── www/               ← Web files root
        └── html/          ← Default web root
```

### Key Directories Explained

**`/etc`** — Think of this as the "Settings" folder of Linux. Every application stores its config files here.
```bash
/etc/apache2/           # Apache configuration
/etc/nginx/             # Nginx configuration
/etc/php/               # PHP configuration
/etc/mysql/             # MySQL configuration
/etc/hosts              # Local DNS overrides
/etc/ssh/sshd_config    # SSH server settings
/etc/crontab            # System-wide cron jobs
```

**`/var/www`** — This is where your website files live. The standard path is:
```bash
/var/www/html/          # Default web root
/var/www/mysite/        # Your custom site
/var/www/client-project/ # Client project
```

**`/var/log`** — This is the most important folder for debugging.
```bash
/var/log/apache2/access.log   # Apache access log
/var/log/apache2/error.log    # Apache error log
/var/log/nginx/access.log     # Nginx access log
/var/log/nginx/error.log      # Nginx error log
/var/log/syslog               # General system log
/var/log/auth.log             # Login/authentication attempts
/var/log/mysql/error.log      # MySQL errors
```

**`/home`** — Each user has their own folder here.
```bash
/home/ubuntu/          # SSH user's files, projects, scripts
/home/ubuntu/.bashrc   # User's shell configuration
/home/ubuntu/.ssh/     # SSH keys
```

**`/tmp`** — Temporary files. Cleared on every reboot. Do NOT store important data here.

**`/opt`** — For software you install manually (not via apt). Example: Node.js installed via nvm.

---

## 2.2 Connecting to a Server via SSH

SSH (Secure Shell) is how you control a server remotely. There is no screen or keyboard — you type commands and the server responds.

```bash
# Connect using password
ssh username@server-ip
ssh ubuntu@203.0.113.42

# Connect using SSH key (recommended and more secure)
ssh -i /path/to/private-key.pem ubuntu@203.0.113.42

# Connect on a different port (if SSH was moved from default 22)
ssh -p 2222 ubuntu@203.0.113.42
```

**First time connecting:**
```
The authenticity of host '203.0.113.42' can't be established.
ECDSA key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no)?
```
Type `yes` — this saves the server's fingerprint so you recognize it in future.

---

## 2.3 Navigation Commands

```bash
# Where am I right now?
pwd
# Output: /var/www/html

# List files in current directory
ls
ls -l          # Long format (shows permissions, owner, size)
ls -la         # Long format + hidden files (starting with .)
ls -lh         # Human-readable file sizes
ls -lt         # Sort by time (newest first)

# Change directory
cd /var/www/html          # Go to absolute path
cd mysite                 # Go to folder named 'mysite' inside current dir
cd ..                     # Go up one level
cd ~                      # Go to your home folder
cd -                      # Go to previous directory

# Clear terminal screen
clear
# or press Ctrl + L
```

---

## 2.4 File and Directory Operations

### Creating Files and Folders
```bash
# Create a directory
mkdir myproject
mkdir -p /var/www/myproject/public   # -p creates parent dirs too

# Create an empty file
touch index.php
touch .env

# Create a file with content
echo "<?php echo 'Hello'; ?>" > index.php
echo "APP_ENV=production" >> .env    # >> appends, > overwrites
```

### Viewing Files
```bash
# Print entire file to terminal
cat /etc/nginx/nginx.conf

# View file page by page (press q to quit)
less /var/log/nginx/error.log

# View first 10 lines
head /var/log/nginx/error.log

# View last 10 lines
tail /var/log/nginx/error.log

# Follow a log file in real-time (VERY useful for debugging)
tail -f /var/log/nginx/error.log
tail -f /var/log/apache2/error.log

# View last 50 lines and follow
tail -n 50 -f /var/log/apache2/error.log
```

### Copying, Moving, Renaming, Deleting
```bash
# Copy a file
cp index.php index.php.backup

# Copy a directory
cp -r /var/www/oldsite /var/www/newsite

# Move (also renames)
mv oldname.php newname.php
mv /var/www/site1 /var/www/site2

# Delete a file
rm filename.php

# Delete a directory and all its contents
rm -rf /var/www/mysite

# WARNING: rm -rf is DANGEROUS. Double-check the path before running.
# NEVER run rm -rf / (deletes everything on the server!)
```

> ⚠️ **WARNING:** `rm -rf` does NOT have an undo. There is no Recycle Bin. Always double-check before deleting. On production servers, take a backup first.

### Searching Files
```bash
# Find files by name
find /var/www -name "*.php"
find /var/www -name "wp-config.php"

# Find files modified in last 24 hours
find /var/www -mtime -1

# Find files larger than 100MB
find /var -size +100M

# Search inside files (grep)
grep -r "database_error" /var/www/mysite/
grep -n "APP_DEBUG" /var/www/mysite/.env    # -n shows line numbers
grep -i "error" /var/log/apache2/error.log  # -i case-insensitive

# Combine with tail to search live logs
tail -f /var/log/nginx/error.log | grep "502"
```

---

## 2.5 File Editing — nano and vim

### nano (Beginner Friendly)
```bash
# Open or create a file
nano /etc/nginx/sites-available/mysite.conf

# Key shortcuts in nano:
# Ctrl + O  → Save the file
# Enter     → Confirm filename
# Ctrl + X  → Exit
# Ctrl + K  → Cut line
# Ctrl + U  → Paste line
# Ctrl + W  → Search
# Ctrl + G  → Help
```

### vim (More Powerful, Steeper Learning Curve)
```bash
# Open a file
vim /etc/apache2/sites-available/mysite.conf

# vim has two modes:
# NORMAL MODE: Default. For navigation and commands.
# INSERT MODE: For typing text. Press 'i' to enter.

# Key commands:
# i         → Enter INSERT mode
# Esc       → Return to NORMAL mode
# :w        → Save
# :q        → Quit
# :wq       → Save and quit
# :q!       → Force quit without saving
# dd        → Delete current line
# yy        → Copy current line
# p         → Paste
# /word     → Search for "word"
# n         → Next search result
# :set nu   → Show line numbers
```

> **Fresher Tip:** Use `nano` in the beginning. Once you're comfortable on the server, invest time learning `vim` — it will make you significantly faster.

---

## 2.6 User and Permission Management

### Understanding Users and Groups

Linux is a **multi-user system**. Each file has:
- An **owner** (a user)
- A **group** (a set of users)
- **Permissions** for owner, group, and everyone else

```bash
# See current user
whoami

# See all users on the system
cat /etc/passwd

# See all groups
cat /etc/group

# Create a new user
sudo adduser developer

# Add user to a group
sudo usermod -aG www-data developer
sudo usermod -aG sudo developer

# Switch user
su - developer

# Become root
sudo su -
sudo -i
```

### Understanding File Permissions

```bash
ls -l /var/www/html/index.php
# Output: -rw-r--r-- 1 www-data www-data 1234 Jan 01 10:00 index.php
#          │││││││││
#          │││││││└└─ Others permissions (r--)
#          │││││││
#          ││││└└└── Group permissions (r--)
#          │││││
#          ││└└└──── Owner permissions (rw-)
#          ││
#          │└──────── File type (- = file, d = directory, l = symlink)
#          │
#          └────────── File type
```

**Permissions breakdown:**

| Symbol | Meaning | Number |
|--------|---------|--------|
| r | Read | 4 |
| w | Write | 2 |
| x | Execute | 1 |
| - | No permission | 0 |

So:
- `rw-` = 4+2+0 = **6**
- `r--` = 4+0+0 = **4**
- `rwx` = 4+2+1 = **7**
- `---` = 0+0+0 = **0**

**Common permission numbers:**

| Value | Meaning | Who Can Do What |
|-------|---------|-----------------|
| 644 | rw-r--r-- | Owner: read+write. Group: read. Others: read |
| 755 | rwxr-xr-x | Owner: all. Group: read+execute. Others: read+execute |
| 600 | rw------- | Owner: read+write. Nobody else |
| 700 | rwx------ | Owner: all. Nobody else |
| 777 | rwxrwxrwx | Everyone full access — **NEVER USE ON PRODUCTION** |

### chmod — Changing Permissions

```bash
# Set file permissions
chmod 644 index.php
chmod 755 /var/www/mysite
chmod 600 .env              # .env should only be readable by owner

# Recursively set all files in a directory
chmod -R 755 /var/www/mysite
chmod -R 644 /var/www/mysite/*.php

# Use symbolic notation
chmod u+x script.sh         # Add execute for user
chmod go-w config.php       # Remove write from group and others
chmod a+r index.html        # Add read for all
```

### chown — Changing Ownership

```bash
# Change owner
chown ubuntu index.php

# Change owner and group
chown ubuntu:www-data index.php
chown www-data:www-data /var/www/mysite

# Recursively change ownership
chown -R www-data:www-data /var/www/mysite
chown -R ubuntu:www-data /var/www/mysite

# Verify the change
ls -la /var/www/mysite
```

> **Why does this matter?** Apache2 and Nginx run as `www-data` user. If your files are owned by `root` and `www-data` can't read them, you get **403 Forbidden**. Understanding ownership is crucial.

---

## 2.7 sudo — The Power Command

`sudo` = "Super User Do" — Run a command as the root (administrator) user.

```bash
# Run a command as root
sudo apt update

# Edit a system file (requires root)
sudo nano /etc/nginx/nginx.conf

# Restart a service
sudo systemctl restart nginx

# See what sudo access you have
sudo -l

# Become root user temporarily
sudo -i
# or
sudo su -
```

> ⚠️ **WARNING:** With great power comes great responsibility. `sudo` commands can break the entire server. Always double-check commands before pressing Enter.

---

## 2.8 Package Management with APT

APT = Advanced Package Tool. This is how you install software on Ubuntu/Debian.

```bash
# Update the package list (not the packages themselves)
sudo apt update

# Upgrade all installed packages
sudo apt upgrade

# Install a package
sudo apt install nginx
sudo apt install php8.2
sudo apt install mysql-server
sudo apt install git

# Install multiple packages at once
sudo apt install nginx php8.2 php8.2-mysql php8.2-curl git unzip

# Remove a package
sudo apt remove nginx

# Remove package AND its config files
sudo apt purge nginx

# Remove unused dependencies
sudo apt autoremove

# Search for a package
apt search php8.2

# Show package info
apt show nginx

# Check if package is installed
dpkg -l nginx
```

> **Best Practice:** Always run `sudo apt update` before installing anything. This ensures you get the latest version.

---

## 2.9 Service Management with systemctl

Services (also called daemons) are programs that run in the background. Like Apache2, Nginx, MySQL.

```bash
# Check service status
sudo systemctl status nginx
sudo systemctl status apache2
sudo systemctl status mysql

# Start a service
sudo systemctl start nginx

# Stop a service
sudo systemctl stop nginx

# Restart a service (stop + start)
sudo systemctl restart nginx

# Reload config without full restart (graceful, preferred for web servers)
sudo systemctl reload nginx
sudo systemctl reload apache2

# Enable service to auto-start on boot
sudo systemctl enable nginx

# Disable auto-start on boot
sudo systemctl disable nginx

# List all running services
sudo systemctl list-units --type=service --state=running
```

### Reading systemctl status output:
```bash
sudo systemctl status nginx
# ● nginx.service - A high performance web server
#    Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
#    Active: active (running) since Mon 2026-01-01 10:00:00 UTC
#   Process: 1234 nginx -g daemon off;
#  Main PID: 1234
#    CGroup: /system.slice/nginx.service
#            └─1234 nginx: master process
#
# ← "active (running)" means it's working fine
# ← "failed" means there's an error — check logs!
```

---

## 2.10 Viewing Logs with journalctl

`journalctl` reads logs from **systemd** (the init system).

```bash
# View all system logs
sudo journalctl

# View logs for a specific service
sudo journalctl -u nginx
sudo journalctl -u apache2
sudo journalctl -u mysql

# View last 50 lines
sudo journalctl -u nginx -n 50

# Follow logs in real-time
sudo journalctl -u nginx -f

# View logs from today
sudo journalctl -u nginx --since today

# View logs from last hour
sudo journalctl -u nginx --since "1 hour ago"

# View logs between two times
sudo journalctl -u nginx --since "2026-01-01 10:00" --until "2026-01-01 11:00"
```

---

## 2.11 Process Management

```bash
# List all running processes
ps aux

# Search for a specific process
ps aux | grep nginx
ps aux | grep php

# Top — real-time process viewer
top
# Press 'q' to quit
# Press 'k' to kill a process (enter PID)

# htop — better visual top (install it)
sudo apt install htop
htop

# Kill a process by PID
kill 1234
kill -9 1234    # Force kill (SIGKILL) — use when regular kill doesn't work

# Kill by name
pkill nginx
killall php

# Find PID of a process
pgrep nginx
pidof nginx
```

---

## 2.12 Disk and Memory Usage

```bash
# Check disk usage
df -h
# Output:
# Filesystem      Size  Used Avail Use% Mounted on
# /dev/sda1        50G   20G   28G  42% /

# Check directory size
du -sh /var/www
du -sh /var/log
du -sh /var/www/*   # Size of each site

# Check memory usage
free -h
# Output:
#               total        used        free
# Mem:           7.8G        4.2G        3.6G
# Swap:          2.0G        0.1G        1.9G

# Check memory with vmstat
vmstat -s
```

---

## 2.13 Networking Commands

```bash
# Check IP address
ip addr
ip addr show eth0

# Check listening ports
sudo ss -tlnp
sudo netstat -tlnp   # older, may need: sudo apt install net-tools

# Check if a port is in use
sudo ss -tlnp | grep :80
sudo ss -tlnp | grep :3306

# Check if you can reach a host
ping google.com
ping 8.8.8.8

# Check DNS resolution
nslookup example.com
dig example.com
dig example.com A          # Check A record
dig example.com MX         # Check mail records

# Trace the route to a host
traceroute google.com
mtr google.com   # Better version

# Check HTTP response
curl -I https://example.com
curl -v https://example.com   # Verbose (shows full request/response)
wget https://example.com/file.zip
```

---

## 2.14 Archive and Compression

```bash
# Create a tar archive
tar -czvf backup.tar.gz /var/www/mysite

# Extract a tar archive
tar -xzvf backup.tar.gz
tar -xzvf backup.tar.gz -C /var/www/   # Extract to specific directory

# Options:
# c = create
# x = extract
# z = gzip compression
# v = verbose (show files)
# f = file name follows

# Zip a file
zip -r mysite.zip /var/www/mysite

# Unzip
unzip mysite.zip
unzip mysite.zip -d /var/www/

# Check contents of zip without extracting
unzip -l mysite.zip
```

---

## 2.15 Cron Jobs — Scheduled Tasks

Cron jobs are **automated tasks that run at scheduled intervals**. Examples:
- Run database backup every night at 2 AM
- Run `php artisan queue:work` every minute
- Clear cache every hour
- Renew SSL certificates every month

```bash
# Edit current user's cron jobs
crontab -e

# Edit root's cron jobs
sudo crontab -e

# View current cron jobs
crontab -l

# Cron syntax:
# ┌───────────── minute (0-59)
# │ ┌───────────── hour (0-23)
# │ │ ┌───────────── day of month (1-31)
# │ │ │ ┌───────────── month (1-12)
# │ │ │ │ ┌───────────── day of week (0-7, Sun=0 or 7)
# │ │ │ │ │
# * * * * * command to run

# Examples:
# Run every minute
* * * * * /usr/bin/php /var/www/myapp/artisan schedule:run

# Run every day at 2 AM
0 2 * * * /usr/bin/mysqldump mydb > /backup/mydb.sql

# Run every Sunday at midnight
0 0 * * 0 /usr/bin/certbot renew

# Run every hour
0 * * * * /usr/bin/php /var/www/mysite/cron.php

# Run at 6 AM and 6 PM every day
0 6,18 * * * /usr/bin/backup.sh

# View cron logs
grep CRON /var/log/syslog
```

---

## 2.16 Symbolic Links

A **symbolic link (symlink)** is a shortcut that points to another file or directory. Nginx and Apache2 use symlinks to enable/disable sites.

```bash
# Create a symlink
ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/mysite.conf
# This means: sites-enabled/mysite.conf points to sites-available/mysite.conf

# Verify symlink
ls -la /etc/nginx/sites-enabled/
# Output: lrwxrwxrwx 1 root root 43 ... mysite.conf -> /etc/nginx/sites-available/mysite.conf

# Remove a symlink (do NOT use rm -rf on a symlink to a directory)
unlink /etc/nginx/sites-enabled/mysite.conf
# or
rm /etc/nginx/sites-enabled/mysite.conf
```

---

## 2.17 Environment Variables

Environment variables are **key-value pairs** that configure how programs run.

```bash
# View all environment variables
env
printenv

# View a specific variable
echo $PATH
echo $HOME
echo $USER

# Set a temporary variable (current session only)
export MY_VAR="hello"
echo $MY_VAR

# Set permanent variables (add to ~/.bashrc or ~/.profile)
echo 'export NODE_ENV=production' >> ~/.bashrc
source ~/.bashrc   # Apply changes immediately

# .env files in applications
cat /var/www/myapp/.env
# APP_ENV=production
# DB_HOST=localhost
# DB_NAME=mydb
# DB_USER=dbuser
# DB_PASS=secretpassword
```

> ⚠️ **Security:** NEVER commit `.env` files to Git. Add `.env` to `.gitignore`. Database passwords and API keys in plain text are a serious security risk.

---

## 2.18 Common Dangerous Commands — Know Before You Type

> ⚠️ **These commands can cause irreversible damage. Never run them without understanding them.**

```bash
# DANGER: Deletes EVERYTHING on the server
rm -rf /
rm -rf /*

# DANGER: Overwrites your disk with zeros
dd if=/dev/zero of=/dev/sda

# DANGER: Fork bomb — crashes the system
:(){ :|:& };:

# DANGER: Deletes all files in current directory
rm -rf ./*   # Be careful about WHERE you are when running rm -rf

# ALWAYS CHECK: Before any rm -rf, run ls first to see what's there
ls /var/www/mysite
# Then delete
rm -rf /var/www/mysite
```

**Safe practices:**
1. Before `rm -rf`, run `ls` on that path first
2. Always take a backup before deleting
3. Use `echo` to test commands before running them
4. Double-check your current directory with `pwd` before `rm -rf ./*`

---

---

# SECTION 3 — APACHE2 COMPLETE GUIDE

---

## 3.1 What Is Apache2?

**Apache HTTP Server** (commonly called Apache2 on Ubuntu) is the **world's most popular web server software**. It has been running websites since 1995. 

Apache's job:
- Listens for HTTP/HTTPS requests on ports 80 and 443
- Receives requests from browsers
- Finds the right files or passes the request to PHP/Python
- Sends the response back

```bash
# Install Apache2
sudo apt update
sudo apt install apache2

# Check version
apache2 -v

# Check if it's running
sudo systemctl status apache2

# Test configuration
sudo apache2ctl configtest
```

---

## 3.2 Apache2 Directory Structure

```
/etc/apache2/
├── apache2.conf          ← Main configuration file
├── envvars               ← Environment variables (APACHE_USER, etc.)
├── magic                 ← MIME type detection
├── ports.conf            ← Which ports Apache listens on
├── sites-available/      ← All virtual host config files live here
│   ├── 000-default.conf  ← Default site (when no VH matches)
│   └── mysite.conf       ← Your site config
├── sites-enabled/        ← SYMLINKS to active sites from sites-available
│   └── 000-default.conf  ← (symlink to sites-available)
├── conf-available/       ← Additional config snippets
├── conf-enabled/         ← Enabled config snippets
├── mods-available/       ← All available modules
│   ├── rewrite.load
│   ├── ssl.load
│   └── ...
└── mods-enabled/         ← Enabled modules (symlinks)
    ├── rewrite.load
    └── ...

/var/www/
└── html/                 ← Default web root
    └── index.html

/var/log/apache2/
├── access.log            ← All requests (IPs, URLs, status codes)
└── error.log             ← All errors (VERY important for debugging)
```

---

## 3.3 Apache2 Modules

Apache2 is **modular** — features are added via modules.

```bash
# Enable a module
sudo a2enmod rewrite       # URL rewriting (.htaccess RewriteRules)
sudo a2enmod ssl           # HTTPS support
sudo a2enmod headers       # HTTP headers manipulation
sudo a2enmod expires       # Browser caching
sudo a2enmod deflate       # Gzip compression
sudo a2enmod proxy         # Reverse proxy
sudo a2enmod proxy_http    # HTTP reverse proxy

# Disable a module
sudo a2dismod autoindex    # Disable directory listing (security)

# List all enabled modules
apache2ctl -M

# After enabling modules, always reload or restart
sudo systemctl reload apache2
```

**Modules you'll use most:**

| Module | Purpose |
|--------|---------|
| mod_rewrite | URL rewriting (required for Laravel, WordPress pretty URLs) |
| mod_ssl | HTTPS support |
| mod_headers | Set security headers |
| mod_expires | Browser caching |
| mod_deflate | Gzip compression |
| mod_proxy | Reverse proxy to Node.js, etc. |
| mod_php | PHP processing (older approach) |
| mod_security | Web Application Firewall |

---

## 3.4 Virtual Hosts — Hosting Multiple Sites

A **Virtual Host (VHost)** lets one Apache server host **multiple different websites** on the same IP address. Apache decides which site to show based on the domain in the request.

```
Browser requests: http://site1.com → Apache checks VirtualHost rules → Serves from /var/www/site1
Browser requests: http://site2.com → Apache checks VirtualHost rules → Serves from /var/www/site2
```

### Creating a Virtual Host for a Plain PHP Site

```bash
# 1. Create directory
sudo mkdir -p /var/www/mysite/public
sudo chown -R www-data:www-data /var/www/mysite

# 2. Create a test file
echo "<h1>My Site Works!</h1>" | sudo tee /var/www/mysite/public/index.php

# 3. Create virtual host config
sudo nano /etc/apache2/sites-available/mysite.conf
```

**Virtual host config file:**
```apache
<VirtualHost *:80>
    # The domain this VHost responds to
    ServerName mysite.com
    ServerAlias www.mysite.com

    # Where the files are (DocumentRoot)
    DocumentRoot /var/www/mysite/public

    # Logging
    ErrorLog ${APACHE_LOG_DIR}/mysite-error.log
    CustomLog ${APACHE_LOG_DIR}/mysite-access.log combined

    # Directory permissions
    <Directory /var/www/mysite/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

```bash
# 4. Enable the site
sudo a2ensite mysite.conf

# 5. Test configuration
sudo apache2ctl configtest
# Should output: Syntax OK

# 6. Reload Apache
sudo systemctl reload apache2
```

---

## 3.5 Apache Virtual Host for Laravel

Laravel needs the document root to point to the `public/` folder (not the project root).

```bash
# Directory structure for Laravel
/var/www/laravel-app/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/         ← DocumentRoot points HERE
│   └── index.php   ← Entry point
├── resources/
├── routes/
├── storage/
├── vendor/
└── .env            ← NEVER expose this
```

```apache
<VirtualHost *:80>
    ServerName mylaravelapp.com
    ServerAlias www.mylaravelapp.com
    DocumentRoot /var/www/laravel-app/public

    <Directory /var/www/laravel-app/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/laravel-app-error.log
    CustomLog ${APACHE_LOG_DIR}/laravel-app-access.log combined
</VirtualHost>
```

```bash
# Laravel permissions setup
sudo chown -R www-data:www-data /var/www/laravel-app
sudo chmod -R 755 /var/www/laravel-app
sudo chmod -R 775 /var/www/laravel-app/storage
sudo chmod -R 775 /var/www/laravel-app/bootstrap/cache
```

---

## 3.6 Apache Virtual Host for WordPress

```apache
<VirtualHost *:80>
    ServerName mywordpresssite.com
    ServerAlias www.mywordpresssite.com
    DocumentRoot /var/www/mywordpresssite

    <Directory /var/www/mywordpresssite>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/wordpress-error.log
    CustomLog ${APACHE_LOG_DIR}/wordpress-access.log combined
</VirtualHost>
```

```bash
# Enable mod_rewrite for WordPress pretty permalinks
sudo a2enmod rewrite
sudo systemctl reload apache2
```

---

## 3.7 Understanding .htaccess

The `.htaccess` file is a **per-directory configuration file** that overrides the main Apache config for that directory.

Why it exists: You can't edit `/etc/apache2/apache2.conf` for every client. `.htaccess` lets each project have its own rules.

**IMPORTANT:** For `.htaccess` to work, `AllowOverride All` must be set in the VirtualHost config (as shown above).

### .htaccess for WordPress
```apache
# WordPress standard .htaccess
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
```

### .htaccess for Laravel
```apache
<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>
```

### .htaccess for Security
```apache
# Deny access to sensitive files
<Files ".env">
    Order allow,deny
    Deny from all
</Files>

<Files "*.log">
    Order allow,deny
    Deny from all
</Files>

# Disable directory listing
Options -Indexes

# Prevent script execution in uploads folder
<Directory "/var/www/mysite/uploads">
    php_flag engine off
    AddType text/plain .php .php3 .php4 .php5 .php7 .phtml
</Directory>

# Security headers
<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "no-referrer-when-downgrade"
</IfModule>

# Force HTTPS redirect
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
```

---

## 3.8 Apache with SSL (HTTPS)

```bash
# Install Certbot for Let's Encrypt
sudo apt install certbot python3-certbot-apache

# Get SSL certificate
sudo certbot --apache -d mysite.com -d www.mysite.com

# Certbot automatically modifies your VirtualHost and creates a new :443 block

# Test auto-renewal
sudo certbot renew --dry-run
```

**After Certbot, your virtual host will look like this:**
```apache
<VirtualHost *:80>
    ServerName mysite.com
    ServerAlias www.mysite.com
    # Redirect HTTP to HTTPS
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =mysite.com [OR]
    RewriteCond %{SERVER_NAME} =www.mysite.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
    ServerName mysite.com
    ServerAlias www.mysite.com
    DocumentRoot /var/www/mysite/public

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/mysite.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mysite.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    <Directory /var/www/mysite/public>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/mysite-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/mysite-ssl-access.log combined
</VirtualHost>
```

---

## 3.9 Apache Logs — Your Debugging Best Friend

### Access Log
Records every request made to the server.
```bash
tail -f /var/log/apache2/access.log

# Format: IP - User [Date] "Request" StatusCode Bytes "Referer" "UserAgent"
# 203.0.113.1 - - [01/Jan/2026:10:00:00 +0000] "GET /index.php HTTP/1.1" 200 4523 "-" "Chrome/120"
```

### Error Log
Records all errors — this is WHERE you look when something breaks.
```bash
tail -f /var/log/apache2/error.log
tail -n 100 /var/log/apache2/error.log
grep "mysite.com" /var/log/apache2/error.log

# Common error messages and meanings:
# [error] [client x.x.x.x] File does not exist: /var/www/mysite/favicon.ico
# → A file is missing. Can be ignored for favicon, or fix the path.

# [error] Permission denied: /var/www/mysite/storage
# → www-data doesn't have permission. Run: chown -R www-data:www-data storage

# PHP Fatal error: → PHP error in your code
# ModSecurity: → Security rule triggered
```

---

## 3.10 Apache Troubleshooting

### 403 Forbidden
```
Symptom: Browser shows "403 Forbidden"
Causes:
1. Wrong file ownership (www-data can't read files)
2. Wrong permissions
3. AllowOverride not set
4. mod_autoindex disabled but no index file exists

Debugging:
sudo tail -f /var/log/apache2/error.log
ls -la /var/www/mysite/
# Check: is the file owned by root? Is permission 600 or 000?

Fixes:
sudo chown -R www-data:www-data /var/www/mysite
sudo chmod -R 755 /var/www/mysite
sudo chmod -R 644 /var/www/mysite/*.php
```

### 500 Internal Server Error
```
Symptom: Browser shows "500 Internal Server Error"
Causes:
1. PHP syntax error in code
2. .htaccess syntax error
3. Memory limit exceeded
4. Missing PHP extension
5. Wrong PHP version

Debugging:
sudo tail -f /var/log/apache2/error.log
# Look for "PHP Parse error" or "PHP Fatal error"

# Test .htaccess syntax
sudo apache2ctl configtest

Fixes:
# Fix PHP syntax error in your code
# Comment out lines in .htaccess one by one to find the issue
# Increase PHP memory: php -r "echo ini_get('memory_limit');"
```

### mod_rewrite Not Working
```
Symptom: Pretty URLs return 404
Causes:
1. mod_rewrite not enabled
2. AllowOverride None (not All)
3. .htaccess file missing

Fix:
sudo a2enmod rewrite
# Edit VirtualHost: AllowOverride All (not None)
sudo systemctl reload apache2
```

### Virtual Host Conflict
```
Symptom: Wrong site shows up for a domain
Causes:
1. Multiple VHosts with same ServerName
2. Default VHost catching requests

Fix:
# List enabled sites
ls -la /etc/nginx/sites-enabled/
sudo apache2ctl -S   # Shows VirtualHost routing
```

---

---

# SECTION 4 — NGINX COMPLETE GUIDE

---

## 4.1 What Is Nginx?

**Nginx** (pronounced "Engine-X") is a **high-performance web server** that also acts as a **reverse proxy**, **load balancer**, and **HTTP cache**. It was created specifically to handle a massive number of concurrent connections efficiently.

**Apache vs Nginx — Key Differences:**

| Feature | Apache2 | Nginx |
|---------|---------|-------|
| Architecture | Process/Thread-based | Event-driven (async) |
| Concurrency | Struggles with thousands of connections | Handles 10,000+ connections easily |
| .htaccess | Supported | NOT supported (configured in server blocks) |
| Dynamic content | Native PHP module (mod_php) | Requires PHP-FPM (FastCGI) |
| Static files | Good | Excellent |
| Configuration | Per-directory (.htaccess) | Central config only |
| Learning curve | Easier for beginners | Slightly steeper |
| Memory usage | Higher | Lower |
| Best for | PHP apps, WordPress, small-medium sites | High traffic, Node.js, reverse proxy, modern apps |

---

## 4.2 Nginx Architecture — Why It's Fast

```
Apache (Old way):
For each request → spawn a new thread/process → process request → destroy thread
Problem: 10,000 requests = 10,000 threads = server crash

Nginx (Modern way):
1 Master Process + N Worker Processes
Each worker handles THOUSANDS of connections using async I/O
No new thread per request = handles massive traffic with minimal resources
```

---

## 4.3 Installing Nginx

```bash
sudo apt update
sudo apt install nginx

# Check version
nginx -v

# Check status
sudo systemctl status nginx

# Start
sudo systemctl start nginx

# Enable on boot
sudo systemctl enable nginx

# Test configuration syntax
sudo nginx -t
```

---

## 4.4 Nginx Directory Structure

```
/etc/nginx/
├── nginx.conf              ← Main configuration file
├── sites-available/        ← All server block configs
│   ├── default             ← Default server block
│   └── mysite.conf         ← Your site's config
├── sites-enabled/          ← Symlinks to active configs
│   └── default             ← (symlink to sites-available)
├── conf.d/                 ← Additional config snippets
├── snippets/               ← Reusable config snippets
│   ├── fastcgi-php.conf    ← PHP-FPM settings
│   └── snakeoil.conf       ← Self-signed SSL settings
├── mime.types              ← File type to MIME mappings
└── modules-enabled/        ← Nginx modules

/var/log/nginx/
├── access.log
└── error.log
```

---

## 4.5 Understanding nginx.conf

```bash
sudo nano /etc/nginx/nginx.conf
```

```nginx
# Main context
user www-data;                      # Run as www-data
worker_processes auto;              # Number of worker processes (auto = 1 per CPU core)
pid /run/nginx.pid;

# Events block
events {
    worker_connections 1024;        # Connections per worker process
    # multi_accept on;              # Accept multiple connections at once
}

# HTTP block
http {
    # Basic settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;              # Hide Nginx version number (security)

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_types text/plain text/css application/json application/javascript text/xml;

    # Include all site configs
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
```

---

## 4.6 Nginx Server Blocks (Virtual Hosts)

In Nginx, virtual hosts are called **server blocks**.

### Basic Server Block for Static Site / PHP

```nginx
server {
    listen 80;
    listen [::]:80;

    server_name mysite.com www.mysite.com;

    root /var/www/mysite/public;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    # PHP processing
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }

    # Deny access to .htaccess (doesn't do anything in Nginx but good practice)
    location ~ /\.ht {
        deny all;
    }

    # Deny access to .env files
    location ~ /\.env {
        deny all;
    }

    access_log /var/log/nginx/mysite-access.log;
    error_log /var/log/nginx/mysite-error.log;
}
```

```bash
# Enable the site
sudo ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/

# Test config
sudo nginx -t

# Reload
sudo systemctl reload nginx
```

---

## 4.7 Nginx Server Block for Laravel

```nginx
server {
    listen 80;
    server_name laravelapp.com www.laravelapp.com;
    root /var/www/laravel-app/public;
    index index.php;

    # Laravel URL rewriting (equivalent of .htaccess)
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP-FPM
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny sensitive files
    location ~ /\.(?!well-known).* {
        deny all;
    }

    error_log /var/log/nginx/laravel-error.log;
    access_log /var/log/nginx/laravel-access.log;
}
```

---

## 4.8 Nginx as Reverse Proxy for Node.js

The most common use of Nginx in modern development: **act as a gateway to a Node.js application**.

Why reverse proxy?
- Node.js runs on port 3000 or 8000 — not port 80/443
- Nginx handles SSL, compression, caching, and routes traffic to Node.js
- Security: Node.js process is not directly exposed to the internet

```
Internet → Port 80/443 → Nginx (reverse proxy) → Port 3000 → Node.js App
```

```nginx
# /etc/nginx/sites-available/nodeapp.conf

server {
    listen 80;
    server_name nodeapp.com www.nodeapp.com;

    location / {
        # Pass all requests to the Node.js app running on port 3000
        proxy_pass http://127.0.0.1:3000;

        # Headers to pass to Node.js
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;

        # Timeout settings
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    access_log /var/log/nginx/nodeapp-access.log;
    error_log /var/log/nginx/nodeapp-error.log;
}
```

---

## 4.9 Nginx Reverse Proxy for Next.js

```nginx
server {
    listen 80;
    server_name mynextapp.com www.mynextapp.com;

    # Next.js default port is 3000
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Serve Next.js static assets directly (faster)
    location /_next/static/ {
        alias /var/www/mynextapp/.next/static/;
        expires 365d;
        add_header Cache-Control "public, immutable";
    }

    error_log /var/log/nginx/nextapp-error.log;
    access_log /var/log/nginx/nextapp-access.log;
}
```

---

## 4.10 Nginx for React App (Static Build)

When you build a React app (`npm run build`), it produces static files. Nginx can serve these directly.

```nginx
server {
    listen 80;
    server_name myreactapp.com www.myreactapp.com;

    root /var/www/myreactapp/build;
    index index.html;

    # This is critical for React Router to work
    # Without this, refreshing on /about returns 404
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    access_log /var/log/nginx/reactapp-access.log;
    error_log /var/log/nginx/reactapp-error.log;
}
```

---

## 4.11 Nginx with SSL

```bash
# Install Certbot for Nginx
sudo apt install certbot python3-certbot-nginx

# Get SSL certificate (automatically configures Nginx)
sudo certbot --nginx -d mysite.com -d www.mysite.com

# Test auto-renewal
sudo certbot renew --dry-run
```

**Manual SSL configuration (after Certbot):**
```nginx
server {
    listen 80;
    server_name mysite.com www.mysite.com;
    return 301 https://$server_name$request_uri;  # Redirect HTTP to HTTPS
}

server {
    listen 443 ssl http2;
    server_name mysite.com www.mysite.com;

    # SSL certificates from Let's Encrypt
    ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem;

    # Strong SSL settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # HSTS (tell browsers to always use HTTPS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Other security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    root /var/www/mysite/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}
```

---

## 4.12 Nginx Gzip Compression

Add to `nginx.conf` inside the `http {}` block:

```nginx
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/x-javascript
    application/xml
    application/json
    application/rss+xml
    image/svg+xml;
gzip_comp_level 6;
```

---

## 4.13 Nginx Security Headers

```nginx
# Add to your server block
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
```

---

## 4.14 Nginx WebSocket Support

For Socket.io or WebSocket applications:

```nginx
server {
    listen 80;
    server_name socketapp.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;         # Required for WebSocket
        proxy_set_header Connection "upgrade";           # Required for WebSocket
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 86400;                        # Keep connection alive
    }
}
```

---

## 4.15 Nginx Load Balancing

For distributing traffic across multiple application instances:

```nginx
# Define the upstream group
upstream myapp {
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
    server 127.0.0.1:3003;
    # least_conn;    # Route to server with fewest connections
    # ip_hash;       # Same client always goes to same server (for sessions)
}

server {
    listen 80;
    server_name myapp.com;

    location / {
        proxy_pass http://myapp;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
```

---

## 4.16 Nginx Troubleshooting

### 502 Bad Gateway
```
Symptom: Browser shows "502 Bad Gateway"
Meaning: Nginx received a bad response from the upstream (PHP-FPM, Node.js, etc.)
Most common cause: The backend application is not running

Debugging:
sudo tail -f /var/log/nginx/error.log
# Look for: "connect() failed (111: Connection refused) while connecting to upstream"

Check if PHP-FPM is running:
sudo systemctl status php8.2-fpm

Check if Node.js app is running:
pm2 status
ps aux | grep node

Check if the port is listening:
sudo ss -tlnp | grep 3000

Fix:
sudo systemctl restart php8.2-fpm
pm2 restart myapp
# Restart whatever application is behind Nginx
```

### 504 Gateway Timeout
```
Symptom: "504 Gateway Timeout"
Meaning: The upstream took too long to respond
Common causes: Slow database query, heavy PHP script, slow API call

Fix in nginx config:
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
fastcgi_read_timeout 300s;
```

### Permission Denied
```
Symptom: 403 Forbidden or "permission denied" in error log
Causes: Nginx (www-data) can't read the files

Fix:
sudo chown -R www-data:www-data /var/www/mysite
sudo chmod -R 755 /var/www/mysite
```

### Infinite Redirect Loop
```
Symptom: Browser shows "ERR_TOO_MANY_REDIRECTS"
Common cause: Both HTTP→HTTPS redirect in Nginx AND in the application (.htaccess / Laravel .env)

Fix:
# In Laravel, when behind a proxy, add to AppServiceProvider:
$request->setTrustedProxies($request->getClientIps(), Request::HEADER_X_FORWARDED_ALL);

# Or in .env:
APP_URL=https://mysite.com
# Make sure the redirect rules aren't duplicated
```

### Static Assets Not Loading
```
Symptom: CSS/JS/images return 404 after routing to index.html
Cause: Missing location block for static files, or wrong root path

Fix: Make sure your root points to the correct build/public folder
Check: curl -I https://mysite.com/static/main.js
```

---

> **End of Part 1 — Sections 1 to 4**  
> Continue to Part 2 for Sections 5 through 8.
