diff --git a/Dockerfile b/Dockerfile
index e74920d..a19fa9d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,8 +23,8 @@ RUN node --version && npm --version
# Can be a tag, release, but prefer a commit hash because it's not changeable
# https://github.com/bitwarden/clients/commit/${VAULT_VERSION}
#
-# Using https://github.com/bitwarden/clients/releases/tag/web-v2024.11.2
-ARG VAULT_VERSION=3b71950c55f9524fbf6e6801b2a1daf9ac71a792
+# Using https://github.com/bitwarden/clients/releases/tag/web-v2024.12.0
+ARG VAULT_VERSION=e0c8f2ced997fc279c8ded903471ca3fa0fe5e94
ENV VAULT_VERSION=$VAULT_VERSION
ENV VAULT_FOLDER=bw_clients
ENV CHECKOUT_TAGS=false
diff --git a/patches/v2024.12.0.patch b/patches/v2024.12.0.patch
new file mode 100644
index 0000000..5282c17
--- /dev/null
+++ b/patches/v2024.12.0.patch
@@ -0,0 +1,783 @@
+diff --git a/apps/web/config/base.json b/apps/web/config/base.json
+index e64ef6ebeb..b41ca4219d 100644
+--- a/apps/web/config/base.json
++++ b/apps/web/config/base.json
+@@ -1,11 +1,5 @@
+ {
+ "urls": {},
+- "stripeKey": "pk_test_KPoCfZXu7mznb9uSCPZ2JpTD",
+- "braintreeKey": "sandbox_r72q8jq6_9pnxkwm75f87sdc2",
+- "paypal": {
+- "businessId": "AD3LAUZSNVPJY",
+- "buttonAction": "https://www.sandbox.paypal.com/cgi-bin/webscr"
+- },
+ "dev": {
+ "port": 8080,
+ "allowedHosts": "auto"
+diff --git a/apps/web/src/app/admin-console/organizations/create/organization-information.component.html b/apps/web/src/app/admin-console/organizations/create/organization-information.component.html
+index e0a8006081..789efd9264 100644
+--- a/apps/web/src/app/admin-console/organizations/create/organization-information.component.html
++++ b/apps/web/src/app/admin-console/organizations/create/organization-information.component.html
+@@ -12,7 +12,7 @@
+
+
+
+- {{ "billingEmail" | i18n }}
++ {{ "email" | i18n }}
+
+
+
+diff --git a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts
+index a15882f42d..39958cb881 100644
+--- a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts
++++ b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts
+@@ -127,6 +127,7 @@ export class OrganizationLayoutComponent implements OnInit {
+ }
+
+ canShowBillingTab(organization: Organization): boolean {
++ return false; // disable billing tab in Vaultwarden
+ return canAccessBillingTab(organization);
+ }
+
+diff --git a/apps/web/src/app/admin-console/organizations/members/members.component.ts b/apps/web/src/app/admin-console/organizations/members/members.component.ts
+index 3e61ec2a20..445f813d17 100644
+--- a/apps/web/src/app/admin-console/organizations/members/members.component.ts
++++ b/apps/web/src/app/admin-console/organizations/members/members.component.ts
+@@ -191,11 +191,7 @@ export class MembersComponent extends BaseMembersComponent
+ .find((p) => p.organizationId === this.organization.id);
+ this.orgResetPasswordPolicyEnabled = resetPasswordPolicy?.enabled;
+
+- const billingMetadata = await this.billingApiService.getOrganizationBillingMetadata(
+- this.organization.id,
+- );
+-
+- this.orgIsOnSecretsManagerStandalone = billingMetadata.isOnSecretsManagerStandalone;
++ this.orgIsOnSecretsManagerStandalone = false; // don't get billing metadata
+
+ await this.load();
+
+diff --git a/apps/web/src/app/admin-console/organizations/settings/account.component.html b/apps/web/src/app/admin-console/organizations/settings/account.component.html
+index b3fac56c0b..796a1a817a 100644
+--- a/apps/web/src/app/admin-console/organizations/settings/account.component.html
++++ b/apps/web/src/app/admin-console/organizations/settings/account.component.html
+@@ -16,7 +16,7 @@
+
+
+
+- {{ "billingEmail" | i18n }}
++ {{ "email" | i18n }}
+
+
+
+diff --git a/apps/web/src/app/admin-console/organizations/settings/account.component.ts b/apps/web/src/app/admin-console/organizations/settings/account.component.ts
+index 5182406564..859a7d86f0 100644
+--- a/apps/web/src/app/admin-console/organizations/settings/account.component.ts
++++ b/apps/web/src/app/admin-console/organizations/settings/account.component.ts
+@@ -84,7 +84,7 @@ export class AccountComponent implements OnInit, OnDestroy {
+ ) {}
+
+ async ngOnInit() {
+- this.selfHosted = this.platformUtilsService.isSelfHost();
++ this.selfHosted = false; // set to false so we can rename organizations
+
+ this.route.params
+ .pipe(
+@@ -177,6 +177,7 @@ export class AccountComponent implements OnInit, OnDestroy {
+ };
+
+ submitCollectionManagement = async () => {
++ return; // flexible collections are not supported by Vaultwarden
+ const request = new OrganizationCollectionManagementUpdateRequest();
+ request.limitCollectionCreation =
+ this.collectionManagementFormGroup.value.limitCollectionCreation;
+diff --git a/apps/web/src/app/app.component.html b/apps/web/src/app/app.component.html
+index a39c045e0e..9d72e609b4 100644
+--- a/apps/web/src/app/app.component.html
++++ b/apps/web/src/app/app.component.html
+@@ -3,7 +3,7 @@
+ when the body has the layout_frontend class. Having this match the index allows for a duplicative yet seamless
+ loading state here for process reloading. -->
+
+-
++
+
+
+
+-
+-
+diff --git a/apps/web/src/app/auth/settings/two-factor/two-factor-setup-authenticator.component.ts b/apps/web/src/app/auth/settings/two-factor/two-factor-setup-authenticator.component.ts
+index a018710391..c37847a474 100644
+--- a/apps/web/src/app/auth/settings/two-factor/two-factor-setup-authenticator.component.ts
++++ b/apps/web/src/app/auth/settings/two-factor/two-factor-setup-authenticator.component.ts
+@@ -187,11 +187,11 @@ export class TwoFactorSetupAuthenticatorComponent
+ new window.QRious({
+ element: document.getElementById("qr"),
+ value:
+- "otpauth://totp/Bitwarden:" +
++ "otpauth://totp/Vaultwarden:" +
+ Utils.encodeRFC3986URIComponent(email) +
+ "?secret=" +
+ encodeURIComponent(this.key) +
+- "&issuer=Bitwarden",
++ "&issuer=Vaultwarden",
+ size: 160,
+ });
+ }
+diff --git a/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts b/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts
+index 30ae39d481..37e2db43d2 100644
+--- a/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts
++++ b/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts
+@@ -52,6 +52,7 @@ export class OrgBillingHistoryViewComponent implements OnInit, OnDestroy {
+
+ this.loading = true;
+
++ /* disable billing history
+ const openInvoicesPromise = this.organizationBillingApiService.getBillingInvoices(
+ this.organizationId,
+ "open",
+@@ -85,6 +86,7 @@ export class OrgBillingHistoryViewComponent implements OnInit, OnDestroy {
+ openInvoices.length <= pageSize ||
+ paidInvoices.length <= pageSize ||
+ transactions.length <= pageSize;
++ */
+
+ this.loading = false;
+ }
+diff --git a/apps/web/src/app/billing/organizations/organization-plans.component.html b/apps/web/src/app/billing/organizations/organization-plans.component.html
+index e1b74abea7..aff83361b6 100644
+--- a/apps/web/src/app/billing/organizations/organization-plans.component.html
++++ b/apps/web/src/app/billing/organizations/organization-plans.component.html
+@@ -6,7 +6,7 @@
+ >
+
{{ "loading" | i18n }}
+
+-
++
+
+ {{ "uploadLicenseFileOrg" | i18n }}
+
+-