# Deployment with Portainer and Traefik

This guide covers deploying MerchBay Admin using your existing Portainer and Traefik setup.

## Prerequisites

- ✅ Gitea self-hosted with Gitea runners configured
- ✅ Portainer installed and accessible
- ✅ Traefik reverse proxy running with:
  - `web` entrypoint (port 80)
  - `websecure` entrypoint (port 443)
  - Let's Encrypt certificate resolver named `letsencrypt`
  - External network named `traefik`

## Deployment Methods

### Method 1: Portainer Stack Deployment (Recommended)

#### Step 1: Prepare the Image

Build the Docker image via Gitea Actions or manually:

```bash
# Using Gitea Actions (will build automatically on push)
git push origin main

# OR build manually
docker build -t merchbay_admin:latest .
```

#### Step 2: Deploy in Portainer

1. **Access Portainer** → `Stacks` → `Add stack`

2. **Stack Configuration:**
   - Name: `merchbay-admin`
   - Build method: `Web editor`

3. **Paste the content from `docker-compose.portainer.yml`** and update:
   - `APP_URL`: Your domain (e.g., `https://merchbay-admin.yourdomain.com`)
   - `DB_HOST`: Your MySQL host
   - `DB_DATABASE`: Database name
   - `DB_USERNAME`: Database username
   - `DB_PASSWORD`: Database password
   - Traefik Host rule: Replace `merchbay-admin.yourdomain.com` with your actual domain

4. **Deploy the stack**

5. **Run Initial Setup:**
   - Go to `Containers` → Find `merchbay_admin_app`
   - Click `Console` → Connect with `/bin/bash`
   - Run:
     ```bash
     php artisan migrate --force
     php artisan config:cache
     php artisan route:cache
     ```

### Method 2: Gitea Actions CI/CD (Automated)

#### Step 1: Configure Gitea Secrets

In your Gitea repository → `Settings` → `Secrets` → `Actions`, add:

| Secret Name | Value | Description |
|------------|-------|-------------|
| `DEPLOY_HOST` | `192.168.1.100` | Your server IP/hostname |
| `DEPLOY_USER` | `deploy` | SSH username |
| `DEPLOY_SSH_KEY` | `-----BEGIN RSA...` | Private SSH key |
| `DEPLOY_PORT` | `22` | SSH port (optional) |
| `DEPLOY_DIR` | `/var/www/merchbay_admin` | Deployment directory |
| `DOMAIN` | `merchbay-admin.yourdomain.com` | Your domain for Traefik |

#### Step 2: Prepare Deployment Server

```bash
# SSH into your server
ssh deploy@your-server

# Create deployment directory
sudo mkdir -p /var/www/merchbay_admin
sudo chown $USER:$USER /var/www/merchbay_admin
cd /var/www/merchbay_admin

# Create .env file
nano .env
```

Add to `.env`:
```env
APP_ENV=production
APP_DEBUG=false
APP_URL=https://merchbay-admin.yourdomain.com
DB_HOST=your-mysql-host
DB_PORT=3306
DB_DATABASE=merchbay_admin
DB_USERNAME=your-mysql-user
DB_PASSWORD=your-mysql-password
DOMAIN=merchbay-admin.yourdomain.com
```

#### Step 3: Ensure Traefik Network Exists

```bash
docker network inspect traefik >/dev/null 2>&1 || docker network create traefik
```

#### Step 4: Deploy

Simply push to your main branch:

```bash
git add .
git commit -m "Deploy application"
git push origin main
```

Gitea Actions will automatically:
1. Build the Docker image
2. Transfer to your server
3. Deploy with docker-compose
4. Connect to Traefik network
5. Run migrations
6. Cache configurations

### Method 3: Manual Deployment with Script

```bash
# On your server
cd /var/www/merchbay_admin

# Pull latest code
git pull origin main

# Run deployment script
./deploy.sh
```

## Traefik Configuration

### Verify Traefik Setup

Ensure your Traefik configuration includes:

```yaml
# traefik.yml or docker-compose.yml
entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt:
    acme:
      email: your-email@example.com
      storage: /letsencrypt/acme.json
      httpChallenge:
        entryPoint: web
```

### External Network

Ensure Traefik network exists and is external:

```bash
# Create network if it doesn't exist
docker network create traefik

# Verify
docker network inspect traefik
```

## DNS Configuration

Point your domain to your server:

```
Type: A Record
Name: merchbay-admin (or @ for root domain)
Value: YOUR_SERVER_IP
TTL: 3600
```

## Verification

### 1. Check Container Status

**Via Portainer:**
- Navigate to `Containers`
- Verify `merchbay_admin_app` is running

**Via CLI:**
```bash
docker ps | grep merchbay_admin
```

### 2. Check Traefik Dashboard

If you have Traefik dashboard enabled:
- Look for `merchbay-admin@docker` router
- Verify it's connected to the correct service

### 3. Test Application

```bash
# Test HTTPS
curl -I https://merchbay-admin.yourdomain.com

# Should return: HTTP/2 200
```

### 4. Check Logs

**Via Portainer:**
- `Containers` → `merchbay_admin_app` → `Logs`

**Via CLI:**
```bash
docker logs merchbay_admin_app -f
```

## Troubleshooting

### Issue: Container not accessible via domain

**Check Traefik labels:**
```bash
docker inspect merchbay_admin_app | grep -A 20 Labels
```

**Verify network connection:**
```bash
docker network inspect traefik | grep merchbay_admin
```

**Solution:**
```bash
# Reconnect to Traefik network
docker network connect traefik merchbay_admin_app
```

### Issue: SSL certificate not generating

**Check Traefik logs:**
```bash
docker logs traefik | grep letsencrypt
```

**Common fixes:**
1. Ensure port 80 is accessible (Let's Encrypt HTTP challenge)
2. Verify DNS is pointing to your server
3. Check email in Traefik's ACME configuration
4. Ensure `acme.json` has correct permissions (600)

### Issue: Database connection failed

**Check environment variables:**
```bash
docker exec merchbay_admin_app env | grep DB_
```

**Test connection:**
```bash
docker exec merchbay_admin_app php artisan tinker
>>> DB::connection()->getPdo();
```

### Issue: 502 Bad Gateway

**Possible causes:**
1. Application not fully started
2. Wrong port in Traefik label (should be 80)
3. Application crashed

**Check:**
```bash
# Container status
docker ps -a | grep merchbay_admin

# Application logs
docker logs merchbay_admin_app --tail 100

# Restart container
docker restart merchbay_admin_app
```

## Updating the Application

### Via Gitea Actions (Automatic)

```bash
git add .
git commit -m "Update application"
git push origin main
```

### Via Portainer

1. Go to `Stacks` → `merchbay-admin`
2. Click `Editor`
3. Update image or configuration
4. Click `Update the stack`
5. Enable "Re-pull image and redeploy"

### Manual Update

```bash
ssh deploy@your-server
cd /var/www/merchbay_admin
./deploy.sh
```

## Rollback

### Via Portainer

1. Go to `Stacks` → `merchbay-admin`
2. Click on the stack
3. Find previous version in `Stack History` (if available)
4. Revert to previous version

### Manual Rollback

```bash
# List available backups
ls -lh /var/www/merchbay_admin/backups/

# Restore from backup
cd /var/www/merchbay_admin
tar -xzf backups/backup_YYYYMMDD_HHMMSS.tar.gz

# Restart
docker compose restart
```

## Security Best Practices

1. **Use Strong Database Passwords**: Generate with `openssl rand -base64 32`
2. **Restrict SSH Access**: Use key-based authentication only
3. **Firewall Rules**: Only allow necessary ports (80, 443, 22)
4. **Regular Backups**: Automated backups of database and storage
5. **Keep Docker Updated**: Regularly update Docker and images
6. **Monitor Logs**: Set up log monitoring/alerting
7. **Use Secrets**: Never commit sensitive data to repository
8. **HTTPS Only**: Ensure HTTP redirects to HTTPS

## Performance Optimization

### PHP-FPM Configuration

Consider switching to PHP-FPM for better performance:

```dockerfile
FROM php:7.4-fpm-alpine
# ... additional configuration
```

### Use Redis for Cache/Sessions

```env
CACHE_DRIVER=redis
SESSION_DRIVER=redis
REDIS_HOST=redis
```

Add Redis service to docker-compose:
```yaml
services:
  redis:
    image: redis:alpine
    networks:
      - default
```

### Enable OPcache

Already included in Dockerfile, verify:
```bash
docker exec merchbay_admin_app php -i | grep opcache
```

## Monitoring

### View Real-time Logs in Portainer

1. Navigate to `Containers`
2. Click on `merchbay_admin_app`
3. Select `Logs` tab
4. Enable `Auto-refresh`

### Set Up Alerts

Configure Portainer notifications:
1. `Settings` → `Notifications`
2. Add webhook or email notification
3. Set up container health checks

## Support

For issues:
1. Check application logs in Portainer
2. Verify Traefik configuration
3. Test database connectivity
4. Review Gitea Actions logs if using CI/CD
