diff --git a/ci/build/build-release.sh b/ci/build/build-release.sh
index e484b251888d..8bcf823070dc 100755
--- a/ci/build/build-release.sh
+++ b/ci/build/build-release.sh
@@ -98,43 +98,6 @@ bundle_vscode() {
 
   rsync "${rsync_opts[@]}" ./lib/vscode-reh-web-*/ "$VSCODE_OUT_PATH"
 
-  # Add the commit, date, our name, links, and enable telemetry. This just makes
-  # telemetry available; telemetry can still be disabled by flag or setting.
-  jq --slurp '.[0] * .[1]' "$VSCODE_SRC_PATH/product.json" <(
-    cat << EOF
-  {
-    "enableTelemetry": true,
-    "commit": "$(cd "$VSCODE_SRC_PATH" && git rev-parse HEAD)",
-    "quality": "stable",
-    "date": $(jq -n 'now | todate'),
-    "codeServerVersion": "$VERSION",
-    "nameShort": "code-server",
-    "nameLong": "code-server",
-    "applicationName": "code-server",
-    "dataFolderName": ".code-server",
-    "win32MutexName": "codeserver",
-    "licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE",
-    "win32DirName": "code-server",
-    "win32NameVersion": "code-server",
-    "win32AppUserModelId": "coder.code-server",
-    "win32ShellNameShort": "c&ode-server",
-    "darwinBundleIdentifier": "com.coder.code.server",
-    "linuxIconName": "com.coder.code.server",
-    "reportIssueUrl": "https://github.com/coder/code-server/issues/new",
-    "documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
-    "keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
-    "keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
-    "keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
-    "introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
-    "tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
-    "newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
-    "linkProtectionTrustedDomains": [
-      "https://open-vsx.org"
-    ]
-  }
-EOF
-  ) > "$VSCODE_OUT_PATH/product.json"
-
   # Use the package.json for the web/remote server.  It does not have the right
   # version though so pull that from the main package.json.
   jq --slurp '.[0] * {version: .[1].version}' \
diff --git a/ci/build/build-vscode.sh b/ci/build/build-vscode.sh
index bb3225a2b517..71d33960fb63 100755
--- a/ci/build/build-vscode.sh
+++ b/ci/build/build-vscode.sh
@@ -9,10 +9,62 @@ MINIFY=${MINIFY-true}
 main() {
   cd "$(dirname "${0}")/../.."
 
+  source ./ci/lib.sh
+
   cd lib/vscode
 
+  # Set the commit Code will embed into the product.json.  We need to do this
+  # since Code tries to get the commit from the `.git` directory which will fail
+  # as it is a submodule.
+  export VSCODE_DISTRO_COMMIT
+  VSCODE_DISTRO_COMMIT=$(git rev-parse HEAD)
+
+  # Add the date, our name, links, and enable telemetry (this just makes
+  # telemetry available; telemetry can still be disabled by flag or setting).
+  # This needs to be done before building as Code will read this file and embed
+  # it into the client-side code.
+  git checkout product.json             # Reset in case the script exited early.
+  cp product.json product.original.json # Since jq has no inline edit.
+  jq --slurp '.[0] * .[1]' product.original.json <(
+    cat << EOF
+  {
+    "enableTelemetry": true,
+    "quality": "stable",
+    "codeServerVersion": "$VERSION",
+    "nameShort": "code-server",
+    "nameLong": "code-server",
+    "applicationName": "code-server",
+    "dataFolderName": ".code-server",
+    "win32MutexName": "codeserver",
+    "licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE",
+    "win32DirName": "code-server",
+    "win32NameVersion": "code-server",
+    "win32AppUserModelId": "coder.code-server",
+    "win32ShellNameShort": "c&ode-server",
+    "darwinBundleIdentifier": "com.coder.code.server",
+    "linuxIconName": "com.coder.code.server",
+    "reportIssueUrl": "https://github.com/coder/code-server/issues/new",
+    "documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
+    "keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
+    "keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
+    "keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
+    "introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
+    "tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
+    "newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
+    "linkProtectionTrustedDomains": [
+      "https://open-vsx.org"
+    ]
+  }
+EOF
+  ) > product.json
+
   # Any platform works since we have our own packaging step (for now).
   yarn gulp "vscode-reh-web-linux-x64${MINIFY:+-min}"
+
+  # Reset so if you develop after building you will not be stuck with the wrong
+  # commit (the dev client will use `oss-dev` but the dev server will still use
+  # product.json which will have `stable-$commit`).
+  git checkout product.json
 }
 
 main "$@"
diff --git a/lib/vscode b/lib/vscode
index dfd34e8260c2..30d9c6cd9483 160000
--- a/lib/vscode
+++ b/lib/vscode
@@ -1 +1 @@
-Subproject commit dfd34e8260c270da74b5c2d86d61aee4b6d56977
+Subproject commit 30d9c6cd9483b2cc586687151bcbcd635f373630
diff --git a/patches/base-path.diff b/patches/base-path.diff
index 95bb8388eb78..bf16984651c9 100644
--- a/patches/base-path.diff
+++ b/patches/base-path.diff
@@ -10,16 +10,14 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/base/common/network.ts
 +++ code-server/lib/vscode/src/vs/base/common/network.ts
-@@ -151,8 +151,10 @@ class RemoteAuthoritiesImpl {
- 		}
+@@ -157,7 +157,9 @@ class RemoteAuthoritiesImpl {
  		return URI.from({
  			scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
--			authority: `${host}:${port}`,
--			path: `/vscode-remote-resource`,
-+			authority: platform.isWeb ? window.location.host : `${host}:${port}`,
+ 			authority: `${host}:${port}`,
+-			path: this._remoteResourcesPath,
 +			path: platform.isWeb
-+				? URI.joinPath(URI.parse(window.location.href), `/vscode-remote-resource`).path
-+				: `/vscode-remote-resource`,
++				? (window.location.pathname + "/" + this._remoteResourcesPath).replace(/\/\/+/g, "/")
++				: this._remoteResourcesPath,
  			query
  		});
  	}
@@ -38,40 +36,28 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
  
  		<!-- Disable pinch zooming -->
  		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
-@@ -27,23 +27,26 @@
+@@ -27,9 +27,9 @@
  		<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
  
  		<!-- Workbench Icon/Manifest/CSS -->
 -		<link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
--		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
+-		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
 -		<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
 +		<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
-+		<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
++		<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
 +		<link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
  	</head>
  
  	<body aria-label="">
- 	</body>
- 
- 	<!-- Startup (do not modify order of script tags!) -->
--	<script src="./static/out/vs/loader.js"></script>
--	<script src="./static/out/vs/webPackagePaths.js"></script>
-+	<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
-+	<script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
+@@ -39,7 +39,7 @@
+ 	<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
+ 	<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/webPackagePaths.js"></script>
  	<script>
+-		const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
++		const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
  		Object.keys(self.webPackagePaths).map(function (key, index) {
--			self.webPackagePaths[key] = `${window.location.origin}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
-+			self.webPackagePaths[key] = new URL(
-+				`{{VS_BASE}}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`,
-+				window.location,
-+			).toString();
+ 			self.webPackagePaths[key] = `${baseUrl}/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
  		});
- 		require.config({
--			baseUrl: `${window.location.origin}/static/out`,
-+			baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
- 			recordStats: true,
- 			trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
- 				createScriptURL(value) {
 Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
@@ -87,68 +73,32 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
  
  		<!-- Disable pinch zooming -->
  		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
-@@ -24,10 +24,10 @@
+@@ -24,9 +24,9 @@
  		<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
  
  		<!-- Workbench Icon/Manifest/CSS -->
 -		<link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
--		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
+-		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
 -		<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
--		<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
 +		<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
-+		<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
++		<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
 +		<link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
-+		<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.css">
+ 		<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
  
  	</head>
- 
-@@ -35,14 +35,17 @@
- 	</body>
- 
- 	<!-- Startup (do not modify order of script tags!) -->
--	<script src="./static/out/vs/loader.js"></script>
--	<script src="./static/out/vs/webPackagePaths.js"></script>
-+	<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
-+	<script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
- 	<script>
- 		Object.keys(self.webPackagePaths).map(function (key, index) {
--			self.webPackagePaths[key] = `${window.location.origin}/static/node_modules/${key}/${self.webPackagePaths[key]}`;
-+			self.webPackagePaths[key] = new URL(
-+				`{{VS_BASE}}/static/node_modules/${key}/${self.webPackagePaths[key]}`,
-+				window.location,
-+			).toString();
- 		});
- 		require.config({
--			baseUrl: `${window.location.origin}/static/out`,
-+			baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
- 			recordStats: true,
- 			trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
- 				createScriptURL(value) {
-@@ -55,7 +58,7 @@
- 	<script>
- 		performance.mark('code/willLoadWorkbenchMain');
- 	</script>
--	<script src="./static/out/vs/workbench/workbench.web.main.nls.js"></script>
--	<script src="./static/out/vs/workbench/workbench.web.main.js"></script>
--	<script src="./static/out/vs/code/browser/workbench/workbench.js"></script>
-+	<script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.nls.js"></script>
-+	<script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.js"></script>
-+	<script src="{{VS_BASE}}/static/out/vs/code/browser/workbench/workbench.js"></script>
- </html>
 Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
 +++ code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
-@@ -274,7 +274,7 @@ export class BrowserSocketFactory implem
+@@ -274,6 +274,7 @@ export class BrowserSocketFactory implem
  
- 	connect(host: string, port: number, query: string, debugLabel: string, callback: IConnectCallback): void {
+ 	connect(host: string, port: number, path: string, query: string, debugLabel: string, callback: IConnectCallback): void {
  		const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
--		const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}/?${query}&skipWebSocketFrames=false`, debugLabel);
-+		const socket = this._webSocketFactory.create(`${webSocketSchema}://${window.location.host}${window.location.pathname}?${query}&skipWebSocketFrames=false`, debugLabel);
++		path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
+ 		const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
  		const errorListener = socket.onError((err) => callback(err, undefined));
  		socket.onOpen(() => {
- 			errorListener.dispose();
-@@ -282,6 +282,3 @@ export class BrowserSocketFactory implem
+@@ -282,6 +283,3 @@ export class BrowserSocketFactory implem
  		});
  	}
  }
@@ -159,47 +109,56 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -253,7 +253,10 @@ export class WebClientServer {
+@@ -267,14 +267,10 @@ export class WebClientServer {
  			return res.end();
  		}
  
--		const remoteAuthority = req.headers.host;
+-		let originalHost = req.headers['x-original-host'];
+-		if (Array.isArray(originalHost)) {
+-			originalHost = originalHost[0];
+-		}
+-		const remoteAuthority = originalHost || req.headers.host;
+-		if (!remoteAuthority) {
+-			return serveError(req, res, 400, `Bad request.`);
+-		}
 +		// It is not possible to reliably detect the remote authority on the server
 +		// in all cases.  Set this to something invalid to make sure we catch code
 +		// that is using this when it should not.
 +		const remoteAuthority = 'remote';
  
- 		function escapeAttribute(value: string): string {
- 			return value.replace(/"/g, '&quot;');
-@@ -275,6 +278,8 @@ export class WebClientServer {
- 			accessToken: this._environmentService.args['github-auth'],
+ 		function asJSON(value: unknown): string {
+ 			return JSON.stringify(value).replace(/"/g, '&quot;');
+@@ -297,6 +293,8 @@ export class WebClientServer {
  			scopes: [['user:email'], ['repo']]
  		} : undefined;
+ 
 +		const base = relativeRoot(getOriginalUrl(req))
 +		const vscodeBase = relativePath(getOriginalUrl(req))
- 		const data = (await util.promisify(fs.readFile)(filePath)).toString()
- 			.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
- 				remoteAuthority,
-@@ -285,6 +290,7 @@ export class WebClientServer {
- 				folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
- 				workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
- 				productConfiguration: <Partial<IProductConfiguration>>{
-+					rootEndpoint: base,
- 					codeServerVersion: this._productService.codeServerVersion,
- 					embedderIdentifier: 'server-distro',
- 					extensionsGallery: this._webExtensionResourceUrlTemplate ? {
-@@ -297,7 +303,9 @@ export class WebClientServer {
- 					} : undefined
- 				}
- 			})))
--			.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '');
-+			.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
-+			.replace(/{{BASE}}/g, base)
-+			.replace(/{{VS_BASE}}/g, vscodeBase);
  
- 		const cspDirectives = [
- 			'default-src \'self\';',
-@@ -376,3 +384,70 @@ export class WebClientServer {
+ 		const workbenchWebConfiguration = {
+ 			remoteAuthority,
+@@ -308,6 +306,7 @@ export class WebClientServer {
+ 			workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
+ 			productConfiguration: <Partial<IProductConfiguration>>{
+ 				codeServerVersion: this._productService.codeServerVersion,
++				rootEndpoint: base,
+ 				embedderIdentifier: 'server-distro',
+ 				extensionsGallery: this._webExtensionResourceUrlTemplate ? {
+ 					...this._productService.extensionsGallery,
+@@ -328,8 +327,10 @@ export class WebClientServer {
+ 		const values: { [key: string]: string } = {
+ 			WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
+ 			WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
+-			WORKBENCH_WEB_BASE_URL: this._staticRoute,
+-			WORKBENCH_NLS_BASE_URL: nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : '',
++			WORKBENCH_WEB_BASE_URL: vscodeBase + this._staticRoute,
++			WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : ''),
++			BASE: base,
++			VS_BASE: vscodeBase,
+ 		};
+ 
+ 
+@@ -419,3 +420,70 @@ export class WebClientServer {
  		return res.end(data);
  	}
  }
@@ -286,7 +245,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
 +++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
-@@ -482,6 +482,7 @@ function doCreateUri(path: string, query
+@@ -485,6 +485,7 @@ function doCreateUri(path: string, query
  		});
  	}
  
@@ -294,12 +253,12 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
  	return URI.parse(window.location.href).with({ path, query });
  }
  
-@@ -493,7 +494,7 @@ function doCreateUri(path: string, query
+@@ -496,7 +497,7 @@ function doCreateUri(path: string, query
  	if (!configElement || !configElementAttribute) {
  		throw new Error('Missing web configuration element');
  	}
--	const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
-+	const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
+-	const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = JSON.parse(configElementAttribute);
++	const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
  
  	// Create workbench
  	create(document.body, {
@@ -312,10 +271,10 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/
  import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
  import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
 -import { RemoteAuthorities } from 'vs/base/common/network';
+ import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
  
  export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
- 
-@@ -72,7 +71,7 @@ export abstract class AbstractExtensionR
+@@ -75,7 +74,7 @@ export abstract class AbstractExtensionR
  	public getExtensionGalleryResourceURL(galleryExtension: { publisher: string; name: string; version: string }, path?: string): URI | undefined {
  		if (this._extensionGalleryResourceUrlTemplate) {
  			const uri = URI.parse(format2(this._extensionGalleryResourceUrlTemplate, { publisher: galleryExtension.publisher, name: galleryExtension.name, version: galleryExtension.version, path: 'extension' }));
diff --git a/patches/connection-type.diff b/patches/connection-type.diff
index 050715c90ff5..7ea29cd0764f 100644
--- a/patches/connection-type.diff
+++ b/patches/connection-type.diff
@@ -14,12 +14,13 @@ Index: code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnectio
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
 +++ code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
-@@ -231,7 +231,7 @@ async function connectToRemoteExtensionH
-
+@@ -233,7 +233,8 @@ async function connectToRemoteExtensionH
+ 
  	let socket: ISocket;
  	try {
--		socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
-+		socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `type=${connectionTypeToString(connectionType)}&reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
+-		socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, getRemoteServerRootPath(options), `reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
++
++		socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, getRemoteServerRootPath(options), `type=${connectionTypeToString(connectionType)}&reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
  	} catch (error) {
  		options.logService.error(`${logPrefix} socketFactory.connect() failed or timed out. Error:`);
  		options.logService.error(error);
diff --git a/patches/disable-builtin-ext-update.diff b/patches/disable-builtin-ext-update.diff
index 4cee1361abe8..cbfd77406428 100644
--- a/patches/disable-builtin-ext-update.diff
+++ b/patches/disable-builtin-ext-update.diff
@@ -7,17 +7,18 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
 +++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
-@@ -206,6 +206,9 @@ export class Extension implements IExten
- 		if (!this.gallery || !this.local) {
- 			return false;
- 		}
-+		if (this.type !== ExtensionType.User) {
-+			return false;
-+		}
- 		if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
- 			return false;
- 		}
-@@ -1057,6 +1060,10 @@ export class ExtensionsWorkbenchService
+@@ -234,6 +234,10 @@ export class Extension implements IExten
+ 			if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
+ 				return false;
+ 			}
++			// Do not update builtin extensions.
++			if (this.type !== ExtensionType.User) {
++				return false;
++			}
+ 			if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
+ 				return false;
+ 			}
+@@ -1088,6 +1092,10 @@ export class ExtensionsWorkbenchService
  				// Skip if check updates only for builtin extensions and current extension is not builtin.
  				continue;
  			}
@@ -25,6 +26,6 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
 +				// Never update builtin extensions.
 +				continue;
 +			}
- 			if (installed.isBuiltin && !installed.local?.identifier.uuid) {
- 				// Skip if the builtin extension does not have Marketplace id
+ 			if (installed.isBuiltin && (!installed.local?.identifier.uuid || (!isWeb && this.productService.quality === 'stable'))) {
+ 				// Skip checking updates for a builtin extension if it does not has Marketplace identifier or the current product is VS Code Desktop stable.
  				continue;
diff --git a/patches/disable-downloads.diff b/patches/disable-downloads.diff
index 7568fcd0b6e5..b5f7dc7233e9 100644
--- a/patches/disable-downloads.diff
+++ b/patches/disable-downloads.diff
@@ -12,7 +12,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
 +++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
-@@ -215,6 +215,11 @@ export interface IWorkbenchConstructionO
+@@ -250,6 +250,11 @@ export interface IWorkbenchConstructionO
  	 */
  	readonly userDataPath?: string
  
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
 +++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
-@@ -30,6 +30,11 @@ export interface IBrowserWorkbenchEnviro
+@@ -31,6 +31,11 @@ export interface IBrowserWorkbenchEnviro
  	 * Options used to configure the workbench.
  	 */
  	readonly options?: IWorkbenchConstructionOptions;
@@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
  }
  
  export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
-@@ -61,6 +66,13 @@ export class BrowserWorkbenchEnvironment
+@@ -62,6 +67,13 @@ export class BrowserWorkbenchEnvironment
  		return this.options.userDataPath;
  	}
  
@@ -58,18 +58,18 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
 +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
-@@ -15,6 +15,7 @@ export const serverOptions: OptionDescri
+@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
+ 	/* ----- code-server ----- */
  	'disable-update-check': { type: 'boolean' },
  	'auth': { type: 'string' },
- 	'locale': { type: 'string' },
 +	'disable-file-downloads': { type: 'boolean' },
  
  	/* ----- server setup ----- */
  
-@@ -96,6 +97,7 @@ export interface ServerParsedArgs {
+@@ -94,6 +95,7 @@ export interface ServerParsedArgs {
+ 	/* ----- code-server ----- */
  	'disable-update-check'?: boolean;
  	'auth'?: string
- 	'locale'?: string
 +	'disable-file-downloads'?: boolean;
  
  	/* ----- server setup ----- */
@@ -78,14 +78,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -293,6 +293,7 @@ export class WebClientServer {
- 					logLevel: this._logService.getLevel(),
- 				},
- 				userDataPath: this._environmentService.userDataPath,
-+				isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
- 				settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
- 				enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
- 				folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
+@@ -300,6 +300,7 @@ export class WebClientServer {
+ 			remoteAuthority,
+ 			webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
+ 			userDataPath: this._environmentService.userDataPath,
++			isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
+ 			_wrapWebWorkerExtHostInIframe,
+ 			developmentOptions: {
+ 				enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined,
 Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -144,7 +144,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
  import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
  import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
  import { ThemeIcon } from 'vs/platform/theme/common/themeService';
-@@ -476,13 +476,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
+@@ -477,13 +477,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
  		id: DOWNLOAD_COMMAND_ID,
  		title: DOWNLOAD_LABEL
  	},
diff --git a/patches/display-language.diff b/patches/display-language.diff
index aad709545fb5..c3de5a83ff88 100644
--- a/patches/display-language.diff
+++ b/patches/display-language.diff
@@ -1,17 +1,28 @@
 Add display language support
 
-This likely needs tweaking if we want to upstream.
+We can remove this once upstream supports all language packs.
+
+1. Proxies language packs to the service on the backend.
+2. NLS configuration is embedded into the HTML for the browser to pick up.  This
+   code to generate this configuration is copied from the native portion.
+3. Remove navigator.language default since that will prevent the argv file from
+   being created if you are changing the language to whatever your browser
+   default happens to be.
+4. Move the argv.json file to the server instead of in-browser storage.  This is
+   where the current locale is stored and currently the server needs to be able
+   to read it.
+5. Add the locale flag.
 
 Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
 +++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
-@@ -192,6 +192,9 @@ export async function setupServerService
+@@ -202,6 +202,9 @@ export async function setupServerService
  		const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
  		socketServer.registerChannel('extensions', channel);
  
-+		const localizationsChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILocalizationsService));
-+		socketServer.registerChannel('localizations', localizationsChannel);
++		const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService));
++		socketServer.registerChannel('languagePacks', languagePackChannel);
 +
  		const encryptionChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(IEncryptionMainService));
  		socketServer.registerChannel('encryption', encryptionChannel);
@@ -20,9 +31,12 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/base/common/platform.ts
 +++ code-server/lib/vscode/src/vs/base/common/platform.ts
-@@ -84,6 +84,17 @@ if (typeof navigator === 'object' && !is
+@@ -80,8 +80,19 @@ if (typeof navigator === 'object' && !is
+ 	_isIOS = (_userAgent.indexOf('Macintosh') >= 0 || _userAgent.indexOf('iPad') >= 0 || _userAgent.indexOf('iPhone') >= 0) && !!navigator.maxTouchPoints && navigator.maxTouchPoints > 0;
+ 	_isLinux = _userAgent.indexOf('Linux') >= 0;
  	_isWeb = true;
- 	_locale = navigator.language;
+-	_locale = navigator.language;
++	_locale = LANGUAGE_DEFAULT;
  	_language = _locale;
 +
 +	const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration');
@@ -51,23 +65,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
 +
  		<!-- Workbench Icon/Manifest/CSS -->
  		<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
- 		<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
-@@ -38,6 +41,27 @@
- 	<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
- 	<script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
- 	<script>
-+		let nlsConfig
+ 		<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+@@ -43,17 +46,27 @@
+ 			self.webPackagePaths[key] = `${baseUrl}/node_modules/${key}/${self.webPackagePaths[key]}`;
+ 		});
+ 
+-		// Set up nls if the user is not using the default language (English)
+ 		const nlsConfig = {};
+-		const locale = navigator.language;
+-		if (!locale.startsWith('en')) {
+-			nlsConfig['vs/nls'] = {
+-				availableLanguages: {
+-					'*': locale
+-				},
+-				baseUrl: '{{WORKBENCH_NLS_BASE_URL}}'
+-			};
+-		}
 +		try {
-+			nlsConfig = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
-+			if (nlsConfig._resolvedLanguagePackCoreLocation) {
++			nlsConfig['vs/nls'] = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
++			if (nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation) {
 +				const bundles = Object.create(null)
-+				nlsConfig.loadBundle = (bundle, _language, cb) => {
++				nlsConfig['vs/nls'].loadBundle = (bundle, _language, cb) => {
 +					const result = bundles[bundle]
 +					if (result) {
 +						return cb(undefined, result)
 +					}
-+					const path = nlsConfig._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
-+					fetch(`{{VS_BASE}}/vscode-remote-resource?path=${encodeURIComponent(path)}`)
++					const path = nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
++					fetch(`{{WORKBENCH_WEB_BASE_URL}}/vscode-remote-resource?path=${encodeURIComponent(path)}`)
 +						.then((response) => response.json())
 +						.then((json) => {
 +							bundles[bundle] = json
@@ -77,19 +101,9 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
 +				}
 +			}
 +		} catch (error) { /* Probably fine. */ }
- 		Object.keys(self.webPackagePaths).map(function (key, index) {
- 			self.webPackagePaths[key] = new URL(
- 				`{{VS_BASE}}/static/node_modules/${key}/${self.webPackagePaths[key]}`,
-@@ -52,7 +76,8 @@
- 					return value;
- 				}
- 			}),
--			paths: self.webPackagePaths
-+			paths: self.webPackagePaths,
-+			'vs/nls': nlsConfig,
- 		});
- 	</script>
- 	<script>
+ 
+ 		require.config({
+ 			baseUrl: `${baseUrl}/out`,
 Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts
@@ -168,98 +182,88 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -27,6 +27,7 @@ import { URI } from 'vs/base/common/uri'
+@@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri'
  import { streamToBuffer } from 'vs/base/common/buffer';
  import { IProductConfiguration } from 'vs/base/common/product';
  import { isString } from 'vs/base/common/types';
 +import { getLocaleFromConfig, getNLSConfiguration } from 'vs/server/node/remoteLanguagePacks';
+ import { CharCode } from 'vs/base/common/charCode';
+ import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
+ 
+@@ -295,6 +296,8 @@ export class WebClientServer {
  
- const textMimeType = {
- 	'.html': 'text/html',
-@@ -280,6 +281,8 @@ export class WebClientServer {
- 		} : undefined;
  		const base = relativeRoot(getOriginalUrl(req))
  		const vscodeBase = relativePath(getOriginalUrl(req))
 +		const locale = this._environmentService.args.locale || await getLocaleFromConfig(this._environmentService.argvResource.fsPath);
 +		const nlsConfiguration = await getNLSConfiguration(locale, this._environmentService.userDataPath)
- 		const data = (await util.promisify(fs.readFile)(filePath)).toString()
- 			.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
- 				remoteAuthority,
-@@ -309,7 +312,8 @@ export class WebClientServer {
- 			})))
- 			.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
- 			.replace(/{{BASE}}/g, base)
--			.replace(/{{VS_BASE}}/g, vscodeBase);
-+			.replace(/{{VS_BASE}}/g, vscodeBase)
-+			.replace(/{{NLS_CONFIGURATION}}/g, () => escapeAttribute(JSON.stringify(nlsConfiguration)));
  
- 		const cspDirectives = [
- 			'default-src \'self\';',
+ 		const workbenchWebConfiguration = {
+ 			remoteAuthority,
+@@ -338,6 +341,7 @@ export class WebClientServer {
+ 			WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : ''),
+ 			BASE: base,
+ 			VS_BASE: vscodeBase,
++			NLS_CONFIGURATION: asJSON(nlsConfiguration),
+ 		};
+ 
+ 
 Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
 +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
-@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
- 	/* ----- code-server ----- */
+@@ -15,6 +15,7 @@ export const serverOptions: OptionDescri
  	'disable-update-check': { type: 'boolean' },
  	'auth': { type: 'string' },
+ 	'disable-file-downloads': { type: 'boolean' },
 +	'locale': { type: 'string' },
  
  	/* ----- server setup ----- */
  
-@@ -94,6 +95,7 @@ export interface ServerParsedArgs {
- 	/* ----- code-server ----- */
+@@ -96,6 +97,7 @@ export interface ServerParsedArgs {
  	'disable-update-check'?: boolean;
  	'auth'?: string
+ 	'disable-file-downloads'?: boolean;
 +	'locale'?: string
  
  	/* ----- server setup ----- */
  
-Index: code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
+Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
 ===================================================================
---- /dev/null
-+++ code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
-@@ -0,0 +1,28 @@
-+/*---------------------------------------------------------------------------------------------
-+ *  Copyright (c) Coder Technologies. All rights reserved.
-+ *  Licensed under the MIT License. See License.txt in the project root for license information.
-+ *--------------------------------------------------------------------------------------------*/
+--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
++++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
+@@ -109,6 +109,12 @@ registerSingleton(IDiagnosticsService, N
+ 
+ //#region --- workbench contributions
+ 
++// Localization.  These do not actually import anything specific to Electron so
++// they should be safe.
++import 'vs/workbench/services/localization/electron-sandbox/localeService';
++import 'vs/workbench/contrib/localization/electron-sandbox/localization.contribution';
++import 'vs/platform/languagePacks/browser/languagePacks';
 +
+ // Output
+ import 'vs/workbench/contrib/output/common/outputChannelModelService';
+ 
+Index: code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
+===================================================================
+--- /dev/null
++++ code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
+@@ -0,0 +1,18 @@
 +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
 +import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
-+import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
++import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
 +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
 +
-+/**
-+ * Add localizations service for the browser.
-+ * @author coder
-+ */
-+
 +// @ts-ignore: interface is implemented via proxy
-+export class LocalizationsService implements ILocalizationsService {
++export class LanguagePackService implements ILanguagePackService {
 +
 +	declare readonly _serviceBrand: undefined;
 +
 +	constructor(
 +		@IRemoteAgentService remoteAgentService: IRemoteAgentService,
 +	) {
-+		return ProxyChannel.toService<ILocalizationsService>(remoteAgentService.getConnection()!.getChannel('localizations'));
++		return ProxyChannel.toService<ILanguagePackService>(remoteAgentService.getConnection()!.getChannel('languagePacks'));
 +	}
 +}
 +
-+registerSingleton(ILocalizationsService, LocalizationsService, true);
-Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
-===================================================================
---- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
-+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
-@@ -112,6 +112,10 @@ registerSingleton(IDiagnosticsService, N
- 
- //#region --- workbench contributions
- 
-+// Localizations
-+import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
-+import 'vs/workbench/services/localizations/browser/localizationsService';
-+
- // Output
- import 'vs/workbench/contrib/output/common/outputChannelModelService';
- 
++registerSingleton(ILanguagePackService, LanguagePackService, true);
diff --git a/patches/github-auth.diff b/patches/github-auth.diff
index 53b98d0f422f..20ab57e42724 100644
--- a/patches/github-auth.diff
+++ b/patches/github-auth.diff
@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainSe
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
 +++ code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
-@@ -5,18 +5,32 @@
+@@ -5,9 +5,18 @@
  
  import { InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials';
  import { ILogService } from 'vs/platform/log/common/log';
@@ -26,6 +26,8 @@ Index: code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainSe
 +}
  
  export class CredentialsWebMainService extends BaseCredentialsMainService {
+ 	// Since we fallback to the in-memory credentials provider, we do not need to surface any Keytar load errors
+@@ -16,10 +25,15 @@ export class CredentialsWebMainService e
  
  	constructor(
  		@ILogService logService: ILogService,
@@ -42,7 +44,7 @@ Index: code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainSe
  	}
  
  	// If the credentials service is running on the server, we add a suffix -server to differentiate from the location that the
-@@ -45,4 +59,59 @@ export class CredentialsWebMainService e
+@@ -48,4 +62,59 @@ export class CredentialsWebMainService e
  		}
  		return this._keytarCache;
  	}
diff --git a/patches/integration.diff b/patches/integration.diff
index e8c1972383dd..f3d63771f91f 100644
--- a/patches/integration.diff
+++ b/patches/integration.diff
@@ -7,6 +7,7 @@ Prepare Code for integration with code-server
 3. Add the code-server version to the help dialog.
 4. Add ready events for use in an iframe.
 5. Add our icons.
+6. Use our own manifest.
 
 Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
 ===================================================================
@@ -21,7 +22,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
  import product from 'vs/platform/product/common/product';
  import * as perf from 'vs/base/common/performance';
  
-@@ -33,38 +33,43 @@ const errorReporter: ErrorReporter = {
+@@ -34,38 +34,43 @@ const errorReporter: ErrorReporter = {
  	}
  };
  
@@ -106,7 +107,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandl
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
 +++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
-@@ -143,12 +143,15 @@ export class BrowserDialogHandler implem
+@@ -143,8 +143,11 @@ export class BrowserDialogHandler implem
  
  	async about(): Promise<void> {
  		const detailString = (useAgo: boolean): string => {
@@ -120,11 +121,6 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandl
  				this.productService.version || 'Unknown',
  				this.productService.commit || 'Unknown',
  				this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown',
--				navigator.userAgent
-+				navigator.userAgent,
- 			);
- 		};
- 
 Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
 ===================================================================
 --- /dev/null
@@ -185,10 +181,10 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
  import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
  import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
 +import { CodeServerClient } from 'vs/workbench/browser/client';
- 
- export class BrowserMain extends Disposable {
- 
-@@ -103,6 +104,9 @@ export class BrowserMain extends Disposa
+ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
+ import { IProgressService } from 'vs/platform/progress/common/progress';
+ import { DelayedLogChannel } from 'vs/workbench/services/output/common/delayedLogChannel';
+@@ -109,6 +110,9 @@ export class BrowserMain extends Disposa
  		// Startup
  		const instantiationService = workbench.startup();
  
@@ -219,22 +215,24 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
  		<meta name="mobile-web-app-capable" content="yes" />
  		<meta name="apple-mobile-web-app-capable" content="yes" />
  		<meta name="apple-mobile-web-app-title" content="Code">
--		<link rel="apple-touch-icon" href="/code-192.png" />
+-		<link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
 +		<link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
 +		<link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
  
  		<!-- Disable pinch zooming -->
  		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
-@@ -26,7 +27,8 @@
+@@ -26,8 +27,9 @@
  		<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
  
  		<!-- Workbench Icon/Manifest/CSS -->
--		<link rel="icon" href="/favicon.ico" type="image/x-icon" />
+-		<link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
+-		<link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/manifest.json" crossorigin="use-credentials" />
 +		<link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
-+		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
- 		<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
++		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
++		<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
  	</head>
  
+ 	<body aria-label="">
 Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
@@ -243,31 +241,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
  		<meta name="mobile-web-app-capable" content="yes" />
  		<meta name="apple-mobile-web-app-capable" content="yes" />
  		<meta name="apple-mobile-web-app-title" content="Code">
--		<link rel="apple-touch-icon" href="/code-192.png" />
+-		<link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
 +		<link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
 +		<link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
  
  		<!-- Disable pinch zooming -->
  		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
-@@ -23,7 +24,8 @@
+@@ -23,8 +24,9 @@
  		<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
  
  		<!-- Workbench Icon/Manifest/CSS -->
--		<link rel="icon" href="/favicon.ico" type="image/x-icon" />
+-		<link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
+-		<link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/manifest.json" crossorigin="use-credentials" />
 +		<link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
-+		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
- 		<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
- 		<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
++		<link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
++		<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
+ 		<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
  
+ 	</head>
 Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -285,6 +285,7 @@ export class WebClientServer {
- 				folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
- 				workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
- 				productConfiguration: <Partial<IProductConfiguration>>{
-+					codeServerVersion: this._productService.codeServerVersion,
- 					embedderIdentifier: 'server-distro',
- 					extensionsGallery: this._webExtensionResourceUrlTemplate ? {
- 						...this._productService.extensionsGallery,
+@@ -307,6 +307,7 @@ export class WebClientServer {
+ 			folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
+ 			workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
+ 			productConfiguration: <Partial<IProductConfiguration>>{
++				codeServerVersion: this._productService.codeServerVersion,
+ 				embedderIdentifier: 'server-distro',
+ 				extensionsGallery: this._webExtensionResourceUrlTemplate ? {
+ 					...this._productService.extensionsGallery,
diff --git a/patches/local-storage.diff b/patches/local-storage.diff
index 744540bbfafd..a7aa8b06b489 100644
--- a/patches/local-storage.diff
+++ b/patches/local-storage.diff
@@ -20,19 +20,19 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -292,6 +292,7 @@ export class WebClientServer {
- 					enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
- 					logLevel: this._logService.getLevel(),
- 				},
-+				userDataPath: this._environmentService.userDataPath,
- 				settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
- 				enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
- 				folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
+@@ -299,6 +299,7 @@ export class WebClientServer {
+ 		const workbenchWebConfiguration = {
+ 			remoteAuthority,
+ 			webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
++			userDataPath: this._environmentService.userDataPath,
+ 			_wrapWebWorkerExtHostInIframe,
+ 			developmentOptions: {
+ 				enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined,
 Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
 +++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
-@@ -210,6 +210,11 @@ export interface IWorkbenchConstructionO
+@@ -245,6 +245,11 @@ export interface IWorkbenchConstructionO
  	 */
  	readonly configurationDefaults?: Record<string, any>;
  
@@ -48,7 +48,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
 +++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
-@@ -52,7 +52,14 @@ export class BrowserWorkbenchEnvironment
+@@ -53,7 +53,14 @@ export class BrowserWorkbenchEnvironment
  	get logFile(): URI { return joinPath(this.logsHome, 'window.log'); }
  
  	@memoize
diff --git a/patches/log-level.diff b/patches/log-level.diff
index 8b4f125b5d43..53226c226338 100644
--- a/patches/log-level.diff
+++ b/patches/log-level.diff
@@ -7,15 +7,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -288,7 +288,10 @@ export class WebClientServer {
- 				remoteAuthority,
- 				webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
- 				_wrapWebWorkerExtHostInIframe,
--				developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
-+				developmentOptions: {
-+					enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
-+					logLevel: this._logService.getLevel(),
-+				},
- 				settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
- 				enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
- 				folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
+@@ -300,7 +300,10 @@ export class WebClientServer {
+ 			remoteAuthority,
+ 			webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
+ 			_wrapWebWorkerExtHostInIframe,
+-			developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
++			developmentOptions: {
++				enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined,
++				logLevel: this._logService.getLevel(),
++			},
+ 			settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
+ 			enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
+ 			folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
diff --git a/patches/logout.diff b/patches/logout.diff
index 1a8d0f00567b..24c4923dff64 100644
--- a/patches/logout.diff
+++ b/patches/logout.diff
@@ -40,14 +40,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -293,6 +293,7 @@ export class WebClientServer {
- 				productConfiguration: <Partial<IProductConfiguration>>{
- 					rootEndpoint: base,
- 					updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
-+					logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
- 					codeServerVersion: this._productService.codeServerVersion,
- 					embedderIdentifier: 'server-distro',
- 					extensionsGallery: {
+@@ -309,6 +309,7 @@ export class WebClientServer {
+ 				codeServerVersion: this._productService.codeServerVersion,
+ 				rootEndpoint: base,
+ 				updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
++				logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
+ 				embedderIdentifier: 'server-distro',
+ 				extensionsGallery: this._productService.extensionsGallery,
+ 			},
 Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
diff --git a/patches/marketplace.diff b/patches/marketplace.diff
index d6e799756320..8eb88101dc49 100644
--- a/patches/marketplace.diff
+++ b/patches/marketplace.diff
@@ -3,6 +3,13 @@ Add Open VSX default and an env var for marketplace, fix old marketplace
 Our old marketplace only supports `serviceUrl` but this causes the marketplace
 to be disabled entirely so this moves the template var check to fix that.
 
+This also removes serverRootPath from the web extension route because that will
+include the commit.  When you update code-server (including this update) the web
+extension will continue using the old path since it is stored in the browser but
+the path will 404 because the commit no longer matches.  This change is only to
+support current installations though because this patch also removes the
+in-between and has web extensions install directly from the marketplace.
+
 This can be tested by setting EXTENSIONS_GALLERY set to:
 
     '{"serviceUrl": "https://extensions.coder.com/api"}'
@@ -32,22 +39,49 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -293,14 +293,14 @@ export class WebClientServer {
- 					rootEndpoint: base,
- 					codeServerVersion: this._productService.codeServerVersion,
- 					embedderIdentifier: 'server-distro',
--					extensionsGallery: this._webExtensionResourceUrlTemplate ? {
-+					extensionsGallery: {
- 						...this._productService.extensionsGallery,
--						'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
-+						'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
- 							scheme: 'http',
- 							authority: remoteAuthority,
- 							path: `web-extension-resource/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
--						}).toString(true)
--					} : undefined
-+						}).toString(true) : undefined
-+					},
- 				}
- 			})))
- 			.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
+@@ -111,7 +111,7 @@ export class WebClientServer {
+ 		const serverRootPath = getRemoteServerRootPath(_productService);
+ 		this._staticRoute = `${serverRootPath}/static`;
+ 		this._callbackRoute = `${serverRootPath}/callback`;
+-		this._webExtensionRoute = `${serverRootPath}/web-extension-resource`;
++		this._webExtensionRoute = `/web-extension-resource`;
+ 	}
+ 
+ 	/**
+@@ -308,14 +308,7 @@ export class WebClientServer {
+ 				codeServerVersion: this._productService.codeServerVersion,
+ 				rootEndpoint: base,
+ 				embedderIdentifier: 'server-distro',
+-				extensionsGallery: this._webExtensionResourceUrlTemplate ? {
+-					...this._productService.extensionsGallery,
+-					'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
+-						scheme: 'http',
+-						authority: remoteAuthority,
+-						path: `${this._webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
+-					}).toString(true)
+-				} : undefined
++				extensionsGallery: this._productService.extensionsGallery,
+ 			},
+ 			callbackRoute: this._callbackRoute
+ 		};
+Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
+===================================================================
+--- code-server.orig/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
++++ code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
+@@ -16,7 +16,6 @@ import { getServiceMachineId } from 'vs/
+ import { IStorageService } from 'vs/platform/storage/common/storage';
+ import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
+ import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
+-import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
+ 
+ export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
+ 
+@@ -60,7 +59,7 @@ export abstract class AbstractExtensionR
+ 		private readonly _environmentService: IEnvironmentService,
+ 		private readonly _configurationService: IConfigurationService,
+ 	) {
+-		this._webExtensionResourceEndPoint = `${getRemoteServerRootPath(_productService)}/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
++		this._webExtensionResourceEndPoint = `/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
+ 		if (_productService.extensionsGallery) {
+ 			this._extensionGalleryResourceUrlTemplate = _productService.extensionsGallery.resourceUrlTemplate;
+ 			this._extensionGalleryAuthority = this._extensionGalleryResourceUrlTemplate ? this._getExtensionGalleryAuthority(URI.parse(this._extensionGalleryResourceUrlTemplate)) : undefined;
diff --git a/patches/proposed-api.diff b/patches/proposed-api.diff
index ebd5deb57569..397a3767e697 100644
--- a/patches/proposed-api.diff
+++ b/patches/proposed-api.diff
@@ -9,7 +9,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstra
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
 +++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
-@@ -1471,7 +1471,7 @@ class ProposedApiController {
+@@ -1451,7 +1451,7 @@ class ProposedApiController {
  
  		this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));
  
@@ -22,7 +22,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
 +++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
-@@ -163,10 +163,7 @@ export interface IExtensionHost {
+@@ -359,10 +359,7 @@ function extensionDescriptionArrayToMap(
  }
  
  export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
diff --git a/patches/proxy-uri.diff b/patches/proxy-uri.diff
index b153b20df00d..c0899b0b7298 100644
--- a/patches/proxy-uri.diff
+++ b/patches/proxy-uri.diff
@@ -26,25 +26,25 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
 +++ code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
-@@ -7,7 +7,7 @@ import { Emitter } from 'vs/base/common/
- import { Disposable } from 'vs/base/common/lifecycle';
+@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/comm
  import { RemoteAuthorities } from 'vs/base/common/network';
  import { URI } from 'vs/base/common/uri';
+ import { IProductService } from 'vs/platform/product/common/productService';
 -import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
 +import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
+ import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
  
  export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
- 
-@@ -20,7 +20,7 @@ export class RemoteAuthorityResolverServ
+@@ -22,7 +22,7 @@ export class RemoteAuthorityResolverServ
  	private readonly _connectionToken: string | undefined;
  	private readonly _connectionTokens: Map<string, string>;
  
--	constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
-+	constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
+-	constructor(@IProductService productService: IProductService, connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
++	constructor(@IProductService productService: IProductService, connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
  		super();
  		this._cache = new Map<string, ResolverResult>();
  		this._connectionToken = connectionToken;
-@@ -59,12 +59,17 @@ export class RemoteAuthorityResolverServ
+@@ -62,12 +62,17 @@ export class RemoteAuthorityResolverServ
  
  	private _doResolveAuthority(authority: string): ResolverResult {
  		const connectionToken = this._connectionTokens.get(authority) || this._connectionToken;
@@ -68,24 +68,24 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -294,6 +294,7 @@ export class WebClientServer {
- 					rootEndpoint: base,
- 					updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
- 					logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
-+					proxyEndpointTemplate: base + '/proxy/{{port}}',
- 					codeServerVersion: this._productService.codeServerVersion,
- 					embedderIdentifier: 'server-distro',
- 					extensionsGallery: {
+@@ -310,6 +310,7 @@ export class WebClientServer {
+ 				rootEndpoint: base,
+ 				updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
+ 				logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
++				proxyEndpointTemplate: base + '/proxy/{{port}}',
+ 				embedderIdentifier: 'server-distro',
+ 				extensionsGallery: this._productService.extensionsGallery,
+ 			},
 Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
 +++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
-@@ -179,7 +179,7 @@ export class BrowserMain extends Disposa
+@@ -209,7 +209,7 @@ export class BrowserMain extends Disposa
  
  		// Remote
  		const connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName);
--		const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider);
-+		const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
+-		const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider);
++		const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
  		serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
  
  		// Signing
@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalE
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
 +++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
-@@ -388,7 +388,7 @@ export function createTerminalEnvironmen
+@@ -388,7 +388,7 @@ export async function createTerminalEnvi
  
  		// Sanitize the environment, removing any undesirable VS Code and Electron environment
  		// variables
diff --git a/patches/series b/patches/series
index 318ad7abac9d..69b66b6ffc76 100644
--- a/patches/series
+++ b/patches/series
@@ -9,7 +9,6 @@ update-check.diff
 logout.diff
 store-socket.diff
 proxy-uri.diff
-display-language.diff
 github-auth.diff
 unique-db.diff
 log-level.diff
@@ -19,3 +18,4 @@ connection-type.diff
 sourcemaps.diff
 disable-downloads.diff
 telemetry.diff
+display-language.diff
diff --git a/patches/service-worker.diff b/patches/service-worker.diff
index db2bacd22ef1..6ead1a60eec1 100644
--- a/patches/service-worker.diff
+++ b/patches/service-worker.diff
@@ -21,17 +21,17 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -304,6 +304,10 @@ export class WebClientServer {
- 					proxyEndpointTemplate: base + '/proxy/{{port}}',
- 					codeServerVersion: this._productService.codeServerVersion,
- 					embedderIdentifier: 'server-distro',
-+					serviceWorker: {
-+						scope: vscodeBase + '/',
-+						path: base + '/_static/out/browser/serviceWorker.js',
-+					},
- 					extensionsGallery: {
- 						...this._productService.extensionsGallery,
- 						'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
+@@ -315,6 +315,10 @@ export class WebClientServer {
+ 				updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
+ 				logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
+ 				proxyEndpointTemplate: base + '/proxy/{{port}}',
++				serviceWorker: {
++					scope: vscodeBase + '/',
++					path: base + '/_static/out/browser/serviceWorker.js',
++				},
+ 				embedderIdentifier: 'server-distro',
+ 				extensionsGallery: this._productService.extensionsGallery,
+ 			},
 Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
diff --git a/patches/sourcemaps.diff b/patches/sourcemaps.diff
index 03502650c23b..fb252cfecddd 100644
--- a/patches/sourcemaps.diff
+++ b/patches/sourcemaps.diff
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
 ===================================================================
 --- code-server.orig/lib/vscode/build/gulpfile.reh.js
 +++ code-server/lib/vscode/build/gulpfile.reh.js
-@@ -191,8 +191,7 @@ function packageTask(type, platform, arc
+@@ -194,8 +194,7 @@ function packageTask(type, platform, arc
  
  		const src = gulp.src(sourceFolderName + '/**', { base: '.' })
  			.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
  
  		const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
  		const isUIExtension = (manifest) => {
-@@ -231,9 +230,9 @@ function packageTask(type, platform, arc
+@@ -234,9 +233,9 @@ function packageTask(type, platform, arc
  			.map(name => `.build/extensions/${name}/**`);
  
  		const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
  
  		let version = packageJson.version;
  		const quality = product.quality;
-@@ -368,7 +367,7 @@ function tweakProductForServerWeb(produc
+@@ -371,7 +370,7 @@ function tweakProductForServerWeb(produc
  	const minifyTask = task.define(`minify-vscode-${type}`, task.series(
  		optimizeTask,
  		util.rimraf(`out-vscode-${type}-min`),
diff --git a/patches/telemetry.diff b/patches/telemetry.diff
index 2d0feabac82b..77b5064b40ce 100644
--- a/patches/telemetry.diff
+++ b/patches/telemetry.diff
@@ -4,15 +4,15 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
 +++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
-@@ -68,6 +68,7 @@ import { REMOTE_TERMINAL_CHANNEL_NAME }
- import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService';
- import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/workbench/services/remote/common/remoteFileSystemProviderClient';
+@@ -70,6 +70,7 @@ import { REMOTE_FILE_SYSTEM_CHANNEL_NAME
  import { ExtensionHostStatusService, IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService';
+ import { IExtensionsScannerService } from 'vs/platform/extensionManagement/common/extensionsScannerService';
+ import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService';
 +import { TelemetryClient } from "vs/server/node/telemetryClient";
+ import { NullPolicyService } from 'vs/platform/policy/common/policy';
  
  const eventPrefix = 'monacoworkbench';
- 
-@@ -120,7 +121,11 @@ export async function setupServerService
+@@ -123,7 +124,11 @@ export async function setupServerService
  	let appInsightsAppender: ITelemetryAppender = NullAppender;
  	const machineId = await getMachineId();
  	if (supportsTelemetry(productService, environmentService)) {
@@ -165,23 +165,11 @@ Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
 +		}
 +	}
 +}
-Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-===================================================================
---- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
-+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -304,6 +304,7 @@ export class WebClientServer {
- 					logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
- 					proxyEndpointTemplate: base + '/proxy/{{port}}',
- 					codeServerVersion: this._productService.codeServerVersion,
-+					enableTelemetry: this._productService.enableTelemetry,
- 					embedderIdentifier: 'server-distro',
- 					serviceWorker: {
- 						scope: vscodeBase + '/',
 Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
 +++ code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
-@@ -119,16 +119,19 @@ export class TelemetryService extends Di
+@@ -120,16 +120,19 @@ export class TelemetryService extends Di
  	) {
  		super();
  
@@ -210,3 +198,15 @@ Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/teleme
  		} else {
  			this.impl = NullTelemetryService;
  		}
+Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
+===================================================================
+--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
++++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
+@@ -320,6 +320,7 @@ export class WebClientServer {
+ 					scope: vscodeBase + '/',
+ 					path: base + '/_static/out/browser/serviceWorker.js',
+ 				},
++				enableTelemetry: this._productService.enableTelemetry,
+ 				embedderIdentifier: 'server-distro',
+ 				extensionsGallery: this._productService.extensionsGallery,
+ 			},
diff --git a/patches/update-check.diff b/patches/update-check.diff
index c36871094f81..941ffa16e59b 100644
--- a/patches/update-check.diff
+++ b/patches/update-check.diff
@@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
  import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
 +import { IProductService } from 'vs/platform/product/common/productService';
 +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
-
+ 
  export class CodeServerClient extends Disposable {
  	constructor (
 +		@ILogService private logService: ILogService,
@@ -98,40 +98,40 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
  	readonly codeServerVersion?: string
  	readonly rootEndpoint?: string
 +	readonly updateEndpoint?: string
-
+ 
  	readonly version: string;
  	readonly date?: string;
 Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -292,6 +292,7 @@ export class WebClientServer {
- 				workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
- 				productConfiguration: <Partial<IProductConfiguration>>{
- 					rootEndpoint: base,
-+					updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
- 					codeServerVersion: this._productService.codeServerVersion,
- 					embedderIdentifier: 'server-distro',
- 					extensionsGallery: {
+@@ -308,6 +308,7 @@ export class WebClientServer {
+ 			productConfiguration: <Partial<IProductConfiguration>>{
+ 				codeServerVersion: this._productService.codeServerVersion,
+ 				rootEndpoint: base,
++				updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
+ 				embedderIdentifier: 'server-distro',
+ 				extensionsGallery: this._productService.extensionsGallery,
+ 			},
 Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
 +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
 @@ -11,6 +11,8 @@ import { refineServiceDecorator } from '
  import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
-
+ 
  export const serverOptions: OptionDescriptions<ServerParsedArgs> = {
 +	/* ----- code-server ----- */
 +	'disable-update-check': { type: 'boolean' },
-
+ 
  	/* ----- server setup ----- */
-
+ 
 @@ -88,6 +90,8 @@ export const serverOptions: OptionDescri
  };
-
+ 
  export interface ServerParsedArgs {
 +	/* ----- code-server ----- */
 +	'disable-update-check'?: boolean;
-
+ 
  	/* ----- server setup ----- */
-
+ 
diff --git a/patches/webview.diff b/patches/webview.diff
index c04847e1bf88..178dff9bada6 100644
--- a/patches/webview.diff
+++ b/patches/webview.diff
@@ -24,73 +24,94 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
 +++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
-@@ -179,7 +179,7 @@ export class BrowserWorkbenchEnvironment
+@@ -183,7 +183,7 @@ export class BrowserWorkbenchEnvironment
  
  	@memoize
  	get webviewExternalEndpoint(): string {
 -		const endpoint = this.options.webviewEndpoint
 +		const endpoint = (this.options.webviewEndpoint && new URL(this.options.webviewEndpoint, window.location.toString()).toString())
  			|| this.productService.webviewContentExternalBaseUrlTemplate
- 			|| 'https://{{uuid}}.vscode-webview.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
+ 			|| 'https://{{uuid}}.vscode-cdn.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
  
 Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
 ===================================================================
 --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
 +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
-@@ -283,6 +283,7 @@ export class WebClientServer {
- 		const data = (await util.promisify(fs.readFile)(filePath)).toString()
- 			.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
- 				remoteAuthority,
-+				webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
- 				_wrapWebWorkerExtHostInIframe,
- 				developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
- 				settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
-Index: code-server/lib/vscode/src/vs/workbench/common/webview.ts
+@@ -298,6 +298,7 @@ export class WebClientServer {
+ 
+ 		const workbenchWebConfiguration = {
+ 			remoteAuthority,
++			webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
+ 			_wrapWebWorkerExtHostInIframe,
+ 			developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
+ 			settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
+Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
 ===================================================================
---- code-server.orig/lib/vscode/src/vs/workbench/common/webview.ts
-+++ code-server/lib/vscode/src/vs/workbench/common/webview.ts
-@@ -22,7 +22,7 @@ export const webviewResourceBaseHost = '
+--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
++++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+@@ -5,7 +5,7 @@
+ 	<meta charset="UTF-8">
  
- export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
+ 	<meta http-equiv="Content-Security-Policy"
+-		content="default-src 'none'; script-src 'sha256-xgIcbQmGjpT42GEj54VFSNh6MI15PZ2D1+DdVehfYBI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
++		content="default-src 'none'; script-src 'sha256-aOCIU83V9nV+0ERJudbrKLqgIVOHqU71i4Lv5urjGTI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
  
--export const webviewGenericCspSource = `https://*.${webviewResourceBaseHost}`;
-+export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost}`;
+ 	<!-- Disable pinch zooming -->
+ 	<meta name="viewport"
+@@ -331,6 +331,12 @@
  
- /**
-  * Construct a uri that can load resources inside a webview
-Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/service-worker.js
-===================================================================
---- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/service-worker.js
-+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/service-worker.js
-@@ -188,9 +188,11 @@ sw.addEventListener('fetch', (event) =>
- 		}
- 	}
+ 				const hostname = location.hostname;
  
--	// If we're making a request against the remote authority, we want to go
--	// back through VS Code itself so that we are authenticated properly
--	if (requestUrl.host === remoteAuthority) {
-+	// If we're making a request against the remote authority, we want to go back
-+	// through VS Code itself so that we are authenticated properly.  If the
-+	// service worker is hosted on the same origin we will have cookies and
-+	// authentication will not be an issue.
-+	if (requestUrl.origin !== sw.origin && requestUrl.host === remoteAuthority) {
- 		switch (event.request.method) {
- 			case 'GET':
- 			case 'HEAD':
-Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
++				// It is safe to run if we are on the same host.
++				const parent = new URL(parentOrigin)
++				if (parent.hostname === hostname) {
++					return start(parentOrigin)
++				}
++
+ 				if (!crypto.subtle) {
+ 					// cannot validate, not running in a secure context
+ 					throw new Error(`Cannot validate in current context!`);
+Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
 ===================================================================
---- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
-+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
-@@ -318,6 +318,12 @@ const hostMessaging = new class HostMess
+--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
++++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
+@@ -330,6 +330,12 @@
  
- 		const hostname = location.hostname;
+ 				const hostname = location.hostname;
  
++				// It is safe to run if we are on the same host.
++				const parent = new URL(parentOrigin)
++				if (parent.hostname === hostname) {
++					return start(parentOrigin)
++				}
++
+ 				if (!crypto.subtle) {
+ 					// cannot validate, not running in a secure context
+ 					throw new Error(`Cannot validate in current context!`);
+Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+===================================================================
+--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
++++ code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+@@ -4,7 +4,7 @@
+ 		<meta http-equiv="Content-Security-Policy" content="
+ 			default-src 'none';
+ 			child-src 'self' data: blob:;
+-			script-src 'self' 'unsafe-eval' 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' https:;
++			script-src 'self' 'unsafe-eval' 'sha256-yHVIAbzODFRINjoLGID5qWPP45HzMtwhyVRC+7yiuXg=' https:;
+ 			connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
+ 	</head>
+ 	<body>
+@@ -23,6 +23,13 @@
+ 			// validation not requested
+ 			return start();
+ 		}
++
 +		// It is safe to run if we are on the same host.
 +		const parent = new URL(parentOrigin)
-+		if (parent.hostname === location.hostname) {
-+			return start(parentOrigin)
++		if (parent.hostname === hostname) {
++			return start()
 +		}
 +
  		if (!crypto.subtle) {
  			// cannot validate, not running in a secure context
- 			throw new Error(`Cannot validate in current context!`);
+ 			return sendError(new Error(`Cannot validate in current context!`));
diff --git a/src/node/routes/vscode.ts b/src/node/routes/vscode.ts
index 8b85b68a5c8e..a0ba3869b367 100644
--- a/src/node/routes/vscode.ts
+++ b/src/node/routes/vscode.ts
@@ -172,7 +172,7 @@ export class CodeServerRouteWrapper {
     this.router.get("/", this.ensureCodeServerLoaded, this.$root)
     this.router.get(/manifest.json$/, this.manifest)
     this.router.all("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyRequest)
-    this._wsRouterWrapper.ws("/", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
+    this._wsRouterWrapper.ws("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
   }
 
   dispose() {
diff --git a/test/unit/node/routes/vscode.test.ts b/test/unit/node/routes/vscode.test.ts
index 88b2c4b2d852..9f453369322a 100644
--- a/test/unit/node/routes/vscode.test.ts
+++ b/test/unit/node/routes/vscode.test.ts
@@ -33,10 +33,10 @@ describe("vscode", () => {
       switch (route) {
         case "/":
         case "/vscode/":
-          expect(html).toContain(`src="./static/`)
+          expect(html).toMatch(/src="\.\/[a-z]+-[0-9a-z]+\/static\//)
           break
         case "/vscode":
-          expect(html).toContain(`src="./vscode/static/`)
+          expect(html).toMatch(/src="\.\/vscode\/[a-z]+-[0-9a-z]+\/static\//)
           break
       }
     }