Sign inSign up

hiteshjoshi/posthog_reverse_proxy

By hiteshjoshi

•Updated about 1 year ago

Posthog reverse proxy to be deployed on you own docker infra.

Image
1

4.4K

hiteshjoshi/posthog_reverse_proxy repository overview

⁠PostHog Nginx Reverse Proxy

This Docker container provides a secure nginx reverse proxy for PostHog analytics, allowing you to route analytics requests through your own domain to avoid ad blockers and maintain data privacy.

⁠Features

⁠Core Functionality
  • Domain-based access control: Only allows requests from your specified domain(s)
  • PostHog Cloud proxy: Routes requests to PostHog Cloud (US or EU regions)
  • Separate handling: Different routing for static assets and API calls
⁠Improvements Over Standard Setup
  1. DNS Re-resolution: Forces nginx to re-resolve PostHog's DNS on each request, preventing issues with IP rotation
  2. SSL/TLS Fixes: Includes proxy_ssl_server_name to prevent SSL handshake failures
  3. Static Asset Caching: Caches static files (like recorder.js) for improved performance
  4. Health Check Endpoint: Built-in /health endpoint for monitoring
  5. Enhanced Logging: Detailed logging including cache status
  6. Redundant DNS Resolvers: Uses multiple DNS providers for reliability
  7. Connection Pooling: Maintains keepalive connections to PostHog servers

⁠Quick Start

⁠Using Docker
docker build -t posthog-proxy .
docker run -d \
  -p 8080:8080 \
  -e ALLOWED_DOMAIN=yourdomain.com \
  -e POSTHOG_CLOUD=us \
  posthog-proxy
⁠Using Docker Compose
version: '3.8'
services:
  posthog-proxy:
    build: .
    ports:
      - "8080:8080"
    environment:
      - ALLOWED_DOMAIN=yourdomain.com
      - POSTHOG_CLOUD=us
      - CACHE_STATIC_DAYS=7
    restart: unless-stopped

⁠Configuration

⁠Environment Variables
VariableDefaultDescription
ALLOWED_DOMAINgoogle.comYour domain name (without protocol). Requests with referers from this domain and its subdomains will be allowed.
POSTHOG_CLOUDusPostHog cloud region. Use us for US cloud or eu for EU cloud.
CACHE_STATIC_DAYS7Number of days to cache static assets.
⁠Client Configuration

Configure your PostHog client to use your proxy:

posthog.init('YOUR_API_KEY', {
    api_host: 'https://yourdomain.com',
    ui_host: 'https://app.posthog.com' // or 'https://eu.posthog.com' for EU
});

If you're serving the proxy on a subpath:

posthog.init('YOUR_API_KEY', {
    api_host: 'https://yourdomain.com/analytics',
});

⁠Architecture

⁠Request Flow
  1. Client makes request to https://yourdomain.com/*
  2. Nginx checks the Referer header:
    • Allows empty referer (direct access)
    • Allows localhost (for development)
    • Allows your configured domain and all subdomains
  3. For /static/* paths:
    • Proxies to https://[region]-assets.i.posthog.com/static/*
    • Caches responses for configured duration
    • Adds cache headers
  4. For all other paths:
    • Proxies to https://[region].i.posthog.com/*
    • No caching (real-time analytics data)
⁠Security Features
  • Referer validation: Only accepts requests from your domain
  • No data storage: Proxy doesn't store any analytics data
  • SSL/TLS termination: Maintains secure connections to PostHog
  • No cookies: Doesn't set or forward cookies

⁠Deployment Examples

⁠Behind Traefik
services:
  posthog-proxy:
    build: .
    environment:
      - ALLOWED_DOMAIN=yourdomain.com
      - POSTHOG_CLOUD=us
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.posthog.rule=Host(`analytics.yourdomain.com`)"
      - "traefik.http.routers.posthog.tls=true"
      - "traefik.http.services.posthog.loadbalancer.server.port=8080"
⁠On Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
  name: posthog-proxy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: posthog-proxy
  template:
    metadata:
      labels:
        app: posthog-proxy
    spec:
      containers:
      - name: nginx
        image: your-registry/posthog-proxy:latest
        ports:
        - containerPort: 8080
        env:
        - name: ALLOWED_DOMAIN
          value: "yourdomain.com"
        - name: POSTHOG_CLOUD
          value: "us"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

⁠Monitoring

⁠Health Check

The proxy includes a health endpoint at /health that returns 200 OK when the service is running.

curl http://localhost:8080/health
# Returns: healthy
⁠Logs

The proxy logs all requests with detailed information:

[01/Jan/2024:12:00:00 +0000] "GET /static/recorder.js HTTP/1.1" 200 "Referer: https://yourdomain.com" "Host: yourdomain.com" "Cache: HIT"
⁠Cache Status

The X-Cache-Status header indicates cache performance for static assets:

  • HIT: Served from cache
  • MISS: Fetched from origin
  • UPDATING: Serving stale content while updating
  • STALE: Serving stale content due to origin error

⁠Troubleshooting

⁠SSL Handshake Failures

If you see SSL handshake errors in the logs, ensure:

  1. The proxy_ssl_server_name on; directive is present (already included)
  2. Your nginx version supports SNI (1.24+ does)
⁠Recording Not Working

If events work but recordings don't:

  1. Check that /static/recorder.js requests are succeeding
  2. Verify the referer header is being sent by your application
  3. Check browser console for CORS errors
⁠403 Forbidden Errors

This means the referer check is failing:

  1. Verify ALLOWED_DOMAIN matches your actual domain
  2. Check that your application sends the Referer header
  3. For development, requests from localhost are allowed
⁠DNS Resolution Issues

The proxy is configured to handle PostHog's IP rotation automatically. If you still experience issues:

  1. Check that the DNS resolvers are accessible from your network
  2. The configuration uses multiple resolvers for redundancy
  3. DNS responses are cached for 5 minutes (configurable via valid=300s)

⁠Contributing

To modify the proxy configuration:

  1. Edit entrypoint.sh for nginx configuration changes
  2. Update Dockerfile for build-time changes
  3. Test locally with: docker build -t test . && docker run -p 8080:8080 test
  4. Check nginx configuration validity inside container: docker exec <container> nginx -t

⁠License

This configuration is provided as-is for use with PostHog services.

Tag summary

Content type

Image

Digest

sha256:8b61ea0d1…

Size

6.9 MB

Last updated

about 1 year ago

docker pull hiteshjoshi/posthog_reverse_proxy