Note: 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.
Note: If you are using the EU cloud then use
eu
instead ofus
in all domains (e.g.us.i.posthog.com
->eu.i.posthog.com
)
If you are using Remix, you can use API routes to set up a reverse proxy.
Create a file ingest.$.tsx
in the routes folder. In this file, set up code to match requests to a custom route, set a new host header, change the URL to point to PostHog, and rewrite the response.
import type { ActionFunction, LoaderFunction } from "@remix-run/node";const API_HOST = "eu.i.posthog.com";const ASSET_HOST = "eu-assets.i.posthog.com";const posthogProxy = async (request: Request) => {const url = new URL(request.url);const hostname = url.pathname.startsWith("/ingest/static/")? ASSET_HOST: API_HOST;const newUrl = new URL(url);newUrl.protocol = "https";newUrl.hostname = hostname;newUrl.port = "443";newUrl.pathname = newUrl.pathname.replace(/^\/ingest/, "");const headers = new Headers(request.headers);headers.set("host", hostname);const response = await fetch(newUrl, {method: request.method,headers,body: request.body,});return new Response(response.body, {status: response.status,statusText: response.statusText,headers: response.headers,});};export const loader: LoaderFunction = async ({ request }) =>posthogProxy(request);export const action: ActionFunction = async ({ request }) =>posthogProxy(request);
Once done, configure the PostHog client to send requests via your rewrite.
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {api_host: "/ingest",ui_host: "<ph_app_host>"})