# 🚨 Apache/LAMP Security Deployment Guide

## Quick Start - Stop Attack NOW

### 1. Block Attacker IP (1 minute)

```bash
# Option A: Using .htaccess (fastest)
sudo nano /var/www/html/sellzaki.com/production/public/.htaccess

# Add at the top:
<RequireAll>
    Require all granted
    Require not ip 41.44.117.225
</RequireAll>

# Save and exit (Ctrl+X, Y, Enter)
```

```bash
# Option B: Using Apache conf file (recommended)
sudo nano /etc/apache2/conf-available/blocked-ips.conf

# Add:
<RequireAll>
    Require all granted
    Require not ip 41.44.117.225
</RequireAll>

# Enable and reload
sudo a2enconf blocked-ips
sudo systemctl reload apache2
```

```bash
# Option C: Using firewall (most secure)
sudo ufw deny from 41.44.117.225
```

### 2. Restart PHP-FPM (1 minute)

```bash
# Find your PHP version
php -v

# Restart PHP-FPM
sudo systemctl restart php8.2-fpm

# Verify
sudo systemctl status php8.2-fpm
```

### 3. Deploy Laravel Security (5 minutes)

```bash
cd /var/www/html/sellzaki.com/production
git pull origin main
php artisan cache:clear
php artisan route:clear
sudo systemctl reload apache2
```

**✅ Attack stopped! Continue below for full protection.**

---

## Deployed configuration (reference)

Current production setup:

| Layer | Config | Values |
|-------|--------|--------|
| **mod_evasive** | `/etc/apache2/mods-enabled/evasive.conf` | 5 req/page/sec, 50 req/site/sec, 60s block; log dir: `/var/log/apache2/mod_evasive` |
| **VHost** | `/etc/apache2/sites-available/sellzaki.com.conf` | IP `41.44.117.225` blocked on `:80` and `:443` via `<Location "/">`; security headers set |
| **Per-endpoint limits** | Laravel `AggressiveRateLimiter` | Search: 10 req/min; login and other endpoints as in `routes/api.php` |

mod_evasive does not support per-`Location` overrides; per-endpoint limiting is done in Laravel.

---

## Full Apache Rate Limiting Setup

### Install mod_evasive (Recommended)

```bash
# Install
sudo apt-get update
sudo apt-get install libapache2-mod-evasive

# Enable module
sudo a2enmod evasive

# Create log directory
sudo mkdir -p /var/log/apache2/mod_evasive
sudo chown www-data:www-data /var/log/apache2/mod_evasive

# Configure
sudo nano /etc/apache2/mods-enabled/evasive.conf
```

Add this configuration:

```apache
<IfModule mod_evasive20.c>
    DOSHashTableSize 3097
    DOSPageCount 5
    DOSSiteCount 50
    DOSPageInterval 1
    DOSSiteInterval 1
    DOSBlockingPeriod 60
    DOSLogDir "/var/log/apache2/mod_evasive"
    DOSEmailNotify your-email@example.com
    DOSWhitelist 127.0.0.1
</IfModule>
```

```bash
# Test and reload
sudo apache2ctl configtest
sudo systemctl reload apache2
```

---

## Update VirtualHost Configuration

```bash
# Edit your site config
sudo nano /etc/apache2/sites-available/sellzaki.conf
```

Add these sections:

**Note:** mod_evasive does **not** support per-`<Location>` or `<LocationMatch>` overrides. Its limits are global per vhost. Per-endpoint rate limiting (e.g. stricter limits for `/api/products/search`, `/api/auth/login`) is handled by Laravel's **AggressiveRateLimiter** middleware.

```apache
<VirtualHost *:80>
    ServerName tyson.sellzaki.com
    DocumentRoot /var/www/html/sellzaki.com/production/public
    
    # Block specific IPs
    <RequireAll>
        Require all granted
        Require not ip 41.44.117.225
    </RequireAll>
    
    # Rate limiting with mod_evasive (global for this vhost)
    <IfModule mod_evasive20.c>
        DOSPageCount 5
        DOSSiteCount 50
        DOSBlockingPeriod 60
    </IfModule>
    
    # PHP-FPM configuration
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
    
    # Security headers
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
    
    # Logging
    ErrorLog ${APACHE_LOG_DIR}/sellzaki-error.log
    CustomLog ${APACHE_LOG_DIR}/sellzaki-access.log combined
    
    <Directory /var/www/html/sellzaki.com/production/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

```bash
# Enable required modules
sudo a2enmod headers
sudo a2enmod proxy_fcgi
sudo a2enmod rewrite

# Test and reload
sudo apache2ctl configtest
sudo systemctl reload apache2
```

---

## Alternative: mod_qos (Quality of Service)

```bash
# Install
sudo apt-get install libapache2-mod-qos

# Enable
sudo a2enmod qos

# Configure
sudo nano /etc/apache2/mods-enabled/qos.conf
```

Add:

```apache
<IfModule mod_qos.c>
    # Maximum connections per IP
    QS_SrvMaxConnPerIP 10
    
    # Request rate per second
    QS_SrvRequestRate 50
    
    # Minimum data rate (bytes per second)
    QS_SrvMinDataRate 150 1200
    
    # Maximum connections
    QS_SrvMaxConnClose 180
</IfModule>
```

```bash
sudo systemctl reload apache2
```

---

## Monitoring

### Check mod_evasive logs

```bash
# Watch for blocked IPs
sudo tail -f /var/log/apache2/mod_evasive/*

# Check Apache access log
sudo tail -f /var/log/apache2/sellzaki-access.log

# Check Apache error log
sudo tail -f /var/log/apache2/sellzaki-error.log
```

### Find abusive IPs

```bash
# Top IPs
sudo tail -10000 /var/log/apache2/sellzaki-access.log | \
  awk '{print $1}' | sort | uniq -c | sort -rn | head -20

# What they're requesting
sudo grep "41.44.117.225" /var/log/apache2/sellzaki-access.log | \
  awk '{print $7}' | sort | uniq -c | sort -rn
```

### Check PHP-FPM status

```bash
# Worker count
ps aux | grep php-fpm | wc -l

# Service status
sudo systemctl status php8.2-fpm

# Check pool configuration
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
# Look for: pm.max_children = 5
```

---

## Testing

### Test IP block

```bash
# Should return 403 Forbidden
curl -I https://tyson.sellzaki.com --header "X-Forwarded-For: 41.44.117.225"
```

### Test rate limiting

```bash
# Send 15 requests rapidly
for i in {1..15}; do 
  curl -s -o /dev/null -w "%{http_code}\n" \
    "https://tyson.sellzaki.com/api/products/search?q=test" \
    -H "Authorization: Bearer $TOKEN"
  sleep 0.3
done

# Should see 429 or 503 responses after threshold
```

### Test Laravel validation

```bash
# Should fail (1 char)
curl "https://tyson.sellzaki.com/api/products/search?q=t" \
  -H "Authorization: Bearer $TOKEN"

# Should work (2+ chars)
curl "https://tyson.sellzaki.com/api/products/search?q=te" \
  -H "Authorization: Bearer $TOKEN"
```

---

## Increase PHP-FPM Workers (If Needed)

```bash
# Edit pool configuration
sudo nano /etc/php/8.2/fpm/pool.d/www.conf

# Find and update:
pm = dynamic
pm.max_children = 10        # was 5
pm.start_servers = 3        # was 2
pm.min_spare_servers = 2
pm.max_spare_servers = 5    # was 3
pm.max_requests = 500

# Restart
sudo systemctl restart php8.2-fpm
```

---

## Create Blocked IPs Management

### Create blocked IPs file

```bash
sudo nano /etc/apache2/conf-available/blocked-ips.conf
```

Add:

```apache
# Blocked IPs for SellZaki
<RequireAll>
    Require all granted
    Require not ip 41.44.117.225
    # Add more IPs below as needed
    # Require not ip 192.168.1.100
</RequireAll>
```

### Enable and manage

```bash
# Enable
sudo a2enconf blocked-ips

# Reload Apache
sudo systemctl reload apache2

# To add more IPs, edit the file and reload
sudo nano /etc/apache2/conf-available/blocked-ips.conf
sudo systemctl reload apache2
```

---

## Performance Tuning

### Apache MPM Configuration

```bash
# Check current MPM
apache2ctl -V | grep MPM

# For prefork (if using mod_php)
sudo nano /etc/apache2/mods-available/mpm_prefork.conf
```

```apache
<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>
```

```bash
# For event MPM (if using PHP-FPM - recommended)
sudo nano /etc/apache2/mods-available/mpm_event.conf
```

```apache
<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>
```

```bash
# Switch to event MPM (better performance with PHP-FPM)
sudo a2dismod mpm_prefork
sudo a2dismod php8.2  # if using mod_php
sudo a2enmod mpm_event
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.2-fpm
sudo systemctl restart apache2
```

---

## Verification Checklist

- [ ] Attacker IP blocked (41.44.117.225)
- [ ] Apache reloaded successfully
- [ ] mod_evasive installed and configured
- [ ] PHP-FPM restarted
- [ ] Laravel security deployed
- [ ] Site accessible
- [ ] Search requires 2+ characters
- [ ] Rate limiting active
- [ ] Logs being written
- [ ] No errors in Apache logs

---

## Rollback

### Remove IP block

```bash
# From .htaccess
sudo nano /var/www/html/sellzaki.com/production/public/.htaccess
# Remove the Require not ip line

# From conf file
sudo a2disconf blocked-ips
sudo systemctl reload apache2

# From firewall
sudo ufw delete deny from 41.44.117.225
```

### Disable mod_evasive

```bash
sudo a2dismod evasive
sudo systemctl reload apache2
```

### Revert Laravel code

```bash
cd /var/www/html/sellzaki.com/production
git log --oneline -10
git checkout <previous-commit>
php artisan cache:clear
php artisan route:clear
```

---

## Common Apache Commands

```bash
# Test configuration
sudo apache2ctl configtest

# Reload (no downtime)
sudo systemctl reload apache2

# Restart (brief downtime)
sudo systemctl restart apache2

# Check status
sudo systemctl status apache2

# View enabled modules
apache2ctl -M

# View enabled sites
apache2ctl -S

# Check error log
sudo tail -f /var/log/apache2/error.log
```

---

## Next Steps

1. **Monitor for 48 hours** - Watch logs for patterns
2. **Adjust thresholds** - Fine-tune based on legitimate traffic
3. **Consider Cloudflare** - Additional DDoS protection layer
4. **Set up fail2ban** - Auto-block based on log patterns
5. **Enable ModSecurity** - Web application firewall

---

## Support

**Apache Logs**: `/var/log/apache2/`  
**PHP-FPM Logs**: `/var/log/php8.2-fpm.log`  
**Laravel Logs**: `storage/logs/laravel.log`  
**mod_evasive Logs**: `/var/log/apache2/mod_evasive/`

**Quick help**: See [SECURITY-QUICK-REFERENCE.md](SECURITY-QUICK-REFERENCE.md)
