From 792a87e407d8fd8b6bb3075a5fba9aa1b7275f6c Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Wed, 22 Mar 2023 21:46:30 +0100 Subject: [PATCH] fix(nginx): x-forwarded-* headers (#2019) * fix(nginx): x-forwarded-* headers * change category / add link to nginx config --- docs/docs/administration/reverse-proxy.md | 22 ++++++++++++++++++++++ nginx/templates/default.conf.template | 22 ++++++++++++++-------- server/apps/immich/src/main.ts | 2 +- web/entrypoint.sh | 2 ++ 4 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 docs/docs/administration/reverse-proxy.md diff --git a/docs/docs/administration/reverse-proxy.md b/docs/docs/administration/reverse-proxy.md new file mode 100644 index 0000000000..dfb4f8d6b3 --- /dev/null +++ b/docs/docs/administration/reverse-proxy.md @@ -0,0 +1,22 @@ +# Reverse Proxy + +When deploying Immich it is important to understand that a reverse proxy is required in front of the server and web container. The reverse proxy acts as an intermediary between the user and container, forwarding requests to the correct container based on the URL path. + +## Default Reverse Proxy + +Immich provides a default nginx reverse proxy preconfigured to perform the correct routing and set the necessary headers for the server and web container to use. These headers are crucial to redirect to the correct URL and determine the client's IP address. + +## Using a Different Reverse Proxy + +While the reverse proxy provided by Immich works well for basic deployments, some users may want to use a different reverse proxy. Fortunately, Immich is flexible enough to accommodate different reverse proxies. Users can either: + +1. Add another reverse proxy on top of Immich's reverse proxy +2. Completely replace the default reverse proxy + +## Adding a Custom Reverse Proxy + +Users can deploy a custom reverse proxy that forwards requests to Immich's reverse proxy. This way, the new reverse proxy can handle TLS termination, load balancing, or other advanced features, while still delegating routing decisions to Immich's reverse proxy. All reverse proxies between Immich and the user must forward all headers and set the `Host`, `X-Forwarded-Host`, `X-Forwarded-Proto` and `X-Forwarded-For` headers to their appropriate values. By following these practices, you ensure that all custom reverse proxies are fully compatible with Immich. + +## Replacing the Default Reverse Proxy + +Replacing Immich's default reverse proxy is an advanced deployment and support may be limited. When replacing Immich's default proxy it is important to ensure that requests to `/api/*` are routed to the server container and all other requests to the web container. Additionally, the previously mentioned headers should be configured accordingly. You may find our [nginx configuration file](https://github.com/immich-app/immich/blob/main/nginx/templates/default.conf.template) a helpful reference. diff --git a/nginx/templates/default.conf.template b/nginx/templates/default.conf.template index 72d0a18b09..7946d8697d 100644 --- a/nginx/templates/default.conf.template +++ b/nginx/templates/default.conf.template @@ -3,6 +3,14 @@ map $http_upgrade $connection_upgrade { '' close; } +map $http_x_forwarded_proto $forwarded_protocol { + default $scheme; + + # Only allow the values 'http' and 'https' for the X-Forwarded-Proto header. + http http; + https https; +} + upstream server { server ${IMMICH_SERVER_HOST}; keepalive 2; @@ -43,13 +51,12 @@ server { proxy_force_ranges on; proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto $forwarded_protocol; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $host; rewrite /api/(.*) /$1 break; @@ -64,13 +71,12 @@ server { proxy_force_ranges on; proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto $forwarded_protocol; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $host; proxy_pass ${IMMICH_WEB_SCHEME}web; } diff --git a/server/apps/immich/src/main.ts b/server/apps/immich/src/main.ts index e97609ef31..38dd0695a0 100644 --- a/server/apps/immich/src/main.ts +++ b/server/apps/immich/src/main.ts @@ -19,7 +19,7 @@ async function bootstrap() { logger: getLogLevels(), }); - app.set('trust proxy'); + app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); app.set('etag', 'strong'); app.use(cookieParser()); app.use(json({ limit: '10mb' })); diff --git a/web/entrypoint.sh b/web/entrypoint.sh index 5f52b7b5ff..d4d84145a4 100644 --- a/web/entrypoint.sh +++ b/web/entrypoint.sh @@ -4,6 +4,8 @@ export PUBLIC_IMMICH_SERVER_URL=$IMMICH_SERVER_URL export PUBLIC_IMMICH_API_URL_EXTERNAL=$IMMICH_API_URL_EXTERNAL +export PROTOCOL_HEADER=X-Forwarded-Proto + if [ "$(id -u)" -eq 0 ] && [ -n "$PUID" ] && [ -n "$PGID" ]; then exec setpriv --reuid "$PUID" --regid "$PGID" --clear-groups node /usr/src/app/build/index.js else