diff --git a/keyserver/src/responders/website-responders.js b/keyserver/src/responders/website-responders.js
--- a/keyserver/src/responders/website-responders.js
+++ b/keyserver/src/responders/website-responders.js
@@ -43,7 +43,6 @@
   +cssInclude: string,
   +olmFilename: string,
   +commQueryExecutorFilename: string,
-  +opaqueURL: string,
   +backupClientFilename: string,
   +webworkersOpaqueFilename: string,
 };
@@ -60,7 +59,6 @@
       cssInclude: '',
       olmFilename: '',
       commQueryExecutorFilename: '',
-      opaqueURL: 'http://localhost:8080/opaque-ke.wasm',
       backupClientFilename: '',
       webworkersOpaqueFilename: '',
     };
@@ -86,7 +84,6 @@
       `,
       olmFilename: manifest['olm.wasm'],
       commQueryExecutorFilename: webworkersManifest['comm_query_executor.wasm'],
-      opaqueURL: `compiled/${manifest['comm_opaque2_wasm_bg.wasm']}`,
       backupClientFilename: webworkersManifest['backup-client-wasm_bg.wasm'],
       webworkersOpaqueFilename: webworkersManifest['comm_opaque2_wasm_bg.wasm'],
     };
@@ -138,7 +135,6 @@
     fontsURL,
     cssInclude,
     olmFilename,
-    opaqueURL,
     commQueryExecutorFilename,
     backupClientFilename,
     webworkersOpaqueFilename,
@@ -195,7 +191,6 @@
           var commQueryExecutorFilename = "${commQueryExecutorFilename}";
           var backupClientFilename = "${backupClientFilename}";
           var webworkersOpaqueFilename = "${webworkersOpaqueFilename}"
-          var opaqueURL = "${opaqueURL}";
         </script>
         <script src="${jsURL}"></script>
       </body>
diff --git a/web/app.react.js b/web/app.react.js
--- a/web/app.react.js
+++ b/web/app.react.js
@@ -49,7 +49,6 @@
 import { MemberListSidebarProvider } from './chat/member-list-sidebar/member-list-sidebar-provider.react.js';
 import NavigationArrows from './components/navigation-arrows.react.js';
 import { olmAPI } from './crypto/olm-api.js';
-import { initOpaque } from './crypto/opaque-utils.js';
 import electron from './electron.js';
 import InputStateContainer from './input/input-state-container.react.js';
 import InviteLinkHandler from './invite-links/invite-link-handler.react.js';
@@ -83,8 +82,6 @@
 import { canonicalURLFromReduxState, navInfoFromURL } from './url-utils.js';
 import { useWebLock, TUNNELBROKER_LOCK_NAME } from './web-lock.js';
 
-void initOpaque();
-
 // We want Webpack's css-loader and style-loader to handle the Fontawesome CSS,
 // so we disable the autoAddCss logic and import the CSS file. Otherwise every
 // icon flashes huge for a second before the CSS is loaded.
diff --git a/web/grpc/identity-service-client-wrapper.js b/web/grpc/identity-service-client-wrapper.js
--- a/web/grpc/identity-service-client-wrapper.js
+++ b/web/grpc/identity-service-client-wrapper.js
@@ -31,7 +31,6 @@
 import { assertWithValidator } from 'lib/utils/validation-utils.js';
 
 import { VersionInterceptor, AuthInterceptor } from './interceptor.js';
-import { initOpaque } from '../crypto/opaque-utils.js';
 import * as IdentityAuthClient from '../protobufs/identity-auth-client.cjs';
 import * as IdentityAuthStructs from '../protobufs/identity-auth-structs.cjs';
 import {
@@ -45,9 +44,10 @@
   SecondaryDeviceKeysUploadRequest,
 } from '../protobufs/identity-unauth-structs.cjs';
 import * as IdentityUnauthClient from '../protobufs/identity-unauth.cjs';
+import { initOpaque } from '../shared-worker/utils/opaque-utils.js';
 
 class IdentityServiceClientWrapper implements IdentityServiceClient {
-  overridedOpaqueFilepath: ?string;
+  overridedOpaqueFilepath: string;
   authClient: ?IdentityAuthClient.IdentityClientServicePromiseClient;
   unauthClient: IdentityUnauthClient.IdentityClientServicePromiseClient;
   getNewDeviceKeyUpload: () => Promise<IdentityNewDeviceKeyUpload>;
@@ -55,7 +55,7 @@
 
   constructor(
     platformDetails: PlatformDetails,
-    overridedOpaqueFilepath: ?string,
+    overridedOpaqueFilepath: string,
     authLayer: ?IdentityServiceAuthLayer,
     getNewDeviceKeyUpload: () => Promise<IdentityNewDeviceKeyUpload>,
     getExistingDeviceKeyUpload: () => Promise<IdentityExistingDeviceKeyUpload>,
diff --git a/web/crypto/opaque-utils.js b/web/shared-worker/utils/opaque-utils.js
rename from web/crypto/opaque-utils.js
rename to web/shared-worker/utils/opaque-utils.js
--- a/web/crypto/opaque-utils.js
+++ b/web/shared-worker/utils/opaque-utils.js
@@ -2,17 +2,14 @@
 
 import initOpaqueKe from '@commapp/opaque-ke-wasm';
 
-declare var opaqueURL: string;
-
 let opaqueKeLoadingState: void | true | Promise<mixed>;
 
-function initOpaque(overrideOpaqueURL?: ?string): Promise<mixed> {
-  const finalOpaqueURL = overrideOpaqueURL ?? opaqueURL;
+function initOpaque(opaqueURL: string): Promise<mixed> {
   if (opaqueKeLoadingState === true) {
     return Promise.resolve();
   }
   if (!opaqueKeLoadingState) {
-    opaqueKeLoadingState = initOpaqueKe(finalOpaqueURL);
+    opaqueKeLoadingState = initOpaqueKe(opaqueURL);
   }
   return opaqueKeLoadingState;
 }
diff --git a/web/shared-worker/worker/identity-client.js b/web/shared-worker/worker/identity-client.js
--- a/web/shared-worker/worker/identity-client.js
+++ b/web/shared-worker/worker/identity-client.js
@@ -15,6 +15,7 @@
 } from '../../types/worker-types.js';
 import type { EmscriptenModule } from '../types/module.js';
 import type { SQLiteQueryExecutor } from '../types/sqlite-query-executor.js';
+import { initOpaque } from '../utils/opaque-utils.js';
 
 let identityClient: ?IdentityServiceClientWrapper = null;
 
@@ -27,6 +28,7 @@
   if (
     message.type === workerRequestMessageTypes.CREATE_IDENTITY_SERVICE_CLIENT
   ) {
+    void initOpaque(message.opaqueWasmPath);
     identityClient = new IdentityServiceClientWrapper(
       platformDetails,
       message.opaqueWasmPath,
diff --git a/web/webpack.config.cjs b/web/webpack.config.cjs
--- a/web/webpack.config.cjs
+++ b/web/webpack.config.cjs
@@ -64,16 +64,6 @@
         },
       ],
     }),
-    new CopyPlugin({
-      patterns: [
-        {
-          from:
-            'node_modules/@commapp/opaque-ke-wasm' +
-            '/pkg/comm_opaque2_wasm_bg.wasm',
-          to: path.join(__dirname, 'dist', 'opaque-ke.wasm'),
-        },
-      ],
-    }),
   ],
 };
 
@@ -88,16 +78,6 @@
         },
       ],
     }),
-    new CopyPlugin({
-      patterns: [
-        {
-          from:
-            'node_modules/@commapp/opaque-ke-wasm' +
-            '/pkg/comm_opaque2_wasm_bg.wasm',
-          to: path.join(__dirname, 'dist', 'opaque-ke.[contenthash:12].wasm'),
-        },
-      ],
-    }),
     new WebpackManifestPlugin({
       publicPath: '',
     }),