# Fogbreak Production Deployment Setup

This directory contains the complete deployment pipeline for Fogbreak: GitHub Actions CI/CD, webhook-based auto-deploy, Nginx configuration, and environment variable templates.

## Files Overview

| File | Purpose |
|------|---------|
| `.github/workflows/deploy.yml` | GitHub Actions workflow: auto-deploys on push to main |
| `deploy/webhook.php` | Webhook receiver: validates GitHub signatures, pulls code, runs migrations |
| `deploy/nginx.conf` | Production Nginx config: SSL/TLS, PHP-FPM, rate limiting, security headers |
| `deploy/.env.example` | Environment variable template: database, email, APIs, AI, social, etc. |

## Deployment Options

### Option A: GitHub Actions (Recommended)

Automatic deployment on every push to `main` branch.

**Setup:**

1. Add secrets to GitHub repo settings:
   ```
   Settings > Secrets and variables > Actions > New repository secret
   ```

   Required secrets:
   - `SSH_HOST` — VPS hostname (e.g., `vps.fogbreak.io`)
   - `SSH_USER` — SSH user (e.g., `deploy`)
   - `SSH_KEY` — Private SSH key (multiline)

   Optional:
   - `SLACK_WEBHOOK_URL` — For deployment notifications

2. Ensure `.github/workflows/deploy.yml` exists in repo (commit to main)

3. Push to main:
   ```bash
   git add .
   git commit -m "Add GitHub Actions deployment pipeline"
   git push origin main
   ```

4. Check Actions tab in GitHub for execution logs

**Workflow Steps:**
1. Checkout code
2. SSH into VPS
3. `git pull origin main`
4. Clear PHP OPcache
5. Run pending migrations
6. Verify deployment
7. Send Slack notification (optional)

**Advantages:**
- No manual commands required
- Automatic on every push
- Audit trail in GitHub
- Easy rollback (push previous commit)

---

### Option B: Webhook-Based Deploy (Alternative)

Lightweight webhook receiver for organizations using CI systems other than GitHub.

**Setup:**

1. Copy `.env.example` to `/var/www/fogbreak.io/.env`:
   ```bash
   cp deploy/.env.example /var/www/fogbreak.io/.env
   chmod 600 /var/www/fogbreak.io/.env
   ```

2. Edit `.env` and set `GITHUB_WEBHOOK_SECRET` to a strong random secret:
   ```bash
   openssl rand -base64 32
   ```

3. In GitHub repo settings:
   ```
   Settings > Webhooks > Add webhook

   - Payload URL: https://fogbreak.io/deploy/webhook.php
   - Content type: application/json
   - Events: Pushes
   - Secret: (paste the secret from .env)
   - Active: ✓
   ```

4. Test webhook:
   ```bash
   # GitHub will show a delivery in the webhook settings
   # Check /var/log/fogbreak/deploy.log for events
   tail -f /var/log/fogbreak/deploy.log
   ```

**Advantages:**
- Simpler setup than GitHub Actions
- Works with any CI system
- Minimal dependencies on VPS

---

## Nginx Configuration

### Install Nginx

```bash
sudo apt update
sudo apt install nginx
sudo systemctl enable nginx
```

### Deploy Config

1. Copy `deploy/nginx.conf` to Nginx sites:
   ```bash
   sudo cp deploy/nginx.conf /etc/nginx/sites-available/fogbreak.io
   ```

2. Enable site:
   ```bash
   sudo ln -s /etc/nginx/sites-available/fogbreak.io /etc/nginx/sites-enabled/fogbreak.io
   ```

3. Remove default site (optional):
   ```bash
   sudo rm /etc/nginx/sites-enabled/default
   ```

4. Test configuration:
   ```bash
   sudo nginx -t
   ```

5. Reload Nginx:
   ```bash
   sudo systemctl reload nginx
   ```

### SSL/TLS (Let's Encrypt)

Nginx config expects Certbot-managed certificates:

```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot certonly --webroot -w /var/www/letsencrypt -d fogbreak.io -d www.fogbreak.io
sudo systemctl reload nginx
```

Auto-renewal (Certbot handles this automatically):
```bash
sudo systemctl enable certbot.timer
```

### Logs

Nginx logs are written to:
- **Access:** `/var/log/fogbreak/access.log`
- **Errors:** `/var/log/fogbreak/error.log`
- **Webhooks:** `/var/log/fogbreak/webhook.log`
- **Cron:** `/var/log/fogbreak/cron.log`

Ensure log directory exists:
```bash
sudo mkdir -p /var/log/fogbreak
sudo chown www-data:www-data /var/log/fogbreak
```

---

## Environment Variables

### Setup

1. Copy template:
   ```bash
   cp deploy/.env.example /var/www/fogbreak.io/.env
   ```

2. Edit with production values:
   ```bash
   nano /var/www/fogbreak.io/.env
   ```

3. Protect from web access:
   ```bash
   chmod 600 /var/www/fogbreak.io/.env
   ```

### Loading in PHP

**Method 1: Manually in config.php**
```php
// In api/config.php or where you define DB credentials
$env = [];
if (file_exists(__DIR__ . '/../.env')) {
    $lines = file(__DIR__ . '/../.env');
    foreach ($lines as $line) {
        $line = trim($line);
        if (empty($line) || $line[0] === '#') continue;
        list($key, $value) = explode('=', $line, 2);
        $_ENV[trim($key)] = trim($value, '\'"');
    }
}

$db_host = $_ENV['DB_HOST'] ?? 'localhost';
$db_name = $_ENV['DB_NAME'] ?? 'fogbreak';
// etc.
```

**Method 2: Using vlucas/phpdotenv (recommended)**
```bash
cd /var/www/fogbreak.io
composer require vlucas/phpdotenv
```

```php
// At the top of api/config.php
require_once __DIR__ . '/../vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();

$db_host = getenv('DB_HOST');
$db_name = getenv('DB_NAME');
// etc.
```

---

## Database Migrations

Migrations run automatically during deployment. Ensure migration files exist:

- `api/migrate_fogbreak.php` — Core schema
- `api/migrate_lp_features.php` — Phase 1.5 features
- `api/migrate_tenants.php` — Multi-tenant support

Each migration should:
1. Check if tables exist
2. Create/alter tables if needed
3. Log completion to `cron_log`
4. Return success/failure

Example pattern:
```php
<?php
// api/migrate_example.php

require_once 'config.php';

try {
    $db = getDB();

    // Check if already migrated
    $result = $db->query("SHOW TABLES LIKE 'example_table'");
    if ($result->rowCount() > 0) {
        echo "Migration already applied\n";
        exit(0);
    }

    // Create table
    $db->exec("CREATE TABLE example_table (...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    // Log
    logCronExecution('migrate_example', 'success', 'Created example_table');
    echo "Migration complete\n";
    exit(0);
} catch (Exception $e) {
    logCronExecution('migrate_example', 'failed', $e->getMessage());
    echo "Migration failed: " . $e->getMessage() . "\n";
    exit(1);
}
```

---

## Security Checklist

Before going live:

- [ ] `.env` file is NOT in version control
- [ ] `.env` permissions are `600` (not readable by web server)
- [ ] `config.php` is NOT in version control (use `config.php.example`)
- [ ] `config.php` permissions are `600`
- [ ] `.git` directory is blocked in Nginx (`deny all`)
- [ ] API key (`API_KEY`) is strong and rotated
- [ ] HTTPS/SSL is working (no mixed content warnings)
- [ ] HSTS is enabled (30+ day max-age)
- [ ] X-Frame-Options header is `SAMEORIGIN`
- [ ] X-Content-Type-Options is `nosniff`
- [ ] Rate limiting is active on `/api/` endpoints
- [ ] Webhook signature validation is enabled
- [ ] PHP version is >= 8.2
- [ ] `display_errors` is OFF in production PHP config
- [ ] Logs are not served via web
- [ ] Backups are running (instruction 21)

---

## Troubleshooting

### Deployment Fails

Check logs:
```bash
# GitHub Actions logs (in GitHub UI)
# Or SSH into server and check:

tail -f /var/log/fogbreak/deploy.log
tail -f /var/log/fogbreak/deploy-error.log
```

Common issues:
- SSH key not configured in GitHub secrets
- Git repository not cloned on server
- Permissions issue (www-data can't write to directories)
- Migration scripts failing

### Webhook Not Triggering

1. Verify GitHub webhook is configured:
   ```
   Settings > Webhooks > Check Recent Deliveries
   ```

2. Check HTTP status codes (should be 200)

3. Verify secret matches:
   ```bash
   grep GITHUB_WEBHOOK_SECRET /var/www/fogbreak.io/.env
   ```

4. Test manually:
   ```bash
   curl -X POST https://fogbreak.io/deploy/webhook.php \
     -H "X-Hub-Signature-256: sha256=dummy" \
     -H "X-Github-Event: push" \
     -d '{"ref":"refs/heads/main","commits":[]}'
   ```

### Nginx Not Starting

```bash
sudo nginx -t  # Test configuration
sudo systemctl restart nginx  # Restart with logs
sudo journalctl -u nginx -n 20  # View last 20 log lines
```

### PHP-FPM Connection Issues

```bash
# Verify socket exists
ls -la /var/run/php/php8.2-fpm.sock

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

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

---

## Monitoring & Alerts

### Health Check

Nginx config includes a `/health` endpoint:
```bash
curl https://fogbreak.io/health
# Response: "healthy" (HTTP 200)
```

Use with uptime monitoring service (e.g., Uptime Robot, DataDog).

### Deployment Notifications

Slack webhook is configured in `deploy.yml`:
- Set `SLACK_WEBHOOK_URL` secret in GitHub
- Notifications sent on success/failure

### Access Logs

Analyze traffic:
```bash
# Real-time access
tail -f /var/log/fogbreak/access.log

# Top IPs
awk '{print $1}' /var/log/fogbreak/access.log | sort | uniq -c | sort -rn

# Top endpoints
awk '{print $7}' /var/log/fogbreak/access.log | sort | uniq -c | sort -rn

# Slow requests (>1 second response time)
awk '$NF > 1.0 {print}' /var/log/fogbreak/access.log
```

---

## Rollback

To rollback to a previous deployment:

**With GitHub Actions:**
```bash
git revert <commit-hash>
git push origin main
# GitHub Actions will auto-deploy the reverted state
```

**Manual rollback:**
```bash
cd /var/www/fogbreak.io
git log --oneline  # Find commit to revert to
git reset --hard <commit-hash>
git push origin main --force  # Not recommended for shared repos
```

---

## Next Steps

1. Add SSH secrets to GitHub repository
2. Commit all files to main branch
3. Monitor first automatic deployment
4. Test webhook manually if using Option B
5. Configure Slack notifications (optional)
6. Set up backup and log rotation (instruction 21)

---

**For questions or issues, refer to CLAUDE.md (project instructions) or the relevant instruction file (e.g., instruction 21 for backups, instruction 03 for AI setup).**
