Guide
7 min read

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

  • client_max_body_size raised well above your largest video.
  • WebSocket upgrade headers forwarded.
  • Read/send timeouts raised on the Immich route only.
  • Host + X-Forwarded-Proto forwarded so links use the right URL.
  • HTTPS with renewal that reloads the proxy.

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.

immich
reverse-proxy
nginx
traefik
self-hosted

From across the StoicSoft network

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

Keep reading

Guide
9 min

Intermittent 502s on a Self-Hosted VPS: It's a Stale Proxy Upstream

Apps that work for hours, then start failing 502 until you reload the proxy, almost always have a stale upstream — IP drift, DNS cache, or a dropped network attachment. Here's how to diagnose it in 60 seconds and the four fixes that eliminate the bug class.

Guide
8 min

When TLS at the Reverse Proxy Is Enough on a Single VPS (and When It Is Not)

If Nginx or Traefik terminates HTTPS on the same VPS that runs your app, internal TLS is usually unnecessary. The real question is where the trust boundary sits.

Guide
7 min

Lost HTTPS After a Network Change? A SWAG and Let's Encrypt Recovery Checklist

Immich or Jellyfin loses HTTPS after an ISP change or a simple network move, and the SWAG logs are a wall of ACME errors. A recovery checklist that starts at DNS and ends at a renewed cert.

Guide
7 min

A Safer Reverse-Proxy Decision Tree for Self-Hosted Media Apps

Should Jellyfin and Immich be public behind a reverse proxy, private over a VPN, or both? A decision tree that weighs privacy, family access, and streaming bandwidth instead of guessing.

Guide
7 min

Traefik Migrations Keep Failing at the Edge Where Cloudflare and App Routing Meet

Moving to Traefik breaks in a predictable place: the seam between Cloudflare's edge and Traefik's routing — redirect loops, wrong client IPs, and certs that won't issue. How to fix the seam.

Guide
6 min

An Easy Immich Install Path for People Who Don't Live in a Terminal

Immich's power scares off the people who'd benefit most. A gentler install path that skips the hand-edited Compose file and still lands a real, updatable, backed-up instance.