diff --git a/.github/workflows/analysis-reviewdog-cppcheck.yml b/.github/workflows/analysis-reviewdog-cppcheck.yml
index 4098ccbdcda..5d940bfeaaf 100644
--- a/.github/workflows/analysis-reviewdog-cppcheck.yml
+++ b/.github/workflows/analysis-reviewdog-cppcheck.yml
@@ -12,7 +12,7 @@ on:
 jobs:
 
   cppcheck:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
       - name: Cancel Previous Runs
         if: github.ref != 'refs/heads/main'
diff --git a/.github/workflows/analysis-reviewdog.yml b/.github/workflows/analysis-reviewdog.yml
index b3bf0b562e6..9da05a76869 100644
--- a/.github/workflows/analysis-reviewdog.yml
+++ b/.github/workflows/analysis-reviewdog.yml
@@ -6,7 +6,7 @@ on:
 
 jobs:
   luac:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
       - name: Cancel Previous Runs
         if: github.ref != 'refs/heads/main'
@@ -34,7 +34,7 @@ jobs:
 
 
   luacheck:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
 
       - name: Check out code.
@@ -56,7 +56,7 @@ jobs:
 
 
   shellcheck:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
 
       - name: Check out code.
@@ -72,7 +72,7 @@ jobs:
 
 
   xmllint:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
 
       - name: Check out code.
@@ -94,7 +94,7 @@ jobs:
 
 
   yamllint:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
 
       - name: Check out code.
@@ -108,7 +108,7 @@ jobs:
 
 
   hadolint:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
 
       - name: Check out code
@@ -120,7 +120,7 @@ jobs:
           reporter: github-pr-check
 
   actionlint:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
 
       - name: Check out code
diff --git a/.github/workflows/build-ubuntu-arm.yml b/.github/workflows/build-ubuntu-arm.yml
new file mode 100644
index 00000000000..d182cd10097
--- /dev/null
+++ b/.github/workflows/build-ubuntu-arm.yml
@@ -0,0 +1,94 @@
+---
+name: Build - Ubuntu - ARM
+
+on:
+  workflow_dispatch:
+  pull_request:
+    types: [opened, synchronize, reopened, ready_for_review]
+    paths:
+      - 'src/**'
+  push:
+    paths:
+      - 'src/**'
+
+env:
+  CMAKE_BUILD_PARALLEL_LEVEL: 4
+  MAKEFLAGS: '-j 4'
+
+jobs:
+  job:
+    if: ${{ github.event_name == 'push' || !github.event.pull_request.draft }}
+    name: ${{ matrix.os }}-${{ matrix.buildtype }}
+    runs-on: ${{ matrix.os }}
+
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [Beats-ARM]
+        buildtype: [linux-release, linux-debug]
+        include:
+          - os: Beats-ARM
+            triplet: x64-linux
+
+    steps:
+      - name: Cancel Previous Runs
+        if: github.ref != 'refs/heads/main'
+        uses: fkirc/skip-duplicate-actions@master
+        with:
+          concurrent_skipping: 'same_content'
+          cancel_others: true
+
+      - name: Checkout repository
+        uses: actions/checkout@main
+
+      - name: Install Linux Dependencies
+        run: >
+          sudo apt-get update && sudo apt-get install ccache linux-headers-$(uname -r)
+
+      - name: CCache
+        uses: hendrikmuhs/ccache-action@main
+        with:
+          max-size: "1G"
+          key: ccache-${{ matrix.os }}-${{ matrix.buildtype }}
+          restore-keys: |
+            ccache-${{ matrix.os }}
+
+      - name: Restore artifacts and install vcpkg
+        id: vcpkg-step
+        run: |
+          vcpkgCommitId=$(grep '.builtin-baseline' vcpkg.json | awk -F: '{print $2}' | tr -d '," ')
+          echo "vcpkg commit ID: $vcpkgCommitId"
+          echo "VCPKG_GIT_COMMIT_ID=$vcpkgCommitId" >> $GITHUB_ENV
+
+      - name: Get vcpkg commit id from vcpkg.json
+        uses: lukka/run-vcpkg@main
+        with:
+          vcpkgGitURL: "https://github.com/microsoft/vcpkg.git"
+          vcpkgGitCommitId: ${{ env.VCPKG_GIT_COMMIT_ID }}
+
+      - name: Get latest CMake and ninja
+        uses: lukka/get-cmake@main
+
+      - name: Run CMake
+        uses: lukka/run-cmake@main
+        with:
+          configurePreset: ${{ matrix.buildtype }}
+          buildPreset: ${{ matrix.buildtype }}
+          configurePresetAdditionalArgs: "['-DBUILD_TESTS=ON']"
+
+      - name: Create and Upload Artifact
+        uses: actions/upload-artifact@main
+        with:
+          name: canary-${{ matrix.os }}-${{ matrix.buildtype }}-${{ github.sha }}
+          path: |
+            ${{ github.workspace }}/build/${{ matrix.buildtype }}/bin/
+
+      - name: Run Unit Tests
+        run: |
+          cd ${{ github.workspace }}/build/${{ matrix.buildtype }}/tests/unit
+          ctest --verbose
+
+#      - name: Run Integration Tests
+#        run: |
+#          cd ${{ github.workspace }}/build/${{ matrix.buildtype }}/tests/integration
+#          ctest --verbose
diff --git a/.github/workflows/lua-format.yml b/.github/workflows/lua-format.yml
index 57caa336668..74b15aa4196 100644
--- a/.github/workflows/lua-format.yml
+++ b/.github/workflows/lua-format.yml
@@ -9,7 +9,7 @@ on:
       - 'data*/**'
 jobs:
   lua-formatter:
-    runs-on: ubuntu-latest
+    runs-on: Beats-ARM
     steps:
       - name: Set up Git
         if: ${{ github.ref != 'refs/heads/main' }}
diff --git a/cmake/modules/BaseConfig.cmake b/cmake/modules/BaseConfig.cmake
index 86b2890d11e..8f5dc1c2a78 100644
--- a/cmake/modules/BaseConfig.cmake
+++ b/cmake/modules/BaseConfig.cmake
@@ -1,8 +1,8 @@
 # *****************************************************************************
 # CMake Features
 # *****************************************************************************
-set(CMAKE_CXX_STANDARD 20)
-set(GNUCXX_MINIMUM_VERSION 11)
+set(CMAKE_CXX_STANDARD 23)
+set(GNUCXX_MINIMUM_VERSION 12)
 set(MSVC_MINIMUM_VERSION "19.32")
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
diff --git a/data/events/scripts/creature.lua b/data/events/scripts/creature.lua
index 4da8217988d..69b14a527a9 100644
--- a/data/events/scripts/creature.lua
+++ b/data/events/scripts/creature.lua
@@ -14,7 +14,7 @@ local function removeCombatProtection(playerUid)
 	end
 
 	player:setStorageValue(Global.Storage.CombatProtectionStorage, 2)
-	addEvent(function(playerFuncUid)
+	                                                    addEvent(function(playerFuncUid)
 		local playerEvent = Player(playerFuncUid)
 		if not playerEvent then
 			return
diff --git a/src/canary_server.cpp b/src/canary_server.cpp
index 8476509c820..9c02ed1892b 100644
--- a/src/canary_server.cpp
+++ b/src/canary_server.cpp
@@ -35,7 +35,7 @@ CanaryServer::CanaryServer(
 	Logger &logger,
 	RSA &rsa,
 	ServiceManager &serviceManager
-) :
+										) :
 	logger(logger),
 	rsa(rsa),
 	serviceManager(serviceManager),