diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index f8cd67e..765e758 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -3,8 +3,6 @@ on:
   pull_request: {}
   push:
     branches: [main]
-env:
-  VITE_DEFAULT_HOMESERVER: "https://call.ems.host"
 jobs:
   build:
     name: Build
diff --git a/config/element_io_develop.json b/config/element_io_develop.json
index 15198ec..caeddc6 100644
--- a/config/element_io_develop.json
+++ b/config/element_io_develop.json
@@ -1,4 +1,10 @@
 {
+  "default_server_config": {
+    "m.homeserver": {
+      "base_url": "https://call.ems.host",
+      "server_name": "call.ems.host"
+    }
+  },
   "posthog": {
     "api_key": "phc_MhClVy9DiV20vazSYIiedFkM5Xi3z1LPBwrdn9PYZQQ",
     "api_host": "https://app.posthog.com"
diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx
index a48101f..fa83f5d 100644
--- a/src/ClientContext.tsx
+++ b/src/ClientContext.tsx
@@ -32,7 +32,6 @@ import { useTranslation } from "react-i18next";
 import { ErrorView } from "./FullScreenView";
 import {
   initClient,
-  defaultHomeserver,
   CryptoStoreIntegrityError,
   fallbackICEServerAllowed,
 } from "./matrix-utils";
@@ -40,6 +39,7 @@ import { widget } from "./widget";
 import { PosthogAnalytics, RegistrationType } from "./PosthogAnalytics";
 import { translatedError } from "./TranslatedError";
 import { useEventTarget } from "./useEvents";
+import { Config } from "./config/Config";
 
 declare global {
   interface Window {
@@ -139,7 +139,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
             return {
               client: await initClient(
                 {
-                  baseUrl: defaultHomeserver,
+                  baseUrl: Config.defaultHomeserverUrl(),
                   accessToken: access_token,
                   userId: user_id,
                   deviceId: device_id,
@@ -155,7 +155,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
               try {
                 const client = await initClient(
                   {
-                    baseUrl: defaultHomeserver,
+                    baseUrl: Config.defaultHomeserverUrl(),
                     accessToken: access_token,
                     userId: user_id,
                     deviceId: device_id,
diff --git a/src/PosthogAnalytics.ts b/src/PosthogAnalytics.ts
index 0e40ab0..9e5b245 100644
--- a/src/PosthogAnalytics.ts
+++ b/src/PosthogAnalytics.ts
@@ -114,8 +114,8 @@ export class PosthogAnalytics {
 
   constructor(private readonly posthog: PostHog) {
     const posthogConfig: PosthogSettings = {
-      project_api_key: Config.instance.config.posthog?.api_key,
-      api_host: Config.instance.config.posthog?.api_host,
+      project_api_key: Config.get().posthog?.api_key,
+      api_host: Config.get().posthog?.api_host,
     };
 
     if (posthogConfig.project_api_key && posthogConfig.api_host) {
diff --git a/src/auth/LoginPage.tsx b/src/auth/LoginPage.tsx
index 3dc4840..88296db 100644
--- a/src/auth/LoginPage.tsx
+++ b/src/auth/LoginPage.tsx
@@ -14,14 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import React, {
-  FC,
-  FormEvent,
-  useCallback,
-  useRef,
-  useState,
-  useMemo,
-} from "react";
+import React, { FC, FormEvent, useCallback, useRef, useState } from "react";
 import { useHistory, useLocation, Link } from "react-router-dom";
 import { Trans, useTranslation } from "react-i18next";
 
@@ -29,11 +22,11 @@ import { ReactComponent as Logo } from "../icons/LogoLarge.svg";
 import { useClient } from "../ClientContext";
 import { FieldRow, InputField, ErrorMessage } from "../input/Input";
 import { Button } from "../button";
-import { defaultHomeserver, defaultHomeserverHost } from "../matrix-utils";
 import styles from "./LoginPage.module.css";
 import { useInteractiveLogin } from "./useInteractiveLogin";
 import { usePageTitle } from "../usePageTitle";
 import { PosthogAnalytics } from "../PosthogAnalytics";
+import { Config } from "../config/Config";
 
 export const LoginPage: FC = () => {
   const { t } = useTranslation();
@@ -41,7 +34,7 @@ export const LoginPage: FC = () => {
 
   const { setClient } = useClient();
   const login = useInteractiveLogin();
-  const homeserver = defaultHomeserver; // TODO: Make this configurable
+  const homeserver = Config.defaultHomeserverUrl(); // TODO: Make this configurable
   const usernameRef = useRef<HTMLInputElement>();
   const passwordRef = useRef<HTMLInputElement>();
   const history = useHistory();
@@ -75,14 +68,6 @@ export const LoginPage: FC = () => {
     [login, location, history, homeserver, setClient]
   );
 
-  const homeserverHost = useMemo(() => {
-    try {
-      return new URL(homeserver).host;
-    } catch (error) {
-      return defaultHomeserverHost;
-    }
-  }, [homeserver]);
-
   return (
     <>
       <div className={styles.container}>
@@ -102,7 +87,7 @@ export const LoginPage: FC = () => {
                   autoCorrect="off"
                   autoCapitalize="none"
                   prefix="@"
-                  suffix={`:${homeserverHost}`}
+                  suffix={`:${Config.defaultServerName()}`}
                 />
               </FieldRow>
               <FieldRow>
diff --git a/src/auth/RegisterPage.tsx b/src/auth/RegisterPage.tsx
index 9da1d32..f5025b8 100644
--- a/src/auth/RegisterPage.tsx
+++ b/src/auth/RegisterPage.tsx
@@ -31,7 +31,6 @@ import { Trans, useTranslation } from "react-i18next";
 import { FieldRow, InputField, ErrorMessage } from "../input/Input";
 import { Button } from "../button";
 import { useClient } from "../ClientContext";
-import { defaultHomeserverHost } from "../matrix-utils";
 import { useInteractiveRegistration } from "./useInteractiveRegistration";
 import styles from "./LoginPage.module.css";
 import { ReactComponent as Logo } from "../icons/LogoLarge.svg";
@@ -40,6 +39,7 @@ import { useRecaptcha } from "./useRecaptcha";
 import { Caption, Link } from "../typography/Typography";
 import { usePageTitle } from "../usePageTitle";
 import { PosthogAnalytics } from "../PosthogAnalytics";
+import { Config } from "../config/Config";
 
 export const RegisterPage: FC = () => {
   const { t } = useTranslation();
@@ -165,7 +165,7 @@ export const RegisterPage: FC = () => {
                   autoCorrect="off"
                   autoCapitalize="none"
                   prefix="@"
-                  suffix={`:${defaultHomeserverHost}`}
+                  suffix={`:${Config.defaultServerName()}`}
                 />
               </FieldRow>
               <FieldRow>
diff --git a/src/auth/useInteractiveLogin.ts b/src/auth/useInteractiveLogin.ts
index ae0c855..4db466e 100644
--- a/src/auth/useInteractiveLogin.ts
+++ b/src/auth/useInteractiveLogin.ts
@@ -18,7 +18,7 @@ import { useCallback } from "react";
 import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
 import { createClient, MatrixClient } from "matrix-js-sdk/src/matrix";
 
-import { initClient, defaultHomeserver } from "../matrix-utils";
+import { initClient } from "../matrix-utils";
 import { Session } from "../ClientContext";
 
 export const useInteractiveLogin = () =>
@@ -59,7 +59,7 @@ export const useInteractiveLogin = () =>
 
     const client = await initClient(
       {
-        baseUrl: defaultHomeserver,
+        baseUrl: homeserver,
         accessToken: access_token,
         userId: user_id,
         deviceId: device_id,
diff --git a/src/auth/useInteractiveRegistration.ts b/src/auth/useInteractiveRegistration.ts
index 6b25c29..bfc7b2a 100644
--- a/src/auth/useInteractiveRegistration.ts
+++ b/src/auth/useInteractiveRegistration.ts
@@ -18,8 +18,9 @@ import { useState, useEffect, useCallback, useRef } from "react";
 import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
 import { createClient, MatrixClient } from "matrix-js-sdk/src/matrix";
 
-import { initClient, defaultHomeserver } from "../matrix-utils";
+import { initClient } from "../matrix-utils";
 import { Session } from "../ClientContext";
+import { Config } from "../config/Config";
 
 export const useInteractiveRegistration = (): [
   string,
@@ -37,7 +38,9 @@ export const useInteractiveRegistration = (): [
 
   const authClient = useRef<MatrixClient>();
   if (!authClient.current) {
-    authClient.current = createClient({ baseUrl: defaultHomeserver });
+    authClient.current = createClient({
+      baseUrl: Config.defaultHomeserverUrl(),
+    });
   }
 
   useEffect(() => {
@@ -92,7 +95,7 @@ export const useInteractiveRegistration = (): [
 
       const client = await initClient(
         {
-          baseUrl: defaultHomeserver,
+          baseUrl: Config.defaultHomeserverUrl(),
           accessToken: access_token,
           userId: user_id,
           deviceId: device_id,
diff --git a/src/config/Config.ts b/src/config/Config.ts
index 2806a5b..cabd460 100644
--- a/src/config/Config.ts
+++ b/src/config/Config.ts
@@ -22,13 +22,15 @@ import {
 
 export class Config {
   private static internalInstance: Config;
-  public static get instance(): Config {
-    if (!this.internalInstance)
+
+  public static get(): ConfigOptions {
+    if (!this.internalInstance?.config)
       throw new Error("Config instance read before config got initialized");
-    return this.internalInstance;
+    return this.internalInstance.config;
   }
+
   public static init(): Promise<void> {
-    if (Config?.internalInstance?.initPromise) {
+    if (Config.internalInstance?.initPromise) {
       return Config.internalInstance.initPromise;
     }
     Config.internalInstance = new Config();
@@ -41,8 +43,17 @@ export class Config {
     return Config.internalInstance.initPromise;
   }
 
-  public config: ResolvedConfigOptions;
-  private initPromise: Promise<void>;
+  // Convenience accessors
+  public static defaultHomeserverUrl(): string | undefined {
+    return Config.get().default_server_config["m.homeserver"].base_url;
+  }
+
+  public static defaultServerName(): string | undefined {
+    return Config.get().default_server_config["m.homeserver"].server_name;
+  }
+
+  public config?: ResolvedConfigOptions;
+  private initPromise?: Promise<void>;
 }
 
 async function downloadConfig(
@@ -59,7 +70,7 @@ async function downloadConfig(
     // Lack of a config isn't an error, we should just use the defaults.
     // Also treat a blank config as no config, assuming the status code is 0, because we don't get 404s from file:
     // URIs so this is the only way we can not fail if the file doesn't exist when loading from a file:// URI.
-    return {};
+    return DEFAULT_CONFIG;
   }
 
   return res.json();
diff --git a/src/config/ConfigOptions.ts b/src/config/ConfigOptions.ts
index 92dd74f..e799d59 100644
--- a/src/config/ConfigOptions.ts
+++ b/src/config/ConfigOptions.ts
@@ -19,21 +19,33 @@ export interface ConfigOptions {
   rageshake?: {
     submit_url: string;
   };
+
+  // Describes the default homeserver to use. The same format as Element Web
+  // (without identity servers as we don't use them).
+  default_server_config?: {
+    ["m.homeserver"]: {
+      base_url: string;
+      server_name: string;
+    };
+  };
 }
 
+// Overrides members from ConfigOptions that are always provided by the
+// default config and are therefore non-optional.
 export interface ResolvedConfigOptions extends ConfigOptions {
-  sentry: {
-    DSN: string;
-    environment: string;
-  };
-  rageshake: {
-    submit_url: string;
+  default_server_config: {
+    ["m.homeserver"]: {
+      base_url: string;
+      server_name: string;
+    };
   };
 }
 
 export const DEFAULT_CONFIG: ResolvedConfigOptions = {
-  sentry: { DSN: "", environment: "production" },
-  rageshake: {
-    submit_url: "https://element.io/bugreports/submit",
+  default_server_config: {
+    ["m.homeserver"]: {
+      base_url: "http://localhost:8008",
+      server_name: "localhost",
+    },
   },
 };
diff --git a/src/initializer.tsx b/src/initializer.tsx
index 6290764..63b90fc 100644
--- a/src/initializer.tsx
+++ b/src/initializer.tsx
@@ -23,7 +23,6 @@ import * as Sentry from "@sentry/react";
 
 import { getUrlParams } from "./UrlParams";
 import { Config } from "./config/Config";
-import { DEFAULT_CONFIG } from "./config/ConfigOptions";
 
 enum LoadState {
   None,
@@ -192,19 +191,21 @@ export class Initializer {
       this.loadStates.sentry === LoadState.None &&
       this.loadStates.config === LoadState.Loaded
     ) {
-      Sentry.init({
-        dsn: Config.instance.config.sentry?.DSN ?? DEFAULT_CONFIG.sentry.DSN,
-        environment:
-          Config.instance.config.sentry.environment ??
-          DEFAULT_CONFIG.sentry.environment,
-        integrations: [
-          new Integrations.BrowserTracing({
-            routingInstrumentation:
-              Sentry.reactRouterV5Instrumentation(history),
-          }),
-        ],
-        tracesSampleRate: 1.0,
-      });
+      if (Config.get().sentry?.DSN && Config.get().sentry?.environment) {
+        Sentry.init({
+          dsn: Config.get().sentry?.DSN,
+          environment: Config.get().sentry?.environment,
+          integrations: [
+            new Integrations.BrowserTracing({
+              routingInstrumentation:
+                Sentry.reactRouterV5Instrumentation(history),
+            }),
+          ],
+          tracesSampleRate: 1.0,
+        });
+      }
+      // Sentry is now 'loadeed' (even if we actually skipped starting
+      // it due to to not being configured)
       this.loadStates.sentry = LoadState.Loaded;
     }
 
diff --git a/src/matrix-utils.ts b/src/matrix-utils.ts
index fdb5938..2d124a0 100644
--- a/src/matrix-utils.ts
+++ b/src/matrix-utils.ts
@@ -19,15 +19,11 @@ import type { Room } from "matrix-js-sdk/src/models/room";
 import IndexedDBWorker from "./IndexedDBWorker?worker";
 import { getUrlParams } from "./UrlParams";
 import { loadOlm } from "./olm";
+import { Config } from "./config/Config";
 
-export const defaultHomeserver =
-  (import.meta.env.VITE_DEFAULT_HOMESERVER as string) ??
-  `${window.location.protocol}//${window.location.host}`;
 export const fallbackICEServerAllowed =
   import.meta.env.VITE_FALLBACK_STUN_ALLOWED === "true";
 
-export const defaultHomeserverHost = new URL(defaultHomeserver).host;
-
 export class CryptoStoreIntegrityError extends Error {
   constructor() {
     super("Crypto store data was expected, but none was found");
@@ -206,7 +202,7 @@ export function roomNameFromRoomId(roomId: string): string {
     .toLowerCase();
 }
 
-export function isLocalRoomId(roomId: string): boolean {
+export function isLocalRoomId(roomId: string, client: MatrixClient): boolean {
   if (!roomId) {
     return false;
   }
@@ -217,7 +213,7 @@ export function isLocalRoomId(roomId: string): boolean {
     return false;
   }
 
-  return parts[1] === defaultHomeserverHost;
+  return parts[1] === client.getDomain();
 }
 
 export async function createRoom(
@@ -291,11 +287,12 @@ export async function createRoom(
   return [fullAliasFromRoomName(name, client), result.room_id];
 }
 
+// Returns a URL to that will load Element Call with the given room
 export function getRoomUrl(roomIdOrAlias: string): string {
   if (roomIdOrAlias.startsWith("#")) {
     const [localPart, host] = roomIdOrAlias.replace("#", "").split(":");
 
-    if (host !== defaultHomeserverHost) {
+    if (host !== Config.defaultServerName()) {
       return `${window.location.protocol}//${window.location.host}/room/${roomIdOrAlias}`;
     } else {
       return `${window.location.protocol}//${window.location.host}/${localPart}`;
diff --git a/src/room/RoomRedirect.tsx b/src/room/RoomRedirect.tsx
index eeef083..f52abf6 100644
--- a/src/room/RoomRedirect.tsx
+++ b/src/room/RoomRedirect.tsx
@@ -17,9 +17,11 @@ limitations under the License.
 import React, { useEffect } from "react";
 import { useLocation, useHistory } from "react-router-dom";
 
-import { defaultHomeserverHost } from "../matrix-utils";
+import { Config } from "../config/Config";
 import { LoadingView } from "../FullScreenView";
 
+// A component that, when loaded, redirects the client to a full room URL
+// based on the current URL being an abbreviated room URL
 export function RoomRedirect() {
   const { pathname } = useLocation();
   const history = useHistory();
@@ -32,7 +34,7 @@ export function RoomRedirect() {
     }
 
     if (!roomId.startsWith("#") && !roomId.startsWith("!")) {
-      roomId = `#${roomId}:${defaultHomeserverHost}`;
+      roomId = `#${roomId}:${Config.defaultServerName()}`;
     }
 
     history.replace(`/room/${roomId.toLowerCase()}`);
diff --git a/src/room/useLoadGroupCall.ts b/src/room/useLoadGroupCall.ts
index eae23b9..5b2a976 100644
--- a/src/room/useLoadGroupCall.ts
+++ b/src/room/useLoadGroupCall.ts
@@ -61,7 +61,7 @@ export const useLoadGroupCall = (
         return room;
       } catch (error) {
         if (
-          isLocalRoomId(roomIdOrAlias) &&
+          isLocalRoomId(roomIdOrAlias, client) &&
           (error.errcode === "M_NOT_FOUND" ||
             (error.message &&
               error.message.indexOf("Failed to fetch alias") !== -1))
diff --git a/src/settings/submit-rageshake.ts b/src/settings/submit-rageshake.ts
index b8064d8..8a77004 100644
--- a/src/settings/submit-rageshake.ts
+++ b/src/settings/submit-rageshake.ts
@@ -25,7 +25,6 @@ import { useClient } from "../ClientContext";
 import { InspectorContext } from "../room/GroupCallInspector";
 import { useModalTriggerState } from "../Modal";
 import { Config } from "../config/Config";
-import { DEFAULT_CONFIG } from "../config/ConfigOptions";
 
 interface RageShakeSubmitOptions {
   sendLogs: boolean;
@@ -54,6 +53,10 @@ export function useSubmitRageshake(): {
 
   const submitRageshake = useCallback(
     async (opts) => {
+      if (!Config.get().rageshake?.submit_url) {
+        throw new Error("No rageshake URL is configured");
+      }
+
       if (sending) {
         return;
       }
@@ -258,14 +261,10 @@ export function useSubmitRageshake(): {
           );
         }
 
-        await fetch(
-          Config.instance.config.rageshake?.submit_url ??
-            DEFAULT_CONFIG.rageshake.submit_url,
-          {
-            method: "POST",
-            body,
-          }
-        );
+        await fetch(Config.get().rageshake?.submit_url, {
+          method: "POST",
+          body,
+        });
 
         setState({ sending: false, sent: true, error: null });
       } catch (error) {