AddonPulse
Proxy Guide

Caddy Proxy Setup

Configure Caddy reverse proxy to serve AddonPulse tracking with automatic HTTPS

Caddy is a powerful web server with automatic HTTPS that makes reverse proxying simple and secure. This guide shows how to configure Caddy to proxy AddonPulse tracking through your own domain.

Overview

Caddy's reverse_proxy directive makes it incredibly easy to proxy requests. Combined with automatic HTTPS via Let's Encrypt, Caddy provides a secure, low-configuration solution for proxying analytics.

What you'll achieve:

  • Automatic HTTPS with Let's Encrypt
  • Simple reverse proxy configuration
  • Header forwarding for accurate tracking
  • Support all AddonPulse features

Prerequisites

  • Caddy installed (version 2.0 or later)
  • Domain pointing to your server
  • Your AddonPulse instance URL https://app.addonpulse.com
  • Your AddonPulse site ID (found in your dashboard)

Caddy automatically obtains and renews SSL certificates from Let's Encrypt. No manual SSL configuration needed!

Implementation

Configure Caddyfile

Add or update your Caddyfile with the analytics proxy configuration:

# /etc/caddy/Caddyfile

yourdomain.com {
    # Main tracking script
    handle /analytics/script.js {
        reverse_proxy https://app.addonpulse.com {
            header_up Host app.addonpulse.com
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api/script.js
    }

    # Event tracking
    handle /analytics/track {
        reverse_proxy https://app.addonpulse.com {
            header_up Host app.addonpulse.com
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api/track
    }
}

Caddy 2.4+ supports a cleaner syntax with handle_path:

# /etc/caddy/Caddyfile

yourdomain.com {
    handle_path /analytics/* {
        reverse_proxy https://app.addonpulse.com {
            header_up Host app.addonpulse.com
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api{uri}
    }
}

This proxies all /analytics/* requests to https://app.addonpulse.com/api/*.

Validate Caddyfile

Test your configuration for syntax errors:

caddy validate --config /etc/caddy/Caddyfile

You should see:

Valid configuration

Reload Caddy

Apply the changes by reloading Caddy:

sudo caddy reload --config /etc/caddy/Caddyfile

Or if using systemd:

sudo systemctl reload caddy

Caddy will automatically obtain an SSL certificate from Let's Encrypt on first request if one doesn't exist.

Update Your Tracking Script

Update your HTML to load the script from your proxied domain:

<!DOCTYPE html>
<html>
<head>
    <!-- ... other head elements -->
    <script src="/analytics/script.js" async data-site-id="YOUR_SITE_ID"></script>
</head>
<body>
    <!-- Your content -->
</body>
</html>

Replace YOUR_SITE_ID with your actual site ID from the AddonPulse dashboard.

Verify the Setup

Test your configuration:

  1. Check Caddy is running:

    sudo systemctl status caddy
  2. Test script loading:

    curl -I https://yourdomain.com/analytics/script.js

    You should see HTTP/2 200 with content-type: application/javascript.

  3. Open your website in a browser with Developer Tools and verify:

    • Script loads from /analytics/script.js
    • Tracking requests go to /analytics/track
    • Data appears in AddonPulse dashboard

How It Works

Caddy's reverse_proxy directive forwards requests to AddonPulse's servers:

  1. Browser requests https://yourdomain.com/analytics/script.js
  2. Caddy matches the handle block
  3. Rewrites the path to /api/script.js
  4. Forwards to https://app.addonpulse.com/api/script.js with proper headers
  5. Returns response to browser

The AddonPulse script auto-detects it's being served from your domain and sends all tracking to your domain's endpoints.

Advanced Configuration

Caching with Cache-Control

Add caching headers for better performance:

yourdomain.com {
    # Scripts - cache for 1 hour
    handle /analytics/script.js {
        reverse_proxy https://app.addonpulse.com {
            header_up Host app.addonpulse.com
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api/script.js
        header Cache-Control "public, max-age=3600"
    }

    # Config - cache for 5 minutes
    handle /analytics/site/tracking-config/* {
        reverse_proxy https://app.addonpulse.com {
            header_up Host app.addonpulse.com
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api/site/tracking-config{path}
        header Cache-Control "public, max-age=300"
    }

    # Tracking - no cache
    handle /analytics/track {
        reverse_proxy https://app.addonpulse.com {
            header_up Host app.addonpulse.com
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api/track
        header Cache-Control "no-store"
    }
}

Subdomain Proxy

Use a dedicated subdomain for analytics:

# /etc/caddy/Caddyfile

analytics.yourdomain.com {
    reverse_proxy https://app.addonpulse.com {
        header_up Host app.addonpulse.com
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
    }
    rewrite * /api{uri}
}

Then use:

<script src="https://analytics.yourdomain.com/script.js" data-site-id="123"></script>

Environment-Based Configuration

Use Caddy's environment variable support:

# /etc/caddy/Caddyfile

{$DOMAIN:yourdomain.com} {
    handle_path /analytics/* {
        reverse_proxy {$ADDONPULSE_HOST:https://app.addonpulse.com} {
            header_up Host {upstream_hostport}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api{uri}
    }
}

Then set environment variables:

export DOMAIN=yourdomain.com
export ADDONPULSE_HOST=https://app.addonpulse.com
caddy run

Rate Limiting

Protect your proxy with rate limiting using the rate_limit plugin:

yourdomain.com {
    handle /analytics/track {
        rate_limit {
            zone analytics {
                key {remote_host}
                events 100
                window 1m
            }
        }
        reverse_proxy https://app.addonpulse.com {
            header_up Host app.addonpulse.com
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
        rewrite * /api/track
    }
}

The rate_limit directive requires the caddy-ratelimit plugin. Install with: xcaddy build --with github.com/mholt/caddy-ratelimit

Troubleshooting

Certificate errors

Problem: Caddy fails to obtain SSL certificate.

Solution:

  1. Verify domain points to your server (DNS)
  2. Check ports 80 and 443 are open
  3. Ensure no other process is using port 443
  4. Check Caddy logs: journalctl -u caddy -f

Incorrect geolocation

Problem: All visitors show same location.

Solution: Ensure you're forwarding client IP:

reverse_proxy https://app.addonpulse.com {
    header_up X-Real-IP {remote_host}
    header_up X-Forwarded-For {remote_host}
}

502 Bad Gateway

Problem: Caddy returns 502 when accessing analytics endpoints.

Solution:

  1. Verify AddonPulse backend is accessible:
    curl -I https://app.addonpulse.com/api/script.js
  2. Check Caddy logs for errors:
    journalctl -u caddy -n 50

Path rewriting not working

Problem: Requests go to wrong AddonPulse endpoints.

Solution: Use the rewrite directive correctly:

handle /analytics/script.js {
    rewrite * /api/script.js  # Rewrite before reverse_proxy
    reverse_proxy https://app.addonpulse.com {
        # ... headers
    }
}

On this page