Using nginx as a reverse proxy

Warning
  1. The following self-hosted proxy isn't provided by PostHog, so we can't take responsibility for it! If unsure, we recommend using our managed reverse proxy.

  2. If you are using the EU cloud then use eu instead of us in all domains (e.g. us.i.posthog.com -> eu.i.posthog.com).

  3. Avoid using generic or common path names like /analytics, /tracking, /ingest, or /posthog for your reverse proxy. They will most likely be blocked. Instead, use a non-obvious path name or something random and unique to your application that's unlikely to appear in a filter list.

Creating a nginx container

You can use nginx as a reverse proxy. To do this, first create a Dockerfile to build a nginx container:

dockerfile
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf.template
CMD ["sh", "-c", "envsubst '\\$POSTHOG_CLOUD_REGION' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"]

Next, create the nginx.conf file with the reverse proxy configuration.

nginx.conf
worker_processes auto;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 8080;
server_name _;
# DNS resolver - increased cache time for stability
resolver 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=300s;
resolver_timeout 5s;
# Static assets - trailing slashes preserve path mapping
location /static/ {
proxy_pass https://${POSTHOG_CLOUD_REGION}-assets.i.posthog.com/static/;
proxy_set_header Host "${POSTHOG_CLOUD_REGION}-assets.i.posthog.com";
proxy_ssl_server_name on;
proxy_hide_header 'Access-Control-Allow-Origin';
proxy_hide_header 'Access-Control-Allow-Methods';
proxy_hide_header 'Access-Control-Allow-Headers';
proxy_hide_header 'Access-Control-Expose-Headers';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
# Main API endpoints
location / {
proxy_pass https://${POSTHOG_CLOUD_REGION}.i.posthog.com;
proxy_set_header Host "${POSTHOG_CLOUD_REGION}.i.posthog.com";
proxy_ssl_server_name on;
proxy_hide_header 'Access-Control-Allow-Origin';
proxy_hide_header 'Access-Control-Allow-Methods';
proxy_hide_header 'Access-Control-Allow-Headers';
proxy_hide_header 'Access-Control-Expose-Headers';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
}
}

Running the nginx container

Terminal
docker build -t posthog-nginx .
docker run --rm -p 8080:8080 -e POSTHOG_CLOUD_REGION=us posthog-nginx

Now you can connect to PostHog through this proxy by configuring the PostHog client to use http://localhost:8080.

JavaScript
posthog.init(<ph_project_api_key>, {
api_host: localhost:8080,
ui_host: 'https://us.posthog.com', // for the toolbar to work
// for EU Cloud
// ui_host: 'https://eu.posthog.com',
});

Community questions

Was this page useful?

Questions about this page? or post a community question.