diff --git a/out/asar/asarUtil.js b/out/asar/asarUtil.js
index bea8a3b1b2ab56d99ea3679eb88aaf0b4b646803..622e362315642a7144021bbb885e571e9e948e07 100644
--- a/out/asar/asarUtil.js
+++ b/out/asar/asarUtil.js
@@ -149,15 +149,24 @@ class AsarPackager {
             if (a === b) {
                 return 0;
             }
+            // SIGNAL CHANGE START
             // Place addons last because their signature changes per build
-            const isAAddon = a.endsWith(".node");
-            const isBAddon = b.endsWith(".node");
-            if (isAAddon && !isBAddon) {
+            function isFickle(name) {
+              return name.endsWith(".node") ||
+                name.endsWith(path.sep + "local-production.json") ||
+                name.endsWith(path.sep + "preload.bundle.js") ||
+                name.endsWith(path.sep + "preload.bundle.cache") ||
+                name.endsWith(path.sep + "package.json");
+            }
+            const isAFickle = isFickle(a);
+            const isBFickle = isFickle(b);
+            if (isAFickle && !isBFickle) {
                 return 1;
             }
-            if (isBAddon && !isAAddon) {
+            if (isBFickle && !isAFickle) {
                 return -1;
             }
+            // SIGNAL CHANGE END
             // Otherwise order by name
             return a < b ? -1 : 1;
         });
diff --git a/out/targets/FpmTarget.js b/out/targets/FpmTarget.js
index 47e6f48fcbed88b6ac07cff15c888c1b8b59721f..76dd6cc7265054222f2d70c76aa8456d550f29d1 100644
--- a/out/targets/FpmTarget.js
+++ b/out/targets/FpmTarget.js
@@ -30,6 +30,7 @@ class FpmTarget extends core_1.Target {
         const templateOptions = {
             // old API compatibility
             executable: packager.executableName,
+            sanitizedName: packager.appInfo.sanitizedName,
             sanitizedProductName: packager.appInfo.sanitizedProductName,
             productFilename: packager.appInfo.productFilename,
             ...packager.platformSpecificBuildOptions,
diff --git a/templates/linux/after-install.tpl b/templates/linux/after-install.tpl
index 6cf860bd2847bae35ca8885cb680dd6c8c516e39..a3cb08a6dc7970ab2b32c731f41ea6e471204a19 100644
--- a/templates/linux/after-install.tpl
+++ b/templates/linux/after-install.tpl
@@ -55,3 +55,26 @@ if apparmor_status --enabled > /dev/null 2>&1; then
     echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile"
   fi
 fi
+
+# SIGNAL CHANGES BEGIN
+
+if command -v pkcheck >/dev/null 2>&1; then
+  POLICY_SOURCE_PATH='/opt/${sanitizedProductName}/resources'
+  POLICY_TARGET_PATH='/usr/share/polkit-1/actions'
+  POLICY_ORG='org.signalapp'
+  POLICY_ENABLE_BACKUPS='enable-backups.policy'
+  POLICY_VIEW_AEP='view-aep.policy'
+  POLICY_EXPORT='plaintext-export.policy'
+  mkdir -p "$POLICY_TARGET_PATH";
+  # Separate policies for staging and production builds
+  cp -f "$POLICY_SOURCE_PATH/$POLICY_ORG.$POLICY_ENABLE_BACKUPS" "$POLICY_TARGET_PATH/$POLICY_ORG.${sanitizedName}.$POLICY_ENABLE_BACKUPS"
+  cp -f "$POLICY_SOURCE_PATH/$POLICY_ORG.$POLICY_VIEW_AEP" "$POLICY_TARGET_PATH/$POLICY_ORG.${sanitizedName}.$POLICY_VIEW_AEP"
+  cp -f "$POLICY_SOURCE_PATH/$POLICY_ORG.$POLICY_EXPORT" "$POLICY_TARGET_PATH/$POLICY_ORG.${sanitizedName}.$POLICY_EXPORT"
+else
+  echo "Skipping installation of policies as polkit does not seem to be installed. This may affect the availability of some features.";
+fi
+
+# Notify updater that the update was fully installed
+touch '/opt/${sanitizedProductName}/.signal-postinst'
+
+# SIGNAL CHANGES END
diff --git a/templates/linux/after-remove.tpl b/templates/linux/after-remove.tpl
index 19b3decabe18a816f9ed5440fa9124ebfd6e3907..b5011d1b8cdb741ba6453f942a3c0660b66d41a0 100644
--- a/templates/linux/after-remove.tpl
+++ b/templates/linux/after-remove.tpl
@@ -13,3 +13,12 @@ APPARMOR_PROFILE_DEST='/etc/apparmor.d/${executable}'
 if [ -f "$APPARMOR_PROFILE_DEST" ]; then
   rm -f "$APPARMOR_PROFILE_DEST"
 fi
+
+# SIGNAL CHANGES BEGIN
+
+POLKIT_TARGET_PATH='/usr/share/polkit-1/actions'
+if [ -d "$POLKIT_TARGET_PATH" ]; then
+  rm -f $POLKIT_TARGET_PATH/org.signalapp.${sanitizedName}.*.policy
+fi
+
+# SIGNAL CHANGES END
\ No newline at end of file
diff --git a/templates/nsis/include/installer.nsh b/templates/nsis/include/installer.nsh
index 34e91dfe82fdbb2e929820f2e8deb771b7f7893c..73bfffc6c227a018cbbeb690d6d7b882ed142fc8 100644
--- a/templates/nsis/include/installer.nsh
+++ b/templates/nsis/include/installer.nsh
@@ -90,7 +90,13 @@
       ${if} $installMode == "all"
         SetShellVarContext current
       ${endif}
-      !insertmacro copyFile "$EXEPATH" "$LOCALAPPDATA\${APP_INSTALLER_STORE_FILE}"
+      # SIGNAL CHANGE START
+      # This file is needed for electron-builder's native incremental updates,
+      # but we have our own system so no need to place it. Clean it up instead.
+      #
+      # !insertmacro copyFile "$EXEPATH" "$LOCALAPPDATA\${APP_INSTALLER_STORE_FILE}"
+      RMDir /r /REBOOTOK "$LOCALAPPDATA\signal-desktop-updater"
+      # SIGNAL CHANGE END
       ${if} $installMode == "all"
         SetShellVarContext all
       ${endif}
diff --git a/templates/nsis/installSection.nsh b/templates/nsis/installSection.nsh
index 053772f55ca6ece52f0a34c4fa0f05c9a5f07bd2..a58ea8c19116f8ec3fb7515ec4104282f635ecc8 100644
--- a/templates/nsis/installSection.nsh
+++ b/templates/nsis/installSection.nsh
@@ -22,11 +22,37 @@ StrCpy $appExe "$INSTDIR\${APP_EXECUTABLE_FILENAME}"
       SpiderBanner::Show /MODERN
     !endif
 
+    # Set text (1000 is the id of text element of SpiderBanner)
     FindWindow $0 "#32770" "" $hwndparent
     FindWindow $0 "#32770" "" $hwndparent $0
-    GetDlgItem $0 $0 1000
-    SendMessage $0 ${WM_SETTEXT} 0 "STR:$(installing)"
 
+    GetDlgItem $1 $0 1000
+    SendMessage $1 ${WM_SETTEXT} 0 "STR:$(installing)"
+
+    # Set header image compatible with "ManifestDPIAware" mode.
+    !ifdef HEADER_ICO
+      # Convert 24 Dialog Units to pixels:
+      # See https://github.com/mozilla/gecko-dev/blob/8de0e699002872d969aebf1bc8407e5c839a4472/toolkit/mozapps/installer/windows/nsis/common.nsh#L8801
+
+      # rect = LPRect { .left = 0, .top = 0, .right = 24, .bottom = 0 }
+      # See https://nsis.sourceforge.io/Docs/System/System.html#faq
+      System::Call "*(i 0, i 0, i 24, i 0) p.r1"
+
+      # Call `MapDialogRect(window, &rect)`
+      System::Call `user32::MapDialogRect(p $0, p r1)`
+
+      # rect.right now contains the converted value (24du => ?px).
+      # Place `rect.right` into `r2`
+      System::Call "*$1(i, i, i.r2, i)"
+      System::Free $1
+
+      # Load image and pass `r2` as both width and height, get the image handle
+      # back to `r2` register.
+      System::Call `user32::LoadImage(i 0, t "$PLUGINSDIR\installerHeaderico.ico", i ${IMAGE_ICON}, i r2, i r2, i ${LR_LOADFROMFILE}) i.r2`
+      # 1025 is the id of the icon of SpiderBanner.
+      GetDlgItem $1 $0 1025
+      SendMessage $1 ${STM_SETIMAGE} ${IMAGE_ICON} $2
+    !endif
     StrCpy $1 $hwndparent
 		System::Call 'user32::ShutdownBlockReasonCreate(${SYSTYPE_PTR}r1, w "$(installing)")'
   ${endif}
