diff --git a/docs/docs/install/environment-variables.md b/docs/docs/install/environment-variables.md
index 4f09818d8f..5cbef2cbf1 100644
--- a/docs/docs/install/environment-variables.md
+++ b/docs/docs/install/environment-variables.md
@@ -50,6 +50,7 @@ Regardless of filesystem, it is not recommended to use a network share for your
 | `IMMICH_API_METRICS_PORT`           | Port for the OTEL metrics                           |            `8081`            | server                   | api                |
 | `IMMICH_MICROSERVICES_METRICS_PORT` | Port for the OTEL metrics                           |            `8082`            | server                   | microservices      |
 | `IMMICH_PROCESS_INVALID_IMAGES`     | When `true`, generate thumbnails for invalid images |                              | server                   | microservices      |
+| `IMMICH_TRUSTED_PROXIES`            | List of comma separated IPs set as trusted proxies  |                              | server                   | api                |
 
 \*1: With the default `WORKDIR` of `/usr/src/app`, this path will resolve to `/usr/src/app/upload`.
 It only need to be set if the Immich deployment method is changing.
diff --git a/server/src/config.ts b/server/src/config.ts
index c7d16826bf..96ce63cf45 100644
--- a/server/src/config.ts
+++ b/server/src/config.ts
@@ -4,7 +4,7 @@ import { CronExpression } from '@nestjs/schedule';
 import { QueueOptions } from 'bullmq';
 import { Request, Response } from 'express';
 import { RedisOptions } from 'ioredis';
-import Joi from 'joi';
+import Joi, { Root } from 'joi';
 import { CLS_ID, ClsModuleOptions } from 'nestjs-cls';
 import { ImmichHeader } from 'src/dtos/auth.dto';
 import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface';
@@ -388,6 +388,20 @@ export const immichAppConfig: ConfigModuleOptions = {
     IMMICH_API_METRICS_PORT: Joi.number().optional(),
     IMMICH_MICROSERVICES_METRICS_PORT: Joi.number().optional(),
 
+    IMMICH_TRUSTED_PROXIES: Joi.extend((joi: Root) => ({
+      type: 'stringArray',
+      base: joi.array(),
+      coerce: (value) => (value.split ? value.split(',') : value),
+    }))
+      .stringArray()
+      .single()
+      .items(
+        Joi.string().ip({
+          version: ['ipv4', 'ipv6'],
+          cidr: 'optional',
+        }),
+      ),
+
     IMMICH_METRICS: Joi.boolean().optional().default(false),
     IMMICH_HOST_METRICS: Joi.boolean().optional().default(false),
     IMMICH_API_METRICS: Joi.boolean().optional().default(false),
diff --git a/server/src/workers/api.ts b/server/src/workers/api.ts
index 8166665515..5857f587a0 100644
--- a/server/src/workers/api.ts
+++ b/server/src/workers/api.ts
@@ -14,9 +14,18 @@ import { useSwagger } from 'src/utils/misc';
 
 const host = process.env.HOST;
 
+function parseTrustedProxy(input?: string) {
+  if (!input) {
+    return [];
+  }
+  // Split on ',' char to allow multiple IPs
+  return input.split(',');
+}
+
 async function bootstrap() {
   process.title = 'immich-api';
   const otelPort = Number.parseInt(process.env.IMMICH_API_METRICS_PORT ?? '8081');
+  const trustedProxies = parseTrustedProxy(process.env.IMMICH_TRUSTED_PROXIES ?? '');
 
   otelStart(otelPort);
 
@@ -27,7 +36,7 @@ async function bootstrap() {
   logger.setAppName('Api');
   logger.setContext('Bootstrap');
   app.useLogger(logger);
-  app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']);
+  app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal', ...trustedProxies]);
   app.set('etag', 'strong');
   app.use(cookieParser());
   app.use(json({ limit: '10mb' }));