WebSockets, HMR, and Dev Tunnels
Running Postiz behind ngrok or a reverse proxy with WebSocket support
Production reverse proxy
How you reverse-proxy depends on how you're running Postiz:
- Official Docker image (
ghcr.io/gitroomhq/postiz-app): frontend and backend are bundled inside one container and exposed on a single port (5000internally; the official compose maps it to host4007). Your reverse proxy only needs to forward one upstream. Most users on this image don't need anything beyond standard HTTPS termination. - Source / multi-container deployments (
pnpm dev,pnpm start, or splitting frontend and backend into separate containers): frontend runs on4200, backend on3000, and you need to route the paths below correctly.
For the split setup, forward:
| Path | Upstream | Notes |
|---|---|---|
/ (everything not below) | Frontend :4200 | Pass Upgrade and Connection headers for Next.js HMR in dev. |
/api/* | Backend :3000 | Standard HTTP. |
/public/* | Backend :3000 | Public API. |
/auth/* | Backend :3000 | Sign-in flow. |
/integrations/* | Backend :3000 | OAuth callbacks. |
/mcp/*, /sse/*, /message/* | Backend :3000 | MCP transport, must support streaming HTTP. |
/webhooks/* | Backend :3000 | Inbound webhook callbacks from providers (Stripe, social platforms). |
For configured examples, see Caddy, Nginx, and Traefik.
Dev behind ngrok / Cloudflared
Running next dev behind an HTTPS tunnel needs three things:
1. Bind to all interfaces
pnpm dev # binds 0.0.0.0:4200 by default in this repo
# or explicitly
pnpm --filter @postiz/frontend exec next dev -p 4200 -H 0.0.0.02. Allow the tunnel host in next.config
Add your tunnel hostname to the allowedDevOrigins field in
apps/frontend/next.config.js (introduced in Next.js 15.x). Without
this, Next.js refuses HMR connections coming through the tunnel.
const nextConfig = {
allowedDevOrigins: ['your-subdomain.ngrok-free.app'],
// ...
};3. WebSockets must reach the dev server
Most tunnels support WSS out of the box. If you've put your own
reverse proxy in front of the tunnel, ensure Upgrade and Connection
headers pass through, without them the HMR client disconnects every
few seconds.
redirectmeto: why OAuth redirects sometimes go through a third party
When FRONTEND_URL is plain HTTP, several social providers
(Slack, TikTok, Threads, VK, Instagram standalone) refuse to register
your redirect URI. Postiz works around this by wrapping the redirect
through https://redirectmeto.com/:
https://redirectmeto.com/http://localhost:4200/integrations/social/slackThe browser hits redirectmeto, which serves an HTTPS page that
immediately redirects to the HTTP target, satisfying the provider's
HTTPS-only validation without needing your dev environment to have a
TLS cert.
You only see this in dev. Once FRONTEND_URL is HTTPS, Postiz
skips redirectmeto entirely and uses your URL directly.
If you don't want redirectmeto in the middle even in dev, terminate
TLS at your tunnel (ngrok and Cloudflared both do this by default) and
set FRONTEND_URL to the https:// tunnel URL.