diff --git a/docker/.env.example b/docker/.env.example
index 7b398969..a594f9c0 100644
--- a/docker/.env.example
+++ b/docker/.env.example
@@ -67,3 +67,14 @@ JWT_SECRET=
 # For example PUBLIC_LOGIN_PAGE_MESSAGE="This is a demo instance of Immich.
Email: demo@demo.de
Password: demo"
 
 PUBLIC_LOGIN_PAGE_MESSAGE=
+
+####################################################################################
+# Alternative Service Addresses - Optional
+####################################################################################
+
+# This is an advanced feature for users who may be running their immich services on different hosts. It will not change which address or port that services bind to within their containers, but it will change where other services look for their peers.
+# Note: immich-microservices is bound to 3002, but no references are made
+
+# IMMICH_WEB_URL=http://immich-web:3000
+# IMMICH_SERVER_URL=http://immich-server:3001
+# IMMICH_MACHINE_LEARNING_URL=http://immich-machine-learning:3003
diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml
index 04ef4dbb..f2a00011 100644
--- a/docker/docker-compose.dev.yml
+++ b/docker/docker-compose.dev.yml
@@ -68,6 +68,9 @@ services:
     command: npm run dev --host
     env_file:
       - .env
+    environment:
+      # Rename these values for svelte public interface
+      - PUBLIC_IMMICH_SERVER_URL=${IMMICH_SERVER_URL}
     ports:
       - 3000:3000
       - 24678:24678
@@ -100,6 +103,10 @@ services:
   immich-proxy:
     container_name: immich_proxy
     image: immich-proxy-dev:latest
+    environment:
+      # Make sure these values get passed through from the env file
+      - IMMICH_SERVER_URL
+      - IMMICH_WEB_URL
     build:
       context: ../nginx
       dockerfile: Dockerfile
diff --git a/docker/docker-compose.staging.yml b/docker/docker-compose.staging.yml
index 1d45f7e4..bc35495c 100644
--- a/docker/docker-compose.staging.yml
+++ b/docker/docker-compose.staging.yml
@@ -47,6 +47,9 @@ services:
     entrypoint: ["/bin/sh", "./entrypoint.sh"]
     env_file:
       - .env
+    environment:
+      # Rename these values for svelte public interface
+      - PUBLIC_IMMICH_SERVER_URL=${IMMICH_SERVER_URL}
     restart: always
 
   redis:
@@ -71,6 +74,10 @@ services:
   immich-proxy:
     container_name: immich_proxy
     image: altran1502/immich-proxy:staging
+    environment:
+      # Make sure these values get passed through from the env file
+      - IMMICH_SERVER_URL
+      - IMMICH_WEB_URL
     ports:
       - 2283:8080
     logging:
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 87bcb958..3e4309a4 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -47,6 +47,9 @@ services:
     entrypoint: ["/bin/sh", "./entrypoint.sh"]
     env_file:
       - .env
+    environment:
+      # Rename these values for svelte public interface
+      - PUBLIC_IMMICH_SERVER_URL=${IMMICH_SERVER_URL}
     restart: always
 
   redis:
@@ -71,6 +74,10 @@ services:
   immich-proxy:
     container_name: immich_proxy
     image: altran1502/immich-proxy:release
+    environment:
+      # Make sure these values get passed through from the env file
+      - IMMICH_SERVER_URL
+      - IMMICH_WEB_URL
     ports:
       - 2283:8080
     logging:
diff --git a/nginx/Dockerfile b/nginx/Dockerfile
index ef3a9a26..efbd0e1d 100644
--- a/nginx/Dockerfile
+++ b/nginx/Dockerfile
@@ -3,6 +3,7 @@ FROM docker.io/nginxinc/nginx-unprivileged:latest
 COPY LICENSE /licenses/LICENSE.txt
 COPY LICENSE /LICENSE
 
-COPY nginx.conf "/etc/nginx/nginx.conf"
+COPY nginx.conf "/etc/nginx/nginx.conf.template"
+COPY start.sh /start.sh
 
-CMD nginx -g "daemon off;"
\ No newline at end of file
+CMD /start.sh
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
index 511d4ade..ecc9ae68 100644
--- a/nginx/nginx.conf
+++ b/nginx/nginx.conf
@@ -1,5 +1,4 @@
-
-
+# NOTE: This file is generated on startup. See /start.sh
 worker_processes auto;
 error_log /var/log/nginx/error.log;
 pid /tmp/nginx.pid;
@@ -62,7 +61,7 @@ http {
 
       rewrite /api/(.*) /$1 break;
 
-      proxy_pass http://immich-server:3001;
+      proxy_pass $IMMICH_SERVER_URL;
     }
 
     location / {
@@ -87,7 +86,7 @@ http {
       proxy_set_header Connection "upgrade";
       proxy_set_header Host $host;
 
-      proxy_pass http://immich-web:3000;
+      proxy_pass $IMMICH_WEB_URL;
     }
   }
-}
\ No newline at end of file
+}
diff --git a/nginx/start.sh b/nginx/start.sh
new file mode 100755
index 00000000..a5c50f97
--- /dev/null
+++ b/nginx/start.sh
@@ -0,0 +1,9 @@
+#! /bin/bash
+set -e
+
+export IMMICH_WEB_URL=${IMMICH_WEB_URL:-http://immich-web:3000}
+export IMMICH_SERVER_URL=${IMMICH_SERVER_URL:-http://immich-server:3001}
+
+envsubst '$IMMICH_WEB_URL $IMMICH_SERVER_URL' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
+
+exec nginx -g 'daemon off;'
diff --git a/server/apps/microservices/src/processors/machine-learning.processor.ts b/server/apps/microservices/src/processors/machine-learning.processor.ts
index 39c92fd9..6ce5789b 100644
--- a/server/apps/microservices/src/processors/machine-learning.processor.ts
+++ b/server/apps/microservices/src/processors/machine-learning.processor.ts
@@ -9,6 +9,8 @@ import axios from 'axios';
 import { Job } from 'bull';
 import { Repository } from 'typeorm';
 
+const immich_machine_learning_url = process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003';
+
 @Processor(QueueNameEnum.MACHINE_LEARNING)
 export class MachineLearningProcessor {
   constructor(
@@ -20,9 +22,12 @@ export class MachineLearningProcessor {
   async tagImage(job: Job) {
     const { asset } = job.data;
 
-    const res = await axios.post('http://immich-machine-learning:3003/image-classifier/tag-image', {
-      thumbnailPath: asset.resizePath,
-    });
+    const res = await axios.post(
+      immich_machine_learning_url + '/image-classifier/tag-image',
+      {
+        thumbnailPath: asset.resizePath,
+      },
+    );
 
     if (res.status == 201 && res.data.length > 0) {
       const smartInfo = new SmartInfoEntity();
@@ -40,9 +45,12 @@ export class MachineLearningProcessor {
     try {
       const { asset }: { asset: AssetEntity } = job.data;
 
-      const res = await axios.post('http://immich-machine-learning:3003/object-detection/detect-object', {
-        thumbnailPath: asset.resizePath,
-      });
+      const res = await axios.post(
+        immich_machine_learning_url + '/object-detection/detect-object',
+        {
+          thumbnailPath: asset.resizePath,
+        },
+      );
 
       if (res.status == 201 && res.data.length > 0) {
         const smartInfo = new SmartInfoEntity();
diff --git a/web/src/api/api.ts b/web/src/api/api.ts
index b621c649..237a47c7 100644
--- a/web/src/api/api.ts
+++ b/web/src/api/api.ts
@@ -1,3 +1,4 @@
+import { env } from '$env/dynamic/public';
 import {
 	AlbumApi,
 	AssetApi,
@@ -45,4 +46,5 @@ class ImmichApi {
 
 export const api = new ImmichApi();
 export const serverApi = new ImmichApi();
-serverApi.setBaseUrl('http://immich-server:3001');
+const immich_server_url = env.PUBLIC_IMMICH_SERVER_URL || 'http://immich-server:3001';
+serverApi.setBaseUrl(immich_server_url);