diff --git a/app/controllers/base_action_controller.rb b/app/controllers/base_action_controller.rb
index 05ba00426c27898c9d33bcf2c34aa9c7cfdc798e..e251c44f63d13da347ee0b44d98390a61994dec0 100644
--- a/app/controllers/base_action_controller.rb
+++ b/app/controllers/base_action_controller.rb
@@ -26,9 +26,8 @@ class BaseActionController < ActionController::Base
     next if p.directives.blank?
 
     if helpers.vite_enabled?
-      vite_host = ViteRuby.instance.config.host
       vite_port = ViteRuby.instance.config.port
-      vite_origin = "#{vite_host}:#{vite_port}"
+      vite_origin = "#{Gitlab.config.gitlab.host}:#{vite_port}"
       http_origin = "http://#{vite_origin}"
       ws_origin = "ws://#{vite_origin}"
       wss_origin = "wss://#{vite_origin}"
diff --git a/lib/vite_gdk.rb b/lib/vite_gdk.rb
index 650a111399a62fdd741a0694aec9af497af4c2ca..f50c6cab5159ec46076735088b2db8817b166a8a 100644
--- a/lib/vite_gdk.rb
+++ b/lib/vite_gdk.rb
@@ -15,6 +15,7 @@ def self.load_gdk_vite_config
     return unless enabled
 
     ViteRuby.configure(
+      host: config.fetch('host', 'localhost'),
       port: Integer(config.fetch('port', 3038))
     )
   end
diff --git a/spec/lib/vite_gdk_spec.rb b/spec/lib/vite_gdk_spec.rb
index 2e21e77881dfba3bb0a3844404feeef142520fe3..f54ede9d877d3eec217c0f1f3dfe0a7f983139fd 100644
--- a/spec/lib/vite_gdk_spec.rb
+++ b/spec/lib/vite_gdk_spec.rb
@@ -24,8 +24,8 @@
           end.and_return(true)
           expect(YAML).to receive(:safe_load_file) do |file_path|
             expect(file_path).to end_with(VITE_GDK_CONFIG_FILEPATH)
-          end.and_return('enabled' => true, 'port' => 3038)
-          expect(ViteRuby).to receive(:configure).with(port: 3038)
+          end.and_return('enabled' => true, 'port' => 3038, 'host' => 'gdk.test')
+          expect(ViteRuby).to receive(:configure).with(host: 'gdk.test', port: 3038)
           expect(ViteRuby.env).to receive(:[]=).with('VITE_ENABLED', 'true')
 
           described_class.load_gdk_vite_config
diff --git a/vite.config.js b/vite.config.js
index b70478abe96779de5234c233f171f8f0db9748cc..5597a6087d1fdf6943e9f23a590d5813b55e53e8 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -1,4 +1,6 @@
-import path from 'path';
+import { readFileSync } from 'node:fs';
+import path from 'node:path';
+
 import { defineConfig } from 'vite';
 import vue from '@vitejs/plugin-vue2';
 import graphql from '@rollup/plugin-graphql';
@@ -12,7 +14,15 @@ import {
   SOURCEGRAPH_PUBLIC_PATH,
   GITLAB_WEB_IDE_PUBLIC_PATH,
 } from './config/webpack.constants';
-import viteSharedConfig from './config/vite.json';
+
+let viteGDKConfig;
+try {
+  viteGDKConfig = JSON.parse(
+    readFileSync(path.resolve(__dirname, 'config/vite.gdk.json'), 'utf-8'),
+  );
+} catch {
+  viteGDKConfig = {};
+}
 
 const aliasArr = Object.entries(webpackConfig.resolve.alias).map(([find, replacement]) => ({
   find: find.includes('$') ? new RegExp(find) : find,
@@ -94,8 +104,7 @@ export default defineConfig({
     ],
   },
   plugins: [
-    // VITE_ENABLED is present when running with GDK
-    process.env.VITE_ENABLED ? autoRestartPlugin : null,
+    viteGDKConfig.enabled ? autoRestartPlugin : null,
     fixedRubyPlugin,
     vue({
       template: {
@@ -122,11 +131,17 @@ export default defineConfig({
     'process.env.GITLAB_WEB_IDE_PUBLIC_PATH': JSON.stringify(GITLAB_WEB_IDE_PUBLIC_PATH),
   },
   server: {
-    hmr: {
-      host: viteSharedConfig?.development?.host || 'localhost',
-      // ensure we stay compatible with HTTPS enabled for GDK
-      protocol: 'ws',
-    },
+    hmr:
+      viteGDKConfig.hmr === undefined
+        ? /*
+        This is a legacy behavior for older GDKs. They will fallback to:
+          ws://localhost:3038/vite-dev/
+        TODO: Remove this after 2024-01-18 */
+          {
+            host: 'localhost',
+            protocol: 'ws',
+          }
+        : viteGDKConfig.hmr,
     https: false,
     watch: {
       ignored: [