diff --git a/.github/workflows/release_build.yml b/.github/workflows/release_build.yml
new file mode 100644
index 0000000000..7eaa7f3fa4
--- /dev/null
+++ b/.github/workflows/release_build.yml
@@ -0,0 +1,212 @@
+# Copyright 2013-2019 High Fidelity, Inc.
+# Copyright 2020-2022 Vircadia contributors
+# Copyright 2021-2024 Overte e.V.
+# SPDX-License-Identifier: Apache-2.0
+
+name: Windows Release Build
+
+on:
+  push:
+    tags:
+      # Release tags. E.g. 2024.06.1
+      # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
+      - "[0-9][0-9][0-9][0-9].[0-9][0-9].**"
+
+env:
+  APP_NAME: interface
+  BUILD_TYPE: Release
+  CI_BUILD: Github
+  GIT_COMMIT: ${{ github.sha }}
+  PRODUCTION_BUILD: true
+  RELEASE_TYPE: PRODUCTION
+  RELEASE_NUMBER: ${{ github.ref_name }}
+  STABLE_BUILD: 1
+  UPLOAD_BUCKET: overte-public
+  UPLOAD_REGION: fra1
+  UPLOAD_ENDPOINT: "https://fra1.digitaloceanspaces.com"
+  CMAKE_BACKTRACE_URL: ${{ secrets.SENTRY_MINIDUMP_ENDPOINT }}
+  CMAKE_BACKTRACE_TOKEN: ${{ github.ref_name }}_Windows_${{ github.sha }}
+  # Disable VCPKG caching to save time.
+  VCPKG_FEATURE_FLAGS: -binarycaching
+
+  # WIN-specific variables
+  PreferredToolArchitecture: X64
+
+jobs:
+  build:
+    strategy:
+      matrix:
+        include:
+          - os: windows-2019
+            build_type: full
+      fail-fast: false
+    runs-on: ${{matrix.os}}
+    steps:
+    - name: Configure build environment 1
+      shell: bash
+      id: buildenv1
+      run: |
+
+        echo "GIT_COMMIT_SHORT=`echo ${{ github.sha }} | cut -c1-7`" >> $GITHUB_ENV
+
+        if [[ "${{ github.ref_name }}" == *"rc"* ]]; then  # release candidate
+            # The uploader already creates a subfolder for each RELEASE_NUMBER.
+            echo "UPLOAD_PREFIX=build/overte/release-candidate/" >> $GITHUB_ENV
+        else  # release
+            echo "UPLOAD_PREFIX=build/overte/release/" >> $GITHUB_ENV
+        fi
+
+        echo ::set-output name=github_sha_short::`echo $GIT_COMMIT | cut -c1-7`
+        echo "JOB_NAME=${{matrix.os}}, ${{matrix.build_type}}" >> $GITHUB_ENV
+        echo "APP_TARGET_NAME=$APP_NAME" >> $GITHUB_ENV
+
+        echo "PYTHON_EXEC=python" >> $GITHUB_ENV
+        echo "ZIP_COMMAND=7z" >> $GITHUB_ENV
+        echo "ZIP_ARGS=a" >> $GITHUB_ENV
+        echo "INSTALLER_EXT=exe" >> $GITHUB_ENV
+        echo "CMAKE_EXTRA=-A x64" >> $GITHUB_ENV
+        echo "SYMBOL_REGEX=\(exe\|dll\|pdb\)" >> $GITHUB_ENV
+        echo "SYMBOLS_ARCHIVE=$RELEASE_NUMBER-${{ github.sha }}-win-symbols.zip" >> $GITHUB_ENV
+        # echo "HF_PFX_PASSPHRASE=${{secrets.pfx_key}}" >> $GITHUB_ENV
+        # echo "HF_PFX_FILE=${{runner.workspace}}\build\codesign.pfx" >> $GITHUB_ENV
+
+    # Configuration is broken into two steps because you can't set an env var and also reference it in the same step
+    - name: Configure build environment 2
+      shell: bash
+      run: |
+
+        echo "BUILD_NUMBER=$GIT_COMMIT_SHORT" >> $GITHUB_ENV
+        echo "ARTIFACT_PATTERN=Overte-$RELEASE_NUMBER.$INSTALLER_EXT" >> $GITHUB_ENV
+        echo "CLIENT_ONLY=FALSE" >> $GITHUB_ENV
+
+    - uses: actions/checkout@v4
+      with:
+        submodules: false
+        fetch-depth: 1
+
+    - name: Override NSIS
+      shell: pwsh
+      if: startsWith(matrix.os, 'windows')
+      run: choco install nsis --allow-downgrade --version=3.06.1
+
+    - name: Install Python modules
+      if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
+      shell: bash
+      run: $PYTHON_EXEC -m pip install boto3 PyGithub
+
+    - name: Create build environment
+      shell: bash
+      run: cmake -E make_directory "${{runner.workspace}}/build"
+
+    - name: Configure CMake
+      working-directory: ${{runner.workspace}}/build
+      shell: bash
+      run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release -DCLIENT_ONLY:BOOLEAN=$CLIENT_ONLY -DBYPASS_SIGNING:BOOLEAN=TRUE $CMAKE_EXTRA
+
+    - name: Build application
+      working-directory: ${{runner.workspace}}/build
+      shell: bash
+      run: cmake --build . --config $BUILD_TYPE --target $APP_TARGET_NAME $CMAKE_BUILD_EXTRA
+
+    - name: Build domain server
+      working-directory: ${{runner.workspace}}/build
+      shell: bash
+      run: cmake --build . --config $BUILD_TYPE --target domain-server $CMAKE_BUILD_EXTRA
+
+    - name: Build assignment client
+      working-directory: ${{runner.workspace}}/build
+      shell: bash
+      run: cmake --build . --config $BUILD_TYPE --target assignment-client $CMAKE_BUILD_EXTRA
+
+    - name: Build console
+      working-directory: ${{runner.workspace}}/build
+      shell: bash
+      run: cmake --build . --config $BUILD_TYPE --target packaged-server-console $CMAKE_BUILD_EXTRA
+
+    - name: Build installer
+      working-directory: ${{runner.workspace}}/build
+      shell: bash
+      run: |
+        echo "Retry code from https://unix.stackexchange.com/a/137639"
+        function fail {
+          echo $1 >&2
+          exit 1
+        }
+        function retry {
+          local n=1
+          local max=5
+          local delay=15
+          while true; do
+            "$@" && break || {
+              if [[ $n -lt $max ]]; then
+                ((n++))
+                echo "Command failed. Attempt $n/$max:"
+                sleep $delay;
+              else
+                fail "The command has failed after $n attempts."
+              fi
+            }
+          done
+        }
+        retry cmake --build . --config $BUILD_TYPE --target package $CMAKE_BUILD_EXTRA
+
+    #- name: Sign installer (Windows)
+    #  if: startsWith(matrix.os, 'windows')
+    #  shell: powershell
+    #  working-directory: C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64
+    #  run: .\signtool.exe sign /fd sha256 /f ${{runner.workspace}}\build\codesign.pfx /p ${{secrets.pfx_key}} /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 ${{runner.workspace}}\build\${env:ARTIFACT_PATTERN}
+
+    - name: Output system stats
+      if: ${{ always() }}
+      working-directory: ${{runner.workspace}}/build
+      shell: bash
+      run: |
+        echo "Disk usage:"
+        df -h
+
+    - name: Output installer logs
+      if: failure() && startsWith(matrix.os, 'windows')
+      shell: bash
+      working-directory: ${{runner.workspace}}/build
+      run: cat ./_CPack_Packages/win64/NSIS/NSISOutput.log
+
+    - name: Upload artifact to S3
+      shell: bash
+      working-directory: ${{runner.workspace}}/build
+      env:
+        AWS_ACCESS_KEY_ID: ${{ secrets.s3_access_key_id }}
+        AWS_SECRET_ACCESS_KEY: ${{ secrets.s3_secret_access_key }}
+      run: $PYTHON_EXEC $GITHUB_WORKSPACE/tools/ci-scripts/upload.py
+
+    - name: Upload artifact to GitHub
+      uses: actions/upload-artifact@v4
+      with:
+        name: ${{ env.ARTIFACT_PATTERN }}
+        path: ${{runner.workspace}}/build/${{ env.ARTIFACT_PATTERN }}
+        if-no-files-found: error
+
+    - name: Archive symbols
+      if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
+      working-directory: ${{runner.workspace}}
+      shell: bash
+      run: |
+        SYMBOLS_TEMP="symbols-temp"
+        mkdir $SYMBOLS_TEMP
+        find "./build" -regex ".*\.$SYMBOL_REGEX" -exec cp -r {} $SYMBOLS_TEMP \;
+        cd $SYMBOLS_TEMP
+        $ZIP_COMMAND $ZIP_ARGS ../$SYMBOLS_ARCHIVE .
+
+    - name: Upload debug symbols to GitHub
+      uses: actions/upload-artifact@v4
+      with:
+        name: ${{ env.SYMBOLS_ARCHIVE }}
+        path: ${{runner.workspace}}/${{ env.SYMBOLS_ARCHIVE }}
+        if-no-files-found: error
+
+    - name: Clear Working Directories
+      if: contains(matrix.runner, 'linux_aarch64')
+      shell: bash
+      run: |
+        rm -rf ./*
+        rm -rf ~/overte-files
+        rm -rf ~/.cache