# Webhook Setup with Pangolin

## Overview

Pangolin provides secure tunneling similar to Cloudflare Tunnel, allowing you to expose your webhook endpoint without opening firewall ports or making your entire application public.

---

## Architecture

```
Internet → Pangolin Edge → Pangolin Agent → Pulse App (Internal)
                           No open ports!    Port 3100
```

**Benefits:**
- ✅ No firewall changes needed
- ✅ No public IP required
- ✅ Automatic SSL/TLS
- ✅ Only webhook endpoint exposed
- ✅ Built-in DDoS protection
- ✅ Zero Trust security

---

## Prerequisites

1. **Pangolin Account**
   - Active Pangolin subscription
   - Access to Pangolin dashboard

2. **Domain/Subdomain**
   - Example: `webhooks.yourdomain.com`
   - DNS managed by Pangolin or pointed to Pangolin

3. **Pulse Application Running**
   - Accessible on internal network (e.g., `localhost:3100`)

---

## Setup Steps

### **Step 1: Install Pangolin Agent**

On the server running Pulse:

```bash
# Download Pangolin agent (adjust URL for your version)
curl -O https://download.pangolin.com/agent/latest/pangolin-agent-linux-amd64

# Make executable
chmod +x pangolin-agent-linux-amd64
sudo mv pangolin-agent-linux-amd64 /usr/local/bin/pangolin-agent

# Verify installation
pangolin-agent --version
```

### **Step 2: Authenticate Pangolin Agent**

```bash
# Login to Pangolin
pangolin-agent login

# Follow the prompts to authenticate
# This will open a browser window or provide a URL
```

### **Step 3: Create Tunnel Configuration**

Create `/etc/pangolin/config.yml`:

```yaml
# Pangolin Tunnel Configuration for Pulse Webhooks

# Tunnel name
name: pulse-webhooks

# Ingress rules - define what gets exposed
ingress:
  # Webhook endpoint - the only exposed path
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/autotask
    service: http://localhost:3100
    
  # Optional: Webhook logs endpoint (for monitoring)
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/logs
    service: http://localhost:3100
    
  # Optional: Webhook stats endpoint (for monitoring)
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/stats
    service: http://localhost:3100
  
  # Catch-all - deny everything else
  - service: http_status:404

# Security settings
security:
  # Rate limiting
  rateLimit:
    enabled: true
    requestsPerMinute: 100
    burstSize: 20
  
  # Optional: IP whitelist for Autotask
  # Get Autotask IP ranges from their documentation
  # ipWhitelist:
  #   - "1.2.3.4/24"
  #   - "5.6.7.8/24"

# Logging
logging:
  level: info
  file: /var/log/pangolin/tunnel.log
```

### **Step 4: Create Tunnel**

```bash
# Create tunnel with configuration
sudo pangolin-agent tunnel create \
  --config /etc/pangolin/config.yml \
  --name pulse-webhooks

# This will output a tunnel ID - save it!
# Example: tun_abc123xyz
```

### **Step 5: Configure DNS**

In Pangolin dashboard or via CLI:

```bash
# Route your subdomain to the tunnel
pangolin-agent dns create \
  --hostname webhooks.yourdomain.com \
  --tunnel pulse-webhooks
```

Or in Pangolin dashboard:
1. Go to DNS settings
2. Add CNAME record: `webhooks.yourdomain.com` → `<tunnel-id>.pangolin.io`

### **Step 6: Start Tunnel**

**Option A: Run in foreground (for testing)**
```bash
sudo pangolin-agent tunnel run pulse-webhooks
```

**Option B: Install as systemd service (recommended)**

Create `/etc/systemd/system/pangolin-tunnel.service`:

```ini
[Unit]
Description=Pangolin Tunnel for Pulse Webhooks
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/pangolin-agent tunnel run pulse-webhooks --config /etc/pangolin/config.yml
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
```

Enable and start:
```bash
sudo systemctl daemon-reload
sudo systemctl enable pangolin-tunnel
sudo systemctl start pangolin-tunnel
sudo systemctl status pangolin-tunnel
```

### **Step 7: Verify Tunnel**

```bash
# Check tunnel status
pangolin-agent tunnel list

# Test endpoint
curl https://webhooks.yourdomain.com/api/webhooks/autotask
# Expected: {"status":"active"...}
```

---

## Alternative: Minimal Configuration

If you prefer a simpler setup without a config file:

```bash
# Create and start tunnel in one command
pangolin-agent tunnel \
  --hostname webhooks.yourdomain.com \
  --url http://localhost:3100 \
  --path /api/webhooks/autotask
```

---

## Security Configuration

### **1. Path-Based Access Control**

Only expose specific paths in `config.yml`:

```yaml
ingress:
  # Allow webhook endpoint
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/autotask
    service: http://localhost:3100
  
  # Block everything else
  - service: http_status:404
```

### **2. Rate Limiting**

Protect against abuse:

```yaml
security:
  rateLimit:
    enabled: true
    requestsPerMinute: 100  # Adjust based on expected traffic
    burstSize: 20           # Allow bursts of 20 requests
```

### **3. IP Whitelisting (Optional)**

If you have Autotask's IP ranges:

```yaml
security:
  ipWhitelist:
    - "1.2.3.4/24"    # Autotask IP range 1
    - "5.6.7.8/24"    # Autotask IP range 2
```

### **4. Request Headers**

Add security headers:

```yaml
ingress:
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/autotask
    service: http://localhost:3100
    headers:
      X-Frame-Options: DENY
      X-Content-Type-Options: nosniff
      X-XSS-Protection: "1; mode=block"
```

---

## Monitoring

### **View Tunnel Logs**

```bash
# Systemd journal
sudo journalctl -u pangolin-tunnel -f

# Or log file (if configured)
tail -f /var/log/pangolin/tunnel.log
```

### **Tunnel Statistics**

```bash
# Get tunnel stats
pangolin-agent tunnel stats pulse-webhooks

# List active connections
pangolin-agent tunnel connections pulse-webhooks
```

### **Webhook Logs**

Monitor webhook processing:

```bash
# Via API (if exposed)
curl https://webhooks.yourdomain.com/api/webhooks/logs?limit=10

# Via database
docker exec pulse-postgres psql -U pulse_user -d pulse_autotask -c \
  "SELECT event_id, entity_type, status, processing_time_ms 
   FROM webhook_logs 
   ORDER BY received_at DESC 
   LIMIT 10;"
```

---

## Testing

### **1. Health Check**

```bash
curl https://webhooks.yourdomain.com/api/webhooks/autotask
```

Expected response:
```json
{
  "status": "active",
  "endpoint": "/api/webhooks/autotask",
  "message": "Autotask webhook receiver is ready"
}
```

### **2. Test Webhook POST**

```bash
curl -X POST https://webhooks.yourdomain.com/api/webhooks/autotask \
  -H "Content-Type: application/json" \
  -d '{
    "eventId": "test_pangolin_123",
    "eventType": "create",
    "entityType": "Tickets",
    "entityId": 99999,
    "eventTimestamp": "2026-01-24T10:00:00Z",
    "entity": {
      "id": 99999,
      "title": "Test Ticket via Pangolin"
    }
  }'
```

Expected response:
```json
{
  "success": true,
  "eventId": "test_pangolin_123",
  "action": "created",
  "processingTime": 45
}
```

### **3. Verify Path Blocking**

```bash
# These should return 404
curl https://webhooks.yourdomain.com/
curl https://webhooks.yourdomain.com/admin
curl https://webhooks.yourdomain.com/api/sync
```

### **4. Test Rate Limiting**

```bash
# Send 150 requests quickly
for i in {1..150}; do
  curl -s https://webhooks.yourdomain.com/api/webhooks/autotask > /dev/null
  echo "Request $i"
done

# Should see rate limit errors after ~100 requests
```

---

## Configure Autotask

Once your Pangolin tunnel is working:

1. **Log in to Autotask** as administrator
2. **Navigate to:** Admin → Features & Settings → API & Integrations → Webhooks
3. **Create New Webhook:**
   - **Name:** `Pulse - Tickets` (or entity name)
   - **Endpoint URL:** `https://webhooks.yourdomain.com/api/webhooks/autotask`
   - **Entity Type:** Select entity (e.g., Tickets)
   - **Events:** ✅ Create, ✅ Update
   - **Include Entity Data:** ✅ **Enable this!**
   - **Active:** ✅ Enabled
4. **Test Webhook** from Autotask UI
5. **Verify** in Pulse webhook logs

Repeat for each entity: Companies, Tasks, Projects, Time Entries, Contacts

---

## Troubleshooting

### **Tunnel Not Starting**

**Check 1: Agent Status**
```bash
pangolin-agent status
```

**Check 2: Configuration**
```bash
# Validate config file
pangolin-agent tunnel validate --config /etc/pangolin/config.yml
```

**Check 3: Logs**
```bash
sudo journalctl -u pangolin-tunnel -n 50
```

### **Webhooks Not Received**

**Check 1: Tunnel is Running**
```bash
pangolin-agent tunnel list
# Should show pulse-webhooks as "active"
```

**Check 2: DNS Resolution**
```bash
nslookup webhooks.yourdomain.com
# Should resolve to Pangolin edge
```

**Check 3: Pulse App is Accessible**
```bash
# Test from same server
curl http://localhost:3100/api/webhooks/autotask
# Should return health check response
```

**Check 4: Webhook Logs**
```bash
# Check if webhooks are being received but failing
docker exec pulse-postgres psql -U pulse_user -d pulse_autotask -c \
  "SELECT * FROM webhook_logs WHERE status = 'failed' ORDER BY received_at DESC LIMIT 5;"
```

### **502 Bad Gateway**

Pulse app is not reachable from Pangolin agent:

```bash
# Verify Pulse app is running
docker ps | grep pulse-app

# Check port
netstat -tlnp | grep 3100

# Test direct connection
curl http://localhost:3100/api/webhooks/autotask
```

**Fix:** Ensure `service: http://localhost:3100` in config matches your Pulse app's actual address and port.

### **Rate Limiting Issues**

If legitimate webhooks are being rate limited:

```yaml
# Increase limits in config.yml
security:
  rateLimit:
    enabled: true
    requestsPerMinute: 200  # Increased from 100
    burstSize: 50           # Increased from 20
```

Then restart tunnel:
```bash
sudo systemctl restart pangolin-tunnel
```

---

## Advanced Configuration

### **Multiple Paths**

Expose additional endpoints if needed:

```yaml
ingress:
  # Webhook receiver
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/autotask
    service: http://localhost:3100
  
  # Monitoring endpoints (optional)
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/logs
    service: http://localhost:3100
    # Optional: Add authentication
    auth:
      type: basic
      username: admin
      password: ${WEBHOOK_ADMIN_PASSWORD}
  
  - hostname: webhooks.yourdomain.com
    path: /api/webhooks/stats
    service: http://localhost:3100
    auth:
      type: basic
      username: admin
      password: ${WEBHOOK_ADMIN_PASSWORD}
```

### **Custom Domain**

If using your own domain (not Pangolin subdomain):

1. Add CNAME in your DNS provider:
   ```
   webhooks.yourdomain.com → <tunnel-id>.pangolin.io
   ```

2. Update Pangolin configuration:
   ```bash
   pangolin-agent dns create \
     --hostname webhooks.yourdomain.com \
     --tunnel pulse-webhooks \
     --custom-domain
   ```

### **High Availability**

Run multiple Pangolin agents for redundancy:

**Server 1:**
```bash
pangolin-agent tunnel run pulse-webhooks --config /etc/pangolin/config.yml
```

**Server 2:**
```bash
pangolin-agent tunnel run pulse-webhooks --config /etc/pangolin/config.yml
```

Pangolin will automatically load balance between agents.

---

## Performance Optimization

### **Connection Pooling**

```yaml
# In config.yml
performance:
  connectionPool:
    maxConnections: 100
    keepAliveTimeout: 60s
```

### **Compression**

```yaml
# Enable compression for responses
compression:
  enabled: true
  minSize: 1024  # Only compress responses > 1KB
```

### **Caching**

```yaml
# Cache health check responses
cache:
  enabled: true
  rules:
    - path: /api/webhooks/autotask
      method: GET
      ttl: 60s
```

---

## Maintenance

### **Update Pangolin Agent**

```bash
# Download latest version
curl -O https://download.pangolin.com/agent/latest/pangolin-agent-linux-amd64

# Stop service
sudo systemctl stop pangolin-tunnel

# Replace binary
sudo mv pangolin-agent-linux-amd64 /usr/local/bin/pangolin-agent
sudo chmod +x /usr/local/bin/pangolin-agent

# Start service
sudo systemctl start pangolin-tunnel

# Verify
pangolin-agent --version
```

### **Rotate Credentials**

```bash
# Re-authenticate
pangolin-agent logout
pangolin-agent login

# Restart tunnel
sudo systemctl restart pangolin-tunnel
```

### **Backup Configuration**

```bash
# Backup config
sudo cp /etc/pangolin/config.yml /etc/pangolin/config.yml.backup

# Backup tunnel info
pangolin-agent tunnel info pulse-webhooks > ~/pangolin-tunnel-info.txt
```

---

## Cost Optimization

Pangolin typically charges based on:
- Number of tunnels
- Bandwidth usage
- Number of requests

**Tips to minimize costs:**

1. **Use rate limiting** to prevent abuse
2. **Enable compression** to reduce bandwidth
3. **Cache static responses** (health checks)
4. **Monitor usage** regularly
5. **Use single tunnel** for all webhook endpoints

---

## Security Best Practices

1. ✅ **Only expose webhook endpoint** - block all other paths
2. ✅ **Enable rate limiting** - prevent DDoS
3. ✅ **Use HTTPS only** - Pangolin provides this automatically
4. ✅ **Monitor logs** - watch for suspicious activity
5. ✅ **IP whitelist** - if Autotask provides IP ranges
6. ✅ **Keep agent updated** - apply security patches
7. ✅ **Rotate credentials** - periodically re-authenticate

---

## Summary

**Pangolin Setup for Pulse Webhooks:**

1. ✅ Install Pangolin agent
2. ✅ Create tunnel configuration (expose only `/api/webhooks/autotask`)
3. ✅ Start tunnel as systemd service
4. ✅ Configure DNS to point to tunnel
5. ✅ Test endpoint
6. ✅ Configure webhooks in Autotask
7. ✅ Monitor logs and statistics

**Result:**
- Webhook endpoint accessible at `https://webhooks.yourdomain.com/api/webhooks/autotask`
- No firewall changes needed
- No open ports
- Automatic SSL/TLS
- Rest of application remains private

---

## Support

For Pangolin-specific issues:
- Pangolin Documentation: Check your Pangolin dashboard
- Pangolin Support: Contact via your support channel

For Pulse webhook issues:
- Check webhook logs: `/api/webhooks/logs`
- Review database: `webhook_logs` table
- See main documentation: `WEBHOOK_SETUP.md`
