GUIDE, WITHOUT THE GUESSWORK

Immich Behind a Reverse Proxy: The App-Specific Edge Cases That Break It

Immich works on localhost and then fails behind nginx or Traefik — large uploads rejected, WebSockets dead, the app convinced it lives on the wrong URL. The Immich-specific fixes.

Immich Behind a Reverse Proxy: The App-Specific Edge Cases That Break It

Immich is one of those apps that runs perfectly on localhost:2283 and then falls apart the moment you put it behind a reverse proxy. The symptoms are specific and repeatable: uploading a video fails at a certain size, the timeline won't live-update, the mobile app can't log in, or Immich keeps generating links to the wrong host. None of these are reverse-proxy bugs in general — they're the handful of things Immich in particular needs the proxy to get right. The generic guidance in reverse proxy at the edge vs end-to-end TLS still applies; this is the Immich-specific layer on top.

Edge case 1: large uploads rejected

Phone videos are big, and proxies cap request bodies by default. nginx returns 413 Request Entity Too Large at 1 MB until you raise it:

client_max_body_size 50000M;

On Traefik there's no body cap by default, but if you've set maxRequestBodyBytes anywhere, raise it. This single setting is the most common "Immich uploads fail" cause.

Edge case 2: WebSockets and the live timeline

Immich uses WebSockets for live updates and job status. A proxy that doesn't forward the Upgrade/Connection headers leaves the UI looking frozen. For nginx:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Traefik handles WebSocket upgrades automatically, so if live updates fail there, suspect a timeout cutting the long-lived connection rather than the upgrade itself.

Edge case 3: timeouts on long operations

Thumbnail generation, large uploads, and ML jobs hold connections open. A 60-second proxy read timeout cuts them off mid-flight. Raise proxy_read_timeout/proxy_send_timeout on the Immich route specifically — not globally — the same targeted-timeout principle that self-hosted AI apps need.

Edge case 4: Immich thinks it's on the wrong URL

Immich builds share links and redirects from the host it believes it's serving. Behind a proxy that means forwarding the real host and scheme:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;

Miss X-Forwarded-Proto and Immich generates http:// links on an HTTPS site — mixed-content failures and broken shares.

Edge case 5: TLS and certificate renewal

Immich over HTTPS is table stakes, but a cert that silently fails to renew breaks the mobile app days later with a confusing error. Make sure renewal actually reloads the proxy — the exact trap in Let's Encrypt renew-and-reload behind a Docker proxy.

The full Immich proxy checklist

Skip the hand-wiring

Every edge case above is a setting that a managed deployment can set for you. Bringing Immich up from a template wires the proxy, TLS, and headers together instead of leaving you to rediscover client_max_body_size at 2am.

ServerCompass selecting the Immich template before deploying Deploying Immich with its reverse proxy and TLS configured together in ServerCompass — the edge cases above are handled before the first upload.

Get these five settings right and Immich behind a proxy is rock solid. Get any one wrong and you'll chase a different confusing symptom for each.

From across the StoicSoft network

Hand-curated reads on the same topic from sister sites in the StoicSoft family.