diff --git a/e2e/src/web/specs/auth.e2e-spec.ts b/e2e/src/web/specs/auth.e2e-spec.ts
index b616a365cf..e89f17a4e9 100644
--- a/e2e/src/web/specs/auth.e2e-spec.ts
+++ b/e2e/src/web/specs/auth.e2e-spec.ts
@@ -33,6 +33,7 @@ test.describe('Registration', () => {
     // onboarding
     await expect(page).toHaveURL('/auth/onboarding');
     await page.getByRole('button', { name: 'Theme' }).click();
+    await page.getByRole('button', { name: 'Privacy' }).click();
     await page.getByRole('button', { name: 'Storage Template' }).click();
     await page.getByRole('button', { name: 'Done' }).click();
 
diff --git a/web/src/lib/components/admin-page/settings/admin-settings.svelte b/web/src/lib/components/admin-page/settings/admin-settings.svelte
index 55750a9737..21e70df950 100644
--- a/web/src/lib/components/admin-page/settings/admin-settings.svelte
+++ b/web/src/lib/components/admin-page/settings/admin-settings.svelte
@@ -8,7 +8,7 @@
   import { handleError } from '$lib/utils/handle-error';
   import { getConfig, getConfigDefaults, updateConfig, type SystemConfigDto } from '@immich/sdk';
   import { loadConfig } from '$lib/stores/server-config.store';
-  import { cloneDeep } from 'lodash-es';
+  import { cloneDeep, isEqual } from 'lodash-es';
   import { onMount } from 'svelte';
   import type { SettingsResetOptions } from './admin-settings';
   import { t } from 'svelte-i18n';
@@ -23,12 +23,16 @@
   };
 
   export const handleSave = async (update: Partial<SystemConfigDto>) => {
+    let systemConfigDto = {
+      ...savedConfig,
+      ...update,
+    };
+    if (isEqual(systemConfigDto, savedConfig)) {
+      return;
+    }
     try {
       const newConfig = await updateConfig({
-        systemConfigDto: {
-          ...savedConfig,
-          ...update,
-        },
+        systemConfigDto,
       });
 
       config = cloneDeep(newConfig);
diff --git a/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte b/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte
index 74cbe2d9a1..7c2c5c856a 100644
--- a/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte
+++ b/web/src/lib/components/admin-page/settings/map-settings/map-settings.svelte
@@ -26,7 +26,12 @@
       <div class="flex flex-col gap-4">
         <SettingAccordion key="map" title={$t('admin.map_settings')} subtitle={$t('admin.map_settings_description')}>
           <div class="ml-4 mt-4 flex flex-col gap-4">
-            <SettingSwitch title={$t('admin.map_enable_description')} {disabled} bind:checked={config.map.enabled} />
+            <SettingSwitch
+              title={$t('admin.map_enable_description')}
+              subtitle={$t('admin.map_implications')}
+              {disabled}
+              bind:checked={config.map.enabled}
+            />
 
             <hr />
 
diff --git a/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte b/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte
index 4ef4804c3f..76c238df82 100644
--- a/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte
+++ b/web/src/lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte
@@ -21,6 +21,7 @@
       <div class="ml-4 mt-4">
         <SettingSwitch
           title={$t('admin.version_check_enabled_description')}
+          subtitle={$t('admin.version_check_implications')}
           bind:checked={config.newVersionCheck.enabled}
           {disabled}
         />
diff --git a/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte b/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte
index 1d0cec3296..4ebf4ed118 100644
--- a/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte
+++ b/web/src/lib/components/admin-page/settings/storage-template/storage-template-settings.svelte
@@ -29,6 +29,7 @@
   export let minified = false;
   export let onReset: SettingsResetEvent;
   export let onSave: SettingsSaveEvent;
+  export let duration: number = 500;
 
   let templateOptions: SystemConfigTemplateStorageOptionDto;
   let selectedPreset = '';
@@ -87,7 +88,7 @@
 </script>
 
 <section class="dark:text-immich-dark-fg mt-2">
-  <div in:fade={{ duration: 500 }} class="mx-4 flex flex-col gap-4 py-4">
+  <div in:fade={{ duration }} class="mx-4 flex flex-col gap-4 py-4">
     <p class="text-sm dark:text-immich-dark-fg">
       <FormatMessage key="admin.storage_template_more_details" let:tag let:message>
         {#if tag === 'template-link'}
diff --git a/web/src/lib/components/onboarding-page/onboarding-card.svelte b/web/src/lib/components/onboarding-page/onboarding-card.svelte
index 8b2da48bb9..9b2378ccd8 100644
--- a/web/src/lib/components/onboarding-page/onboarding-card.svelte
+++ b/web/src/lib/components/onboarding-page/onboarding-card.svelte
@@ -1,11 +1,27 @@
 <script lang="ts">
+  import Icon from '$lib/components/elements/icon.svelte';
   import { fade } from 'svelte/transition';
+
+  export let title: string | undefined = undefined;
+  export let icon: string | undefined = undefined;
 </script>
 
 <div
   id="onboarding-card"
-  class="flex w-full max-w-4xl flex-col gap-4 rounded-3xl border-2 border-gray-500 px-8 py-14 dark:border-immich-dark-gray dark:bg-immich-dark-gray text-black dark:text-immich-dark-fg bg-gray-50"
+  class="flex w-full max-w-4xl flex-col gap-4 rounded-3xl border-2 border-gray-500 px-8 py-8 dark:border-immich-dark-gray dark:bg-immich-dark-gray text-black dark:text-immich-dark-fg bg-gray-50"
   in:fade={{ duration: 250 }}
 >
+  {#if title || icon}
+    <div class="flex gap-2 items-center justify-center w-fit">
+      {#if icon}
+        <Icon path={icon} size="30" class="text-immich-primary dark:text-immich-dark-primary" />
+      {/if}
+      {#if title}
+        <p class="text-xl text-immich-primary dark:text-immich-dark-primary">
+          {title.toUpperCase()}
+        </p>
+      {/if}
+    </div>
+  {/if}
   <slot />
 </div>
diff --git a/web/src/lib/components/onboarding-page/onboarding-hello.svelte b/web/src/lib/components/onboarding-page/onboarding-hello.svelte
index c2d318ccda..466e1d29f7 100644
--- a/web/src/lib/components/onboarding-page/onboarding-hello.svelte
+++ b/web/src/lib/components/onboarding-page/onboarding-hello.svelte
@@ -3,14 +3,11 @@
   import Button from '$lib/components/elements/buttons/button.svelte';
   import { mdiArrowRight } from '@mdi/js';
   import Icon from '$lib/components/elements/icon.svelte';
-  import { createEventDispatcher } from 'svelte';
-  import ImmichLogo from '../shared-components/immich-logo.svelte';
+  import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
   import { user } from '$lib/stores/user.store';
   import { t } from 'svelte-i18n';
 
-  const dispatch = createEventDispatcher<{
-    done: void;
-  }>();
+  export let onDone: () => void;
 </script>
 
 <OnboardingCard>
@@ -21,7 +18,7 @@
   <p class="text-3xl pb-6 font-light">{$t('onboarding_welcome_description')}</p>
 
   <div class="w-full flex place-content-end">
-    <Button class="flex gap-2 place-content-center" on:click={() => dispatch('done')}>
+    <Button class="flex gap-2 place-content-center" on:click={() => onDone()}>
       <p>{$t('theme')}</p>
       <Icon path={mdiArrowRight} size="18" />
     </Button>
diff --git a/web/src/lib/components/onboarding-page/onboarding-privacy.svelte b/web/src/lib/components/onboarding-page/onboarding-privacy.svelte
new file mode 100644
index 0000000000..da36f741f1
--- /dev/null
+++ b/web/src/lib/components/onboarding-page/onboarding-privacy.svelte
@@ -0,0 +1,63 @@
+<script lang="ts">
+  import { user } from '$lib/stores/user.store';
+  import { getConfig, type SystemConfigDto } from '@immich/sdk';
+  import { mdiArrowLeft, mdiArrowRight, mdiIncognito } from '@mdi/js';
+  import { onMount } from 'svelte';
+  import AdminSettings from '$lib/components/admin-page/settings/admin-settings.svelte';
+  import Button from '$lib/components/elements/buttons/button.svelte';
+  import Icon from '$lib/components/elements/icon.svelte';
+  import OnboardingCard from './onboarding-card.svelte';
+  import { t } from 'svelte-i18n';
+  import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
+
+  export let onDone: () => void;
+  export let onPrevious: () => void;
+
+  let config: SystemConfigDto | null = null;
+
+  onMount(async () => {
+    config = await getConfig();
+  });
+</script>
+
+<OnboardingCard title={$t('privacy')} icon={mdiIncognito}>
+  <p>
+    {$t('onboarding_privacy_description')}
+  </p>
+
+  {#if config && $user}
+    <AdminSettings bind:config let:handleSave>
+      <SettingSwitch
+        title={$t('admin.map_settings')}
+        subtitle={$t('admin.map_implications')}
+        bind:checked={config.map.enabled}
+      />
+      <SettingSwitch
+        title={$t('admin.version_check_settings')}
+        subtitle={$t('admin.version_check_implications')}
+        bind:checked={config.newVersionCheck.enabled}
+      />
+      <div class="flex pt-4">
+        <div class="w-full flex place-content-start">
+          <Button class="flex gap-2 place-content-center" on:click={() => onPrevious()}>
+            <Icon path={mdiArrowLeft} size="18" />
+            <p>{$t('theme')}</p>
+          </Button>
+        </div>
+        <div class="flex w-full place-content-end">
+          <Button
+            on:click={() => {
+              handleSave({ map: config?.map, newVersionCheck: config?.newVersionCheck });
+              onDone();
+            }}
+          >
+            <span class="flex place-content-center place-items-center gap-2">
+              {$t('admin.storage_template_settings')}
+              <Icon path={mdiArrowRight} size="18" />
+            </span>
+          </Button>
+        </div>
+      </div>
+    </AdminSettings>
+  {/if}
+</OnboardingCard>
diff --git a/web/src/lib/components/onboarding-page/onboarding-storage-template.svelte b/web/src/lib/components/onboarding-page/onboarding-storage-template.svelte
index 096417d72a..69809dd39d 100644
--- a/web/src/lib/components/onboarding-page/onboarding-storage-template.svelte
+++ b/web/src/lib/components/onboarding-page/onboarding-storage-template.svelte
@@ -2,20 +2,18 @@
   import { featureFlags } from '$lib/stores/server-config.store';
   import { user } from '$lib/stores/user.store';
   import { getConfig, type SystemConfigDto } from '@immich/sdk';
-  import { mdiArrowLeft, mdiCheck } from '@mdi/js';
-  import { createEventDispatcher, onMount } from 'svelte';
-  import AdminSettings from '../admin-page/settings/admin-settings.svelte';
-  import StorageTemplateSettings from '../admin-page/settings/storage-template/storage-template-settings.svelte';
-  import Button from '../elements/buttons/button.svelte';
-  import Icon from '../elements/icon.svelte';
+  import { mdiArrowLeft, mdiCheck, mdiHarddisk } from '@mdi/js';
+  import { onMount } from 'svelte';
+  import AdminSettings from '$lib/components/admin-page/settings/admin-settings.svelte';
+  import StorageTemplateSettings from '$lib/components/admin-page/settings/storage-template/storage-template-settings.svelte';
+  import Button from '$lib/components/elements/buttons/button.svelte';
+  import Icon from '$lib/components/elements/icon.svelte';
   import OnboardingCard from './onboarding-card.svelte';
   import { t } from 'svelte-i18n';
   import FormatMessage from '$lib/components/i18n/format-message.svelte';
 
-  const dispatch = createEventDispatcher<{
-    done: void;
-    previous: void;
-  }>();
+  export let onDone: () => void;
+  export let onPrevious: () => void;
 
   let config: SystemConfigDto | null = null;
 
@@ -24,11 +22,7 @@
   });
 </script>
 
-<OnboardingCard>
-  <p class="text-xl text-immich-primary dark:text-immich-dark-primary">
-    {$t('admin.storage_template_settings').toUpperCase()}
-  </p>
-
+<OnboardingCard title={$t('admin.storage_template_settings')} icon={mdiHarddisk}>
   <p>
     <FormatMessage key="admin.storage_template_onboarding_description" let:message>
       <a class="underline" href="https://immich.app/docs/administration/storage-template">{message}</a>
@@ -45,10 +39,11 @@
         {savedConfig}
         onSave={(config) => handleSave(config)}
         onReset={(options) => handleReset(options)}
+        duration={0}
       >
         <div class="flex pt-4">
           <div class="w-full flex place-content-start">
-            <Button class="flex gap-2 place-content-center" on:click={() => dispatch('previous')}>
+            <Button class="flex gap-2 place-content-center" on:click={() => onPrevious()}>
               <Icon path={mdiArrowLeft} size="18" />
               <p>{$t('theme')}</p>
             </Button>
@@ -57,7 +52,7 @@
             <Button
               on:click={() => {
                 handleSave({ storageTemplate: config?.storageTemplate });
-                dispatch('done');
+                onDone();
               }}
             >
               <span class="flex place-content-center place-items-center gap-2">
diff --git a/web/src/lib/components/onboarding-page/onboarding-theme.svelte b/web/src/lib/components/onboarding-page/onboarding-theme.svelte
index ff15b8b64a..975dbd1ec3 100644
--- a/web/src/lib/components/onboarding-page/onboarding-theme.svelte
+++ b/web/src/lib/components/onboarding-page/onboarding-theme.svelte
@@ -1,23 +1,17 @@
 <script lang="ts">
-  import { mdiArrowRight } from '@mdi/js';
-  import Button from '../elements/buttons/button.svelte';
-  import Icon from '../elements/icon.svelte';
+  import { mdiArrowRight, mdiThemeLightDark } from '@mdi/js';
+  import Button from '$lib/components/elements/buttons/button.svelte';
+  import Icon from '$lib/components/elements/icon.svelte';
   import OnboardingCard from './onboarding-card.svelte';
-  import { createEventDispatcher } from 'svelte';
   import { colorTheme } from '$lib/stores/preferences.store';
   import { moonPath, moonViewBox, sunPath, sunViewBox } from '$lib/assets/svg-paths';
   import { Theme } from '$lib/constants';
   import { t } from 'svelte-i18n';
 
-  const dispatch = createEventDispatcher<{
-    done: void;
-    previous: void;
-  }>();
+  export let onDone: () => void;
 </script>
 
-<OnboardingCard>
-  <p class="text-xl text-immich-primary dark:text-immich-dark-primary">{$t('color_theme').toUpperCase()}</p>
-
+<OnboardingCard icon={mdiThemeLightDark} title={$t('color_theme')}>
   <div>
     <p class="pb-6 font-light">{$t('onboarding_theme_description')}</p>
   </div>
@@ -51,8 +45,8 @@
 
   <div class="flex">
     <div class="w-full flex place-content-end">
-      <Button class="flex gap-2 place-content-center" on:click={() => dispatch('done')}>
-        <p>{$t('admin.storage_template_settings')}</p>
+      <Button class="flex gap-2 place-content-center" on:click={() => onDone()}>
+        <p>{$t('privacy')}</p>
         <Icon path={mdiArrowRight} size="18" />
       </Button>
     </div>
diff --git a/web/src/lib/i18n/en.json b/web/src/lib/i18n/en.json
index 6796ae3a71..eaf5ffc1a4 100644
--- a/web/src/lib/i18n/en.json
+++ b/web/src/lib/i18n/en.json
@@ -127,12 +127,13 @@
     "map_enable_description": "Enable map features",
     "map_gps_settings": "Map & GPS Settings",
     "map_gps_settings_description": "Manage Map & GPS (Reverse Geocoding) Settings",
+    "map_implications": "The map feature relies on an external tile service (tiles.immich.cloud)",
     "map_light_style": "Light style",
     "map_manage_reverse_geocoding_settings": "Manage <link>Reverse Geocoding</link> settings",
     "map_reverse_geocoding": "Reverse Geocoding",
     "map_reverse_geocoding_enable_description": "Enable reverse geocoding",
     "map_reverse_geocoding_settings": "Reverse Geocoding Settings",
-    "map_settings": "Map Settings",
+    "map_settings": "Map",
     "map_settings_description": "Manage map settings",
     "map_style_description": "URL to a style.json map theme",
     "metadata_extraction_job": "Extract metadata",
@@ -317,7 +318,8 @@
     "user_settings": "User Settings",
     "user_settings_description": "Manage user settings",
     "user_successfully_removed": "User {email} has been successfully removed.",
-    "version_check_enabled_description": "Enable periodic requests to GitHub to check for new releases",
+    "version_check_enabled_description": "Enable version check",
+    "version_check_implications": "The version check feature relies on periodic communication with github.com",
     "version_check_settings": "Version Check",
     "version_check_settings_description": "Enable/disable the new version notification",
     "video_conversion_job": "Transcode videos",
@@ -850,6 +852,7 @@
   "ok": "Ok",
   "oldest_first": "Oldest first",
   "onboarding": "Onboarding",
+  "onboarding_privacy_description": "The following (optional) features rely on external services, and can by disabled at any time in the administration settings.",
   "onboarding_theme_description": "Choose a color theme for your instance. You can change this later in your settings.",
   "onboarding_welcome_description": "Let's get your instance set up with some common settings.",
   "onboarding_welcome_user": "Welcome, {user}",
@@ -920,6 +923,7 @@
   "previous_memory": "Previous memory",
   "previous_or_next_photo": "Previous or next photo",
   "primary": "Primary",
+  "privacy": "Privacy",
   "profile_image_of_user": "Profile image of {user}",
   "profile_picture_set": "Profile picture set.",
   "public_album": "Public album",
diff --git a/web/src/routes/auth/onboarding/+page.svelte b/web/src/routes/auth/onboarding/+page.svelte
index 4647ad8bde..0fe2c68c84 100644
--- a/web/src/routes/auth/onboarding/+page.svelte
+++ b/web/src/routes/auth/onboarding/+page.svelte
@@ -2,6 +2,7 @@
   import { goto } from '$app/navigation';
   import { page } from '$app/stores';
   import OnboardingHello from '$lib/components/onboarding-page/onboarding-hello.svelte';
+  import OnboardingPrivacy from '$lib/components/onboarding-page/onboarding-privacy.svelte';
   import OnboadingStorageTemplate from '$lib/components/onboarding-page/onboarding-storage-template.svelte';
   import OnboardingTheme from '$lib/components/onboarding-page/onboarding-theme.svelte';
   import { AppRoute, QueryParameter } from '$lib/constants';
@@ -11,12 +12,17 @@
 
   interface OnboardingStep {
     name: string;
-    component: typeof OnboardingHello | typeof OnboardingTheme | typeof OnboadingStorageTemplate;
+    component:
+      | typeof OnboardingHello
+      | typeof OnboardingTheme
+      | typeof OnboadingStorageTemplate
+      | typeof OnboardingPrivacy;
   }
 
   const onboardingSteps: OnboardingStep[] = [
     { name: 'hello', component: OnboardingHello },
     { name: 'theme', component: OnboardingTheme },
+    { name: 'privacy', component: OnboardingPrivacy },
     { name: 'storage', component: OnboadingStorageTemplate },
   ];
 
@@ -55,8 +61,8 @@
     <div class="w-full min-w-screen py-8 flex h-full place-content-center place-items-center">
       <svelte:component
         this={onboardingSteps[index].component}
-        on:done={handleDoneClicked}
-        on:previous={handlePrevious}
+        onDone={handleDoneClicked}
+        onPrevious={handlePrevious}
       />
     </div>
   </div>