diff --git a/apps/settings/lib/Settings/Admin/Overview.php b/apps/settings/lib/Settings/Admin/Overview.php
index d796f91f83d..83027326a35 100644
--- a/apps/settings/lib/Settings/Admin/Overview.php
+++ b/apps/settings/lib/Settings/Admin/Overview.php
@@ -8,18 +8,15 @@ namespace OCA\Settings\Settings\Admin;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\IConfig;
 use OCP\IL10N;
+use OCP\ServerVersion;
 use OCP\Settings\IDelegatedSettings;
 
 class Overview implements IDelegatedSettings {
-	/** @var IConfig */
-	private $config;
-
-	/** @var IL10N $l */
-	private $l;
-
-	public function __construct(IConfig $config, IL10N $l) {
-		$this->config = $config;
-		$this->l = $l;
+	public function __construct(
+		private ServerVersion $serverVersion,
+		private IConfig $config,
+		private IL10N $l,
+	) {
 	}
 
 	/**
@@ -28,6 +25,7 @@ class Overview implements IDelegatedSettings {
 	public function getForm() {
 		$parameters = [
 			'checkForWorkingWellKnownSetup' => $this->config->getSystemValue('check_for_working_wellknown_setup', true),
+			'version' => $this->serverVersion->getHumanVersion(),
 		];
 
 		return new TemplateResponse('settings', 'settings/admin/overview', $parameters, '');
diff --git a/apps/settings/templates/settings/admin/overview.php b/apps/settings/templates/settings/admin/overview.php
index 83eab572534..c6d3ffa40ba 100644
--- a/apps/settings/templates/settings/admin/overview.php
+++ b/apps/settings/templates/settings/admin/overview.php
@@ -57,5 +57,5 @@
 <div id="version" class="section">
 	<!-- should be the last part, so Updater can follow if enabled (it has no heading therefore). -->
 	<h2><?php p($l->t('Version'));?></h2>
-	<p><strong><a href="<?php print_unescaped($theme->getBaseUrl()); ?>" rel="noreferrer noopener" target="_blank">Nextcloud Hub 9</a> (<?php p(OC_Util::getHumanVersion()) ?>)</strong></p>
+	<p><strong><a href="<?php print_unescaped($theme->getBaseUrl()); ?>" rel="noreferrer noopener" target="_blank">Nextcloud Hub 9</a> (<?php p($_['version']) ?>)</strong></p>
 </div>
diff --git a/apps/theming/lib/Util.php b/apps/theming/lib/Util.php
index 839ef1d0b46..fbb465505ac 100644
--- a/apps/theming/lib/Util.php
+++ b/apps/theming/lib/Util.php
@@ -13,19 +13,16 @@ use OCP\Files\NotFoundException;
 use OCP\Files\SimpleFS\ISimpleFile;
 use OCP\IConfig;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 
 class Util {
-
-	private IConfig $config;
-	private IAppManager $appManager;
-	private IAppData $appData;
-	private ImageManager $imageManager;
-
-	public function __construct(IConfig $config, IAppManager $appManager, IAppData $appData, ImageManager $imageManager) {
-		$this->config = $config;
-		$this->appManager = $appManager;
-		$this->appData = $appData;
-		$this->imageManager = $imageManager;
+	public function __construct(
+		private ServerVersion $serverVersion,
+		private IConfig $config,
+		private IAppManager $appManager,
+		private IAppData $appData,
+		private ImageManager $imageManager,
+	) {
 	}
 
 	/**
@@ -311,7 +308,7 @@ class Util {
 		if (!is_null($user)) {
 			$userId = $user->getUID();
 		}
-		$serverVersion = \OC_Util::getVersionString();
+		$serverVersion = $this->serverVersion->getVersionString();
 		$themingAppVersion = $this->appManager->getAppVersion('theming');
 		$userCacheBuster = '';
 		if ($userId) {
diff --git a/apps/theming/tests/CapabilitiesTest.php b/apps/theming/tests/CapabilitiesTest.php
index 277dd5b6a7a..1274be929ef 100644
--- a/apps/theming/tests/CapabilitiesTest.php
+++ b/apps/theming/tests/CapabilitiesTest.php
@@ -14,6 +14,7 @@ use OCP\Files\IAppData;
 use OCP\IConfig;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 use Test\TestCase;
 
@@ -169,7 +170,7 @@ class CapabilitiesTest extends TestCase {
 			->method('getLogo')
 			->willReturn($logo);
 
-		$util = new Util($this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class));
+		$util = new Util($this->createMock(ServerVersion::class), $this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class));
 		$this->util->expects($this->exactly(3))
 			->method('elementColor')
 			->with($color)
diff --git a/apps/theming/tests/IconBuilderTest.php b/apps/theming/tests/IconBuilderTest.php
index bef48448bfa..ec7bd8bcc55 100644
--- a/apps/theming/tests/IconBuilderTest.php
+++ b/apps/theming/tests/IconBuilderTest.php
@@ -13,6 +13,7 @@ use OCA\Theming\Util;
 use OCP\App\IAppManager;
 use OCP\Files\NotFoundException;
 use OCP\IConfig;
+use OCP\ServerVersion;
 use PHPUnit\Framework\Error\Warning;
 use Test\TestCase;
 
@@ -41,7 +42,7 @@ class IconBuilderTest extends TestCase {
 		$this->themingDefaults = $this->createMock(ThemingDefaults::class);
 		$this->appManager = $this->createMock(IAppManager::class);
 		$this->imageManager = $this->createMock(ImageManager::class);
-		$this->util = new Util($this->config, $this->appManager, $this->appData, $this->imageManager);
+		$this->util = new Util($this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->appData, $this->imageManager);
 		$this->iconBuilder = new IconBuilder($this->themingDefaults, $this->util, $this->imageManager);
 	}
 
diff --git a/apps/theming/tests/Themes/DarkHighContrastThemeTest.php b/apps/theming/tests/Themes/DarkHighContrastThemeTest.php
index 63fb2bf414d..16f7e86d217 100644
--- a/apps/theming/tests/Themes/DarkHighContrastThemeTest.php
+++ b/apps/theming/tests/Themes/DarkHighContrastThemeTest.php
@@ -18,6 +18,7 @@ use OCP\IConfig;
 use OCP\IL10N;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 
 class DarkHighContrastThemeTest extends AccessibleThemeTestCase {
@@ -49,6 +50,7 @@ class DarkHighContrastThemeTest extends AccessibleThemeTestCase {
 		$this->appManager = $this->createMock(IAppManager::class);
 
 		$this->util = new Util(
+			$this->createMock(ServerVersion::class),
 			$this->config,
 			$this->appManager,
 			$this->createMock(IAppData::class),
diff --git a/apps/theming/tests/Themes/DarkThemeTest.php b/apps/theming/tests/Themes/DarkThemeTest.php
index f53028d3a63..ea570adf21d 100644
--- a/apps/theming/tests/Themes/DarkThemeTest.php
+++ b/apps/theming/tests/Themes/DarkThemeTest.php
@@ -18,6 +18,7 @@ use OCP\IConfig;
 use OCP\IL10N;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 
 class DarkThemeTest extends AccessibleThemeTestCase {
@@ -46,6 +47,7 @@ class DarkThemeTest extends AccessibleThemeTestCase {
 		$this->appManager = $this->createMock(IAppManager::class);
 
 		$this->util = new Util(
+			$this->createMock(ServerVersion::class),
 			$this->config,
 			$this->appManager,
 			$this->createMock(IAppData::class),
diff --git a/apps/theming/tests/Themes/DefaultThemeTest.php b/apps/theming/tests/Themes/DefaultThemeTest.php
index db6a5bf1cfc..b463cf4567c 100644
--- a/apps/theming/tests/Themes/DefaultThemeTest.php
+++ b/apps/theming/tests/Themes/DefaultThemeTest.php
@@ -18,6 +18,7 @@ use OCP\IConfig;
 use OCP\IL10N;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 
 class DefaultThemeTest extends AccessibleThemeTestCase {
@@ -46,6 +47,7 @@ class DefaultThemeTest extends AccessibleThemeTestCase {
 		$this->appManager = $this->createMock(IAppManager::class);
 
 		$this->util = new Util(
+			$this->createMock(ServerVersion::class),
 			$this->config,
 			$this->appManager,
 			$this->createMock(IAppData::class),
diff --git a/apps/theming/tests/Themes/DyslexiaFontTest.php b/apps/theming/tests/Themes/DyslexiaFontTest.php
index 53505f4bd03..a022ee40114 100644
--- a/apps/theming/tests/Themes/DyslexiaFontTest.php
+++ b/apps/theming/tests/Themes/DyslexiaFontTest.php
@@ -19,6 +19,7 @@ use OCP\IL10N;
 use OCP\IRequest;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 use Test\TestCase;
 
@@ -49,6 +50,7 @@ class DyslexiaFontTest extends TestCase {
 		$this->appManager = $this->createMock(IAppManager::class);
 
 		$util = new Util(
+			$this->createMock(ServerVersion::class),
 			$this->config,
 			$this->appManager,
 			$this->createMock(IAppData::class),
diff --git a/apps/theming/tests/Themes/HighContrastThemeTest.php b/apps/theming/tests/Themes/HighContrastThemeTest.php
index 603bf08a0ee..71576caf841 100644
--- a/apps/theming/tests/Themes/HighContrastThemeTest.php
+++ b/apps/theming/tests/Themes/HighContrastThemeTest.php
@@ -18,6 +18,7 @@ use OCP\IConfig;
 use OCP\IL10N;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 
 class HighContrastThemeTest extends AccessibleThemeTestCase {
@@ -49,6 +50,7 @@ class HighContrastThemeTest extends AccessibleThemeTestCase {
 		$this->appManager = $this->createMock(IAppManager::class);
 
 		$this->util = new Util(
+			$this->createMock(ServerVersion::class),
 			$this->config,
 			$this->appManager,
 			$this->createMock(IAppData::class),
diff --git a/apps/theming/tests/UtilTest.php b/apps/theming/tests/UtilTest.php
index ba160684b7a..9a05c77a274 100644
--- a/apps/theming/tests/UtilTest.php
+++ b/apps/theming/tests/UtilTest.php
@@ -13,6 +13,7 @@ use OCP\Files\NotFoundException;
 use OCP\Files\SimpleFS\ISimpleFile;
 use OCP\Files\SimpleFS\ISimpleFolder;
 use OCP\IConfig;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 use Test\TestCase;
 
@@ -30,7 +31,7 @@ class UtilTest extends TestCase {
 		$this->appData = $this->createMock(IAppData::class);
 		$this->appManager = \OCP\Server::get(IAppManager::class);
 		$this->imageManager = $this->createMock(ImageManager::class);
-		$this->util = new Util($this->config, $this->appManager, $this->appData, $this->imageManager);
+		$this->util = new Util($this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->appData, $this->imageManager);
 	}
 
 	public function dataColorContrast() {
diff --git a/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php b/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php
index dd6497c7e48..30786f5e12d 100644
--- a/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php
+++ b/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php
@@ -18,6 +18,7 @@ use OCP\IConfig;
 use OCP\IGroup;
 use OCP\IGroupManager;
 use OCP\Notification\IManager;
+use OCP\ServerVersion;
 
 class UpdateAvailableNotifications extends TimedJob {
 	protected $connectionNotifications = [3, 7, 14, 30];
@@ -27,6 +28,7 @@ class UpdateAvailableNotifications extends TimedJob {
 
 	public function __construct(
 		ITimeFactory $timeFactory,
+		protected ServerVersion $serverVersion,
 		protected IConfig $config,
 		protected IAppConfig $appConfig,
 		protected IManager $notificationManager,
@@ -64,7 +66,7 @@ class UpdateAvailableNotifications extends TimedJob {
 	 * Check for ownCloud update
 	 */
 	protected function checkCoreUpdate() {
-		if (\in_array($this->getChannel(), ['daily', 'git'], true)) {
+		if (\in_array($this->serverVersion->getChannel(), ['daily', 'git'], true)) {
 			// "These aren't the update channels you're looking for." - Ben Obi-Wan Kenobi
 			return;
 		}
@@ -220,13 +222,6 @@ class UpdateAvailableNotifications extends TimedJob {
 		$this->notificationManager->markProcessed($notification);
 	}
 
-	/**
-	 * @return string
-	 */
-	protected function getChannel(): string {
-		return \OC_Util::getChannel();
-	}
-
 	/**
 	 * @param string $app
 	 * @return string|false
diff --git a/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php b/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php
index 3ebeb3d805d..61bacf9e0ac 100644
--- a/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php
+++ b/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php
@@ -20,10 +20,12 @@ use OCP\IGroupManager;
 use OCP\IUser;
 use OCP\Notification\IManager;
 use OCP\Notification\INotification;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 use Test\TestCase;
 
 class UpdateAvailableNotificationsTest extends TestCase {
+	private ServerVersion $serverVersion;
 	private IConfig|MockObject $config;
 	private IManager|MockObject $notificationManager;
 	private IGroupManager|MockObject $groupManager;
@@ -36,6 +38,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
 	protected function setUp(): void {
 		parent::setUp();
 
+		$this->serverVersion = $this->createMock(ServerVersion::class);
 		$this->config = $this->createMock(IConfig::class);
 		$this->appConfig = $this->createMock(IAppConfig::class);
 		$this->notificationManager = $this->createMock(IManager::class);
@@ -54,6 +57,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
 		if (empty($methods)) {
 			return new UpdateAvailableNotifications(
 				$this->timeFactory,
+				$this->serverVersion,
 				$this->config,
 				$this->appConfig,
 				$this->notificationManager,
@@ -67,6 +71,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
 			return $this->getMockBuilder(UpdateAvailableNotifications::class)
 				->setConstructorArgs([
 					$this->timeFactory,
+					$this->serverVersion,
 					$this->config,
 					$this->appConfig,
 					$this->notificationManager,
@@ -158,13 +163,12 @@ class UpdateAvailableNotificationsTest extends TestCase {
 	 */
 	public function testCheckCoreUpdate(string $channel, $versionCheck, $version, $readableVersion, $errorDays): void {
 		$job = $this->getJob([
-			'getChannel',
 			'createNotifications',
 			'clearErrorNotifications',
 			'sendErrorNotifications',
 		]);
 
-		$job->expects($this->once())
+		$this->serverVersion->expects($this->once())
 			->method('getChannel')
 			->willReturn($channel);
 
diff --git a/apps/user_ldap/lib/Controller/ConfigAPIController.php b/apps/user_ldap/lib/Controller/ConfigAPIController.php
index f4f55217ef1..8ce2486c153 100644
--- a/apps/user_ldap/lib/Controller/ConfigAPIController.php
+++ b/apps/user_ldap/lib/Controller/ConfigAPIController.php
@@ -21,6 +21,7 @@ use OCP\AppFramework\OCS\OCSNotFoundException;
 use OCP\IRequest;
 use OCP\IUserManager;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use Psr\Log\LoggerInterface;
 
 class ConfigAPIController extends OCSController {
@@ -31,6 +32,7 @@ class ConfigAPIController extends OCSController {
 		IUserSession $userSession,
 		IUserManager $userManager,
 		Manager $keyManager,
+		ServerVersion $serverVersion,
 		private Helper $ldapHelper,
 		private LoggerInterface $logger,
 		private ConnectionFactory $connectionFactory,
@@ -41,7 +43,8 @@ class ConfigAPIController extends OCSController {
 			$capabilitiesManager,
 			$userSession,
 			$userManager,
-			$keyManager
+			$keyManager,
+			$serverVersion,
 		);
 	}
 
diff --git a/core/Command/Status.php b/core/Command/Status.php
index 1f6d5705137..a00d4a94658 100644
--- a/core/Command/Status.php
+++ b/core/Command/Status.php
@@ -7,9 +7,9 @@
  */
 namespace OC\Core\Command;
 
-use OC_Util;
 use OCP\Defaults;
 use OCP\IConfig;
+use OCP\ServerVersion;
 use OCP\Util;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
@@ -19,6 +19,7 @@ class Status extends Base {
 	public function __construct(
 		private IConfig $config,
 		private Defaults $themingDefaults,
+		private ServerVersion $serverVersion,
 	) {
 		parent::__construct('status');
 	}
@@ -41,8 +42,8 @@ class Status extends Base {
 		$needUpgrade = Util::needUpgrade();
 		$values = [
 			'installed' => $this->config->getSystemValueBool('installed', false),
-			'version' => implode('.', Util::getVersion()),
-			'versionstring' => OC_Util::getVersionString(),
+			'version' => implode('.', $this->serverVersion->getVersion()),
+			'versionstring' => $this->serverVersion->getVersionString(),
 			'edition' => '',
 			'maintenance' => $maintenanceMode,
 			'needsDbUpgrade' => $needUpgrade,
diff --git a/core/Controller/OCJSController.php b/core/Controller/OCJSController.php
index 3a0922c9344..176558b013d 100644
--- a/core/Controller/OCJSController.php
+++ b/core/Controller/OCJSController.php
@@ -27,6 +27,7 @@ use OCP\ISession;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
 use OCP\L10N\IFactory;
+use OCP\ServerVersion;
 
 #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
 class OCJSController extends Controller {
@@ -48,10 +49,12 @@ class OCJSController extends Controller {
 		IInitialStateService $initialStateService,
 		IProvider $tokenProvider,
 		FilenameValidator $filenameValidator,
+		ServerVersion $serverVersion,
 	) {
 		parent::__construct($appName, $request);
 
 		$this->helper = new JSConfigHelper(
+			$serverVersion,
 			$l10nFactory->get('lib'),
 			$defaults,
 			$appManager,
diff --git a/core/Controller/OCSController.php b/core/Controller/OCSController.php
index 743a71622da..65ce55b8606 100644
--- a/core/Controller/OCSController.php
+++ b/core/Controller/OCSController.php
@@ -16,6 +16,7 @@ use OCP\AppFramework\Http\DataResponse;
 use OCP\IRequest;
 use OCP\IUserManager;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 
 class OCSController extends \OCP\AppFramework\OCSController {
 	public function __construct(
@@ -25,6 +26,7 @@ class OCSController extends \OCP\AppFramework\OCSController {
 		private IUserSession $userSession,
 		private IUserManager $userManager,
 		private Manager $keyManager,
+		private ServerVersion $serverVersion,
 	) {
 		parent::__construct($appName, $request);
 	}
@@ -55,12 +57,11 @@ class OCSController extends \OCP\AppFramework\OCSController {
 	#[ApiRoute(verb: 'GET', url: '/capabilities', root: '/cloud')]
 	public function getCapabilities(): DataResponse {
 		$result = [];
-		[$major, $minor, $micro] = \OCP\Util::getVersion();
 		$result['version'] = [
-			'major' => (int)$major,
-			'minor' => (int)$minor,
-			'micro' => (int)$micro,
-			'string' => \OC_Util::getVersionString(),
+			'major' => $this->serverVersion->getMajorVersion(),
+			'minor' => $this->serverVersion->getMinorVersion(),
+			'micro' => $this->serverVersion->getPatchVersion(),
+			'string' => $this->serverVersion->getVersionString(),
 			'edition' => '',
 			'extendedSupport' => \OCP\Util::hasExtendedSupport()
 		];
diff --git a/core/Controller/WhatsNewController.php b/core/Controller/WhatsNewController.php
index 58cb70c863a..98c5e77964b 100644
--- a/core/Controller/WhatsNewController.php
+++ b/core/Controller/WhatsNewController.php
@@ -19,6 +19,7 @@ use OCP\IRequest;
 use OCP\IUserManager;
 use OCP\IUserSession;
 use OCP\L10N\IFactory;
+use OCP\ServerVersion;
 
 class WhatsNewController extends OCSController {
 	public function __construct(
@@ -28,12 +29,13 @@ class WhatsNewController extends OCSController {
 		private IUserSession $userSession,
 		IUserManager $userManager,
 		Manager $keyManager,
+		ServerVersion $serverVersion,
 		private IConfig $config,
 		private ChangesCheck $whatsNewService,
 		private IFactory $langFactory,
 		private Defaults $defaults,
 	) {
-		parent::__construct($appName, $request, $capabilitiesManager, $userSession, $userManager, $keyManager);
+		parent::__construct($appName, $request, $capabilitiesManager, $userSession, $userManager, $keyManager, $serverVersion);
 	}
 
 	/**
diff --git a/core/ajax/update.php b/core/ajax/update.php
index 575a1f159e5..0868eff72b4 100644
--- a/core/ajax/update.php
+++ b/core/ajax/update.php
@@ -91,6 +91,7 @@ if (\OCP\Util::needUpgrade()) {
 
 	$config = Server::get(IConfig::class);
 	$updater = new \OC\Updater(
+		Server::get(\OCP\ServerVersion::class),
 		$config,
 		Server::get(IAppConfig::class),
 		\OC::$server->getIntegrityCodeChecker(),
diff --git a/lib/base.php b/lib/base.php
index ec5cf3759f2..5bab5d9f3f6 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -292,10 +292,12 @@ class OC {
 			http_response_code(503);
 			header('Retry-After: 120');
 
+			$serverVersion = \OCP\Server::get(\OCP\ServerVersion::class);
+
 			// render error page
 			$template = new OC_Template('', 'update.use-cli', 'guest');
 			$template->assign('productName', 'nextcloud'); // for now
-			$template->assign('version', OC_Util::getVersionString());
+			$template->assign('version', $serverVersion->getVersionString());
 			$template->assign('tooBig', $tooBig);
 			$template->assign('cliUpgradeLink', $cliUpgradeLink);
 
@@ -321,7 +323,7 @@ class OC {
 		$appManager = Server::get(\OCP\App\IAppManager::class);
 
 		$tmpl = new OC_Template('', 'update.admin', 'guest');
-		$tmpl->assign('version', OC_Util::getVersionString());
+		$tmpl->assign('version', \OCP\Server::get(\OCP\ServerVersion::class)->getVersionString());
 		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
 
 		// get third party apps
@@ -663,7 +665,7 @@ class OC {
 		if (!function_exists('simplexml_load_file')) {
 			throw new \OCP\HintException('The PHP SimpleXML/PHP-XML extension is not installed.', 'Install the extension or make sure it is enabled.');
 		}
-		
+
 		OC_App::loadApps(['session']);
 		if (!self::$CLI) {
 			self::initSession();
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 82964a6e6c7..166d5805bdc 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -688,6 +688,7 @@ return array(
     'OCP\\Security\\VerificationToken\\IVerificationToken' => $baseDir . '/lib/public/Security/VerificationToken/IVerificationToken.php',
     'OCP\\Security\\VerificationToken\\InvalidTokenException' => $baseDir . '/lib/public/Security/VerificationToken/InvalidTokenException.php',
     'OCP\\Server' => $baseDir . '/lib/public/Server.php',
+    'OCP\\ServerVersion' => $baseDir . '/lib/public/ServerVersion.php',
     'OCP\\Session\\Exceptions\\SessionNotAvailableException' => $baseDir . '/lib/public/Session/Exceptions/SessionNotAvailableException.php',
     'OCP\\Settings\\DeclarativeSettingsTypes' => $baseDir . '/lib/public/Settings/DeclarativeSettingsTypes.php',
     'OCP\\Settings\\Events\\DeclarativeSettingsGetValueEvent' => $baseDir . '/lib/public/Settings/Events/DeclarativeSettingsGetValueEvent.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index d83229c7426..b455077b958 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -721,6 +721,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
         'OCP\\Security\\VerificationToken\\IVerificationToken' => __DIR__ . '/../../..' . '/lib/public/Security/VerificationToken/IVerificationToken.php',
         'OCP\\Security\\VerificationToken\\InvalidTokenException' => __DIR__ . '/../../..' . '/lib/public/Security/VerificationToken/InvalidTokenException.php',
         'OCP\\Server' => __DIR__ . '/../../..' . '/lib/public/Server.php',
+        'OCP\\ServerVersion' => __DIR__ . '/../../..' . '/lib/public/ServerVersion.php',
         'OCP\\Session\\Exceptions\\SessionNotAvailableException' => __DIR__ . '/../../..' . '/lib/public/Session/Exceptions/SessionNotAvailableException.php',
         'OCP\\Settings\\DeclarativeSettingsTypes' => __DIR__ . '/../../..' . '/lib/public/Settings/DeclarativeSettingsTypes.php',
         'OCP\\Settings\\Events\\DeclarativeSettingsGetValueEvent' => __DIR__ . '/../../..' . '/lib/public/Settings/Events/DeclarativeSettingsGetValueEvent.php',
diff --git a/lib/private/App/AppStore/Fetcher/Fetcher.php b/lib/private/App/AppStore/Fetcher/Fetcher.php
index edb96b55f0a..f998c9e2023 100644
--- a/lib/private/App/AppStore/Fetcher/Fetcher.php
+++ b/lib/private/App/AppStore/Fetcher/Fetcher.php
@@ -13,6 +13,8 @@ use OCP\Files\IAppData;
 use OCP\Files\NotFoundException;
 use OCP\Http\Client\IClientService;
 use OCP\IConfig;
+use OCP\Server;
+use OCP\ServerVersion;
 use OCP\Support\Subscription\IRegistry;
 use Psr\Log\LoggerInterface;
 
@@ -207,7 +209,7 @@ abstract class Fetcher {
 	 */
 	protected function getChannel() {
 		if ($this->channel === null) {
-			$this->channel = \OC_Util::getChannel();
+			$this->channel = Server::get(ServerVersion::class)->getChannel();
 		}
 		return $this->channel;
 	}
diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php
index 1b620089736..ac30a93a186 100644
--- a/lib/private/Console/Application.php
+++ b/lib/private/Console/Application.php
@@ -19,6 +19,7 @@ use OCP\EventDispatcher\IEventDispatcher;
 use OCP\IConfig;
 use OCP\IRequest;
 use OCP\Server;
+use OCP\ServerVersion;
 use Psr\Container\ContainerExceptionInterface;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\Console\Application as SymfonyApplication;
@@ -31,6 +32,7 @@ class Application {
 	private SymfonyApplication $application;
 
 	public function __construct(
+		ServerVersion $serverVersion,
 		private IConfig $config,
 		private IEventDispatcher $dispatcher,
 		private IRequest $request,
@@ -39,7 +41,7 @@ class Application {
 		private IAppManager $appManager,
 		private Defaults $defaults,
 	) {
-		$this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
+		$this->application = new SymfonyApplication($defaults->getName(), $serverVersion->getVersionString());
 	}
 
 	/**
diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php
index a6a61555957..3a24e8632de 100644
--- a/lib/private/IntegrityCheck/Checker.php
+++ b/lib/private/IntegrityCheck/Checker.php
@@ -21,6 +21,7 @@ use OCP\IAppConfig;
 use OCP\ICache;
 use OCP\ICacheFactory;
 use OCP\IConfig;
+use OCP\ServerVersion;
 use phpseclib\Crypt\RSA;
 use phpseclib\File\X509;
 
@@ -40,6 +41,7 @@ class Checker {
 	private ICache $cache;
 
 	public function __construct(
+		private ServerVersion $serverVersion,
 		private EnvironmentHelper $environmentHelper,
 		private FileAccessHelper $fileAccessHelper,
 		private AppLocator $appLocator,
@@ -59,7 +61,7 @@ class Checker {
 	 */
 	public function isCodeCheckEnforced(): bool {
 		$notSignedChannels = [ '', 'git'];
-		if (\in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) {
+		if (\in_array($this->serverVersion->getChannel(), $notSignedChannels, true)) {
 			return false;
 		}
 
diff --git a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
index dcdc7839f8e..583ae5e534f 100644
--- a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
+++ b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
@@ -23,13 +23,4 @@ class EnvironmentHelper {
 	public function getServerRoot(): string {
 		return rtrim(\OC::$SERVERROOT, '/');
 	}
-
-	/**
-	 * Provides \OC_Util::getChannel()
-	 *
-	 * @return string
-	 */
-	public function getChannel(): string {
-		return \OC_Util::getChannel();
-	}
 }
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 943b4fc6997..19c3b72c11c 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -216,6 +216,7 @@ use OCP\Security\ISecureRandom;
 use OCP\Security\ITrustedDomainHelper;
 use OCP\Security\RateLimiting\ILimiter;
 use OCP\Security\VerificationToken\IVerificationToken;
+use OCP\ServerVersion;
 use OCP\Settings\IDeclarativeManager;
 use OCP\SetupCheck\ISetupCheckManager;
 use OCP\Share\IProviderFactory;
@@ -593,10 +594,12 @@ class Server extends ServerContainer implements IServerContainer {
 			);
 			/** @var SystemConfig $config */
 			$config = $c->get(SystemConfig::class);
+			/** @var ServerVersion $serverVersion */
+			$serverVersion = $c->get(ServerVersion::class);
 
 			if ($config->getValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
 				$logQuery = $config->getValue('log_query');
-				$prefixClosure = function () use ($logQuery) {
+				$prefixClosure = function () use ($logQuery, $serverVersion) {
 					if (!$logQuery) {
 						try {
 							$v = \OC_App::getAppVersions();
@@ -613,7 +616,7 @@ class Server extends ServerContainer implements IServerContainer {
 							'log_query' => 'enabled',
 						];
 					}
-					$v['core'] = implode(',', \OC_Util::getVersion());
+					$v['core'] = implode(',', $serverVersion->getVersion());
 					$version = implode(',', $v);
 					$instanceId = \OC_Util::getInstanceId();
 					$path = \OC::$SERVERROOT;
@@ -865,7 +868,8 @@ class Server extends ServerContainer implements IServerContainer {
 			$appManager = $c->get(IAppManager::class);
 
 			return new Checker(
-				new EnvironmentHelper(),
+				$c->get(ServerVersion::class),
+				$c->get(EnvironmentHelper::class),
 				new FileAccessHelper(),
 				new AppLocator(),
 				$config,
@@ -1056,7 +1060,7 @@ class Server extends ServerContainer implements IServerContainer {
 					$c->get(IUserSession::class),
 					$c->get(IURLGenerator::class),
 					$c->get(ICacheFactory::class),
-					new Util($c->get(\OCP\IConfig::class), $this->get(IAppManager::class), $c->getAppDataDir('theming'), $imageManager),
+					new Util($c->get(ServerVersion::class), $c->get(\OCP\IConfig::class), $this->get(IAppManager::class), $c->getAppDataDir('theming'), $imageManager),
 					$imageManager,
 					$c->get(IAppManager::class),
 					$c->get(INavigationManager::class),
diff --git a/lib/private/Setup.php b/lib/private/Setup.php
index fa10f238bde..e64f6806b87 100644
--- a/lib/private/Setup.php
+++ b/lib/private/Setup.php
@@ -32,6 +32,7 @@ use OCP\L10N\IFactory as IL10NFactory;
 use OCP\Migration\IOutput;
 use OCP\Security\ISecureRandom;
 use OCP\Server;
+use OCP\ServerVersion;
 use Psr\Log\LoggerInterface;
 
 class Setup {
@@ -380,7 +381,7 @@ class Setup {
 			unlink(\OC::$configDir . '/CAN_INSTALL');
 		}
 
-		$bootstrapCoordinator = \OCP\Server::get(\OC\AppFramework\Bootstrap\Coordinator::class);
+		$bootstrapCoordinator = Server::get(\OC\AppFramework\Bootstrap\Coordinator::class);
 		$bootstrapCoordinator->runInitialRegistration();
 
 		// Create a session token for the newly created user
@@ -561,7 +562,7 @@ class Setup {
 	}
 
 	public function shouldRemoveCanInstallFile(): bool {
-		return \OC_Util::getChannel() !== 'git' && is_file(\OC::$configDir . '/CAN_INSTALL');
+		return Server::get(ServerVersion::class)->getChannel() !== 'git' && is_file(\OC::$configDir . '/CAN_INSTALL');
 	}
 
 	public function canInstallFileExists(): bool {
diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php
index 1dec8634aca..44563f2938c 100644
--- a/lib/private/Template/JSConfigHelper.php
+++ b/lib/private/Template/JSConfigHelper.php
@@ -30,6 +30,7 @@ use OCP\ILogger;
 use OCP\ISession;
 use OCP\IURLGenerator;
 use OCP\IUser;
+use OCP\ServerVersion;
 use OCP\Session\Exceptions\SessionNotAvailableException;
 use OCP\Share\IManager as IShareManager;
 use OCP\User\Backend\IPasswordConfirmationBackend;
@@ -41,6 +42,7 @@ class JSConfigHelper {
 	private $excludedUserBackEnds = ['user_saml' => true, 'user_globalsiteselector' => true];
 
 	public function __construct(
+		protected ServerVersion        $serverVersion,
 		protected IL10N                $l,
 		protected Defaults             $defaults,
 		protected IAppManager          $appManager,
@@ -53,7 +55,7 @@ class JSConfigHelper {
 		protected CapabilitiesManager  $capabilitiesManager,
 		protected IInitialStateService $initialStateService,
 		protected IProvider            $tokenProvider,
-		protected FilenameValidator   $filenameValidator,
+		protected FilenameValidator    $filenameValidator,
 	) {
 	}
 
@@ -154,8 +156,8 @@ class JSConfigHelper {
 			'session_lifetime' => min($this->config->getSystemValue('session_lifetime', $this->iniWrapper->getNumeric('session.gc_maxlifetime')), $this->iniWrapper->getNumeric('session.gc_maxlifetime')),
 			'sharing.maxAutocompleteResults' => max(0, $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)),
 			'sharing.minSearchStringLength' => $this->config->getSystemValueInt('sharing.minSearchStringLength', 0),
-			'version' => implode('.', Util::getVersion()),
-			'versionstring' => \OC_Util::getVersionString(),
+			'version' => implode('.', $this->serverVersion->getVersion()),
+			'versionstring' => $this->serverVersion->getVersionString(),
 			'enable_non-accessible_features' => $this->config->getSystemValueBool('enable_non-accessible_features', true),
 		];
 
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index 6c7cec90740..c21df495b5b 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -25,6 +25,7 @@ use OCP\IRequest;
 use OCP\IURLGenerator;
 use OCP\IUserSession;
 use OCP\L10N\IFactory;
+use OCP\ServerVersion;
 use OCP\Support\Subscription\IRegistry;
 use OCP\Util;
 
@@ -218,6 +219,7 @@ class TemplateLayout extends \OC_Template {
 			// this is on purpose outside of the if statement below so that the initial state is prefilled (done in the getConfig() call)
 			// see https://github.com/nextcloud/server/pull/22636 for details
 			$jsConfigHelper = new JSConfigHelper(
+				\OCP\Server::get(ServerVersion::class),
 				\OCP\Util::getL10N('lib'),
 				\OCP\Server::get(Defaults::class),
 				\OC::$server->getAppManager(),
diff --git a/lib/private/Updater.php b/lib/private/Updater.php
index 2ea680efcf5..c4631f2c7d3 100644
--- a/lib/private/Updater.php
+++ b/lib/private/Updater.php
@@ -31,6 +31,7 @@ use OCP\HintException;
 use OCP\IAppConfig;
 use OCP\IConfig;
 use OCP\ILogger;
+use OCP\ServerVersion;
 use OCP\Util;
 use Psr\Log\LoggerInterface;
 
@@ -53,6 +54,7 @@ class Updater extends BasicEmitter {
 	];
 
 	public function __construct(
+		private ServerVersion $serverVersion,
 		private IConfig $config,
 		private IAppConfig $appConfig,
 		private Checker $checker,
@@ -82,14 +84,14 @@ class Updater extends BasicEmitter {
 		}
 
 		// Clear CAN_INSTALL file if not on git
-		if (\OC_Util::getChannel() !== 'git' && is_file(\OC::$configDir . '/CAN_INSTALL')) {
+		if ($this->serverVersion->getChannel() !== 'git' && is_file(\OC::$configDir . '/CAN_INSTALL')) {
 			if (!unlink(\OC::$configDir . '/CAN_INSTALL')) {
 				$this->log->error('Could not cleanup CAN_INSTALL from your config folder. Please remove this file manually.');
 			}
 		}
 
 		$installedVersion = $this->config->getSystemValueString('version', '0.0.0');
-		$currentVersion = implode('.', \OCP\Util::getVersion());
+		$currentVersion = implode('.', $this->serverVersion->getVersion());
 
 		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, ['app' => 'core']);
 
diff --git a/lib/private/Updater/VersionCheck.php b/lib/private/Updater/VersionCheck.php
index cc5ff63379c..53bfc0d5d5f 100644
--- a/lib/private/Updater/VersionCheck.php
+++ b/lib/private/Updater/VersionCheck.php
@@ -11,12 +11,14 @@ use OCP\Http\Client\IClientService;
 use OCP\IAppConfig;
 use OCP\IConfig;
 use OCP\IUserManager;
+use OCP\ServerVersion;
 use OCP\Support\Subscription\IRegistry;
 use OCP\Util;
 use Psr\Log\LoggerInterface;
 
 class VersionCheck {
 	public function __construct(
+		private ServerVersion $serverVersion,
 		private IClientService $clientService,
 		private IConfig $config,
 		private IAppConfig $appConfig,
@@ -54,9 +56,9 @@ class VersionCheck {
 		$version = Util::getVersion();
 		$version['installed'] = $this->config->getAppValue('core', 'installedat');
 		$version['updated'] = $this->appConfig->getValueInt('core', 'lastupdatedat');
-		$version['updatechannel'] = \OC_Util::getChannel();
+		$version['updatechannel'] = $this->serverVersion->getChannel();
 		$version['edition'] = '';
-		$version['build'] = \OC_Util::getBuild();
+		$version['build'] = $this->serverVersion->getBuild();
 		$version['php_major'] = PHP_MAJOR_VERSION;
 		$version['php_minor'] = PHP_MINOR_VERSION;
 		$version['php_release'] = PHP_RELEASE_VERSION;
diff --git a/lib/private/legacy/OC_Defaults.php b/lib/private/legacy/OC_Defaults.php
index cc0ac687ccc..f7015a1863a 100644
--- a/lib/private/legacy/OC_Defaults.php
+++ b/lib/private/legacy/OC_Defaults.php
@@ -6,6 +6,10 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+use OCP\IConfig;
+use OCP\Server;
+use OCP\ServerVersion;
+
 class OC_Defaults {
 	private $theme;
 
@@ -27,7 +31,8 @@ class OC_Defaults {
 	private $defaultProductName;
 
 	public function __construct() {
-		$config = \OC::$server->getConfig();
+		$config = Server::get(IConfig::class);
+		$serverVersion = Server::get(ServerVersion::class);
 
 		$this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */
 		$this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */
@@ -39,7 +44,7 @@ class OC_Defaults {
 		$this->defaultAndroidClientUrl = $config->getSystemValue('customclient_android', 'https://play.google.com/store/apps/details?id=com.nextcloud.client');
 		$this->defaultFDroidClientUrl = $config->getSystemValue('customclient_fdroid', 'https://f-droid.org/packages/com.nextcloud.client/');
 		$this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
-		$this->defaultDocVersion = \OC_Util::getVersion()[0]; // used to generate doc links
+		$this->defaultDocVersion = $serverVersion->getMajorVersion(); // used to generate doc links
 		$this->defaultColorBackground = '#00679e';
 		$this->defaultColorPrimary = '#00679e';
 		$this->defaultTextColorPrimary = '#ffffff';
diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php
index c390b7727e9..7b41f797e32 100644
--- a/lib/private/legacy/OC_Util.php
+++ b/lib/private/legacy/OC_Util.php
@@ -215,76 +215,6 @@ class OC_Util {
 		$setupManager->tearDown();
 	}
 
-	/**
-	 * get the current installed version of ownCloud
-	 *
-	 * @return array
-	 */
-	public static function getVersion() {
-		OC_Util::loadVersion();
-		return self::$versionCache['OC_Version'];
-	}
-
-	/**
-	 * get the current installed version string of ownCloud
-	 *
-	 * @return string
-	 */
-	public static function getVersionString() {
-		OC_Util::loadVersion();
-		return self::$versionCache['OC_VersionString'];
-	}
-
-	/**
-	 * @deprecated 11.0.0 the value is of no use anymore
-	 * @return string
-	 */
-	public static function getEditionString() {
-		return '';
-	}
-
-	/**
-	 * @description get the update channel of the current installed of ownCloud.
-	 * @return string
-	 */
-	public static function getChannel() {
-		OC_Util::loadVersion();
-		return \OC::$server->getConfig()->getSystemValueString('updater.release.channel', self::$versionCache['OC_Channel']);
-	}
-
-	/**
-	 * @description get the build number of the current installed of ownCloud.
-	 * @return string
-	 */
-	public static function getBuild() {
-		OC_Util::loadVersion();
-		return self::$versionCache['OC_Build'];
-	}
-
-	/**
-	 * @description load the version.php into the session as cache
-	 * @suppress PhanUndeclaredVariable
-	 */
-	private static function loadVersion() {
-		if (self::$versionCache !== null) {
-			return;
-		}
-
-		$timestamp = filemtime(OC::$SERVERROOT . '/version.php');
-		require OC::$SERVERROOT . '/version.php';
-		/** @var int $timestamp */
-		self::$versionCache['OC_Version_Timestamp'] = $timestamp;
-		/** @var string $OC_Version */
-		self::$versionCache['OC_Version'] = $OC_Version;
-		/** @var string $OC_VersionString */
-		self::$versionCache['OC_VersionString'] = $OC_VersionString;
-		/** @var string $OC_Build */
-		self::$versionCache['OC_Build'] = $OC_Build;
-
-		/** @var string $OC_Channel */
-		self::$versionCache['OC_Channel'] = $OC_Channel;
-	}
-
 	/**
 	 * generates a path for JS/CSS files. If no application is provided it will create the path for core.
 	 *
@@ -1021,20 +951,6 @@ class OC_Util {
 		return $normalizedValue;
 	}
 
-	/**
-	 * A human readable string is generated based on version and build number
-	 *
-	 * @return string
-	 */
-	public static function getHumanVersion() {
-		$version = OC_Util::getVersionString();
-		$build = OC_Util::getBuild();
-		if (!empty($build) and OC_Util::getChannel() === 'daily') {
-			$version .= ' Build:' . $build;
-		}
-		return $version;
-	}
-
 	/**
 	 * Check whether the instance needs to perform an upgrade,
 	 * either when the core version is higher or any app requires
diff --git a/lib/public/ServerVersion.php b/lib/public/ServerVersion.php
new file mode 100644
index 00000000000..637c34d3619
--- /dev/null
+++ b/lib/public/ServerVersion.php
@@ -0,0 +1,102 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCP;
+
+/**
+ * @since 31.0.0
+ */
+class ServerVersion {
+
+	private array $version;
+	private string $versionString;
+	private string $build;
+	/** @var 'beta'|'stable'|'enterprise'|'git' */
+	private string $channel;
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function __construct() {
+		$versionFile = __DIR__ . '/../../version.php';
+		require $versionFile;
+
+		/** @var int[] $OC_Version */
+		$this->version = $OC_Version;
+		/** @var string $OC_VersionString */
+		$this->versionString = $OC_VersionString;
+		/** @var string $OC_Build */
+		$this->build = $OC_Build;
+		/** @var string $OC_Channel */
+		$this->channel = $OC_Channel;
+	}
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function getMajorVersion(): int {
+		return $this->version[0];
+	}
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function getMinorVersion(): int {
+		return $this->version[1];
+	}
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function getPatchVersion(): int {
+		return $this->version[2];
+	}
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function getVersion(): array {
+		return $this->version;
+	}
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function getVersionString(): string {
+		return $this->versionString;
+	}
+
+	/**
+	 * @psalm-return 'beta'|'stable'|'enterprise'|'git'
+	 * @since 31.0.0
+	 */
+	public function getChannel(): string {
+		return $this->channel;
+	}
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function getBuild(): string {
+		return $this->build;
+	}
+
+	/**
+	 * @since 31.0.0
+	 */
+	public function getHumanVersion(): string {
+		$version = $this->getVersionString();
+		$build = $this->getBuild();
+		if (!empty($build) && $this->getChannel() === 'daily') {
+			$version .= ' Build:' . $build;
+		}
+		return $version;
+
+	}
+}
diff --git a/lib/public/Util.php b/lib/public/Util.php
index 520e4616de5..28da91c9a0f 100644
--- a/lib/public/Util.php
+++ b/lib/public/Util.php
@@ -35,9 +35,10 @@ class Util {
 	 * get the current installed version of Nextcloud
 	 * @return array
 	 * @since 4.0.0
+	 * @deprecated 31.0.0 Use \OCP\ServerVersion::getVersion
 	 */
 	public static function getVersion() {
-		return \OC_Util::getVersion();
+		return Server::get(ServerVersion::class)->getVersion();
 	}
 
 	/**
@@ -46,7 +47,7 @@ class Util {
 	public static function hasExtendedSupport(): bool {
 		try {
 			/** @var \OCP\Support\Subscription\IRegistry */
-			$subscriptionRegistry = \OCP\Server::get(\OCP\Support\Subscription\IRegistry::class);
+			$subscriptionRegistry = Server::get(\OCP\Support\Subscription\IRegistry::class);
 			return $subscriptionRegistry->delegateHasExtendedSupport();
 		} catch (ContainerExceptionInterface $e) {
 		}
@@ -66,9 +67,10 @@ class Util {
 	 * Get current update channel
 	 * @return string
 	 * @since 8.1.0
+	 * @deprecated 31.0.0 Use \OCP\ServerVersion::getChannel
 	 */
 	public static function getChannel() {
-		return \OC_Util::getChannel();
+		return \OCP\Server::get(ServerVersion::class)->getChannel();
 	}
 
 	/**
@@ -567,7 +569,7 @@ class Util {
 		if (!function_exists($functionName)) {
 			return false;
 		}
-		$ini = \OCP\Server::get(IniGetWrapper::class);
+		$ini = Server::get(IniGetWrapper::class);
 		$disabled = explode(',', $ini->get('disable_functions') ?: '');
 		$disabled = array_map('trim', $disabled);
 		if (in_array($functionName, $disabled)) {
diff --git a/status.php b/status.php
index 46d9b801e71..e4d4bab7e45 100644
--- a/status.php
+++ b/status.php
@@ -24,7 +24,7 @@ try {
 		'maintenance' => $maintenance,
 		'needsDbUpgrade' => \OCP\Util::needUpgrade(),
 		'version' => implode('.', \OCP\Util::getVersion()),
-		'versionstring' => OC_Util::getVersionString(),
+		'versionstring' => \OCP\Server::get(\OCP\ServerVersion::class)->getVersionString(),
 		'edition' => '',
 		'productname' => $defaults->getProductName(),
 		'extendedSupport' => \OCP\Util::hasExtendedSupport()
diff --git a/tests/Core/Controller/OCSControllerTest.php b/tests/Core/Controller/OCSControllerTest.php
index 6fc5f54b8ef..142a15e2308 100644
--- a/tests/Core/Controller/OCSControllerTest.php
+++ b/tests/Core/Controller/OCSControllerTest.php
@@ -15,6 +15,7 @@ use OCP\IRequest;
 use OCP\IUser;
 use OCP\IUserManager;
 use OCP\IUserSession;
+use OCP\ServerVersion;
 use Test\TestCase;
 
 class OCSControllerTest extends TestCase {
@@ -28,6 +29,8 @@ class OCSControllerTest extends TestCase {
 	private $userManager;
 	/** @var Manager|\PHPUnit\Framework\MockObject\MockObject */
 	private $keyManager;
+	/** @var ServerVersion|\PHPUnit\Framework\MockObject\MockObject */
+	private $serverVersion;
 	/** @var OCSController */
 	private $controller;
 
@@ -39,6 +42,7 @@ class OCSControllerTest extends TestCase {
 		$this->userSession = $this->createMock(IUserSession::class);
 		$this->userManager = $this->createMock(IUserManager::class);
 		$this->keyManager = $this->createMock(Manager::class);
+		$serverVersion = \OCP\Server::get(ServerVersion::class);
 
 		$this->controller = new OCSController(
 			'core',
@@ -46,7 +50,8 @@ class OCSControllerTest extends TestCase {
 			$this->capabilitiesManager,
 			$this->userSession,
 			$this->userManager,
-			$this->keyManager
+			$this->keyManager,
+			$serverVersion
 		);
 	}
 
@@ -72,14 +77,15 @@ class OCSControllerTest extends TestCase {
 		$this->userSession->expects($this->once())
 			->method('isLoggedIn')
 			->willReturn(true);
-		[$major, $minor, $micro] = \OCP\Util::getVersion();
+
+		$serverVersion = \OCP\Server::get(ServerVersion::class);
 
 		$result = [];
 		$result['version'] = [
-			'major' => $major,
-			'minor' => $minor,
-			'micro' => $micro,
-			'string' => \OC_Util::getVersionString(),
+			'major' => $serverVersion->getMajorVersion(),
+			'minor' => $serverVersion->getMinorVersion(),
+			'micro' => $serverVersion->getPatchVersion(),
+			'string' => $serverVersion->getVersionString(),
 			'edition' => '',
 			'extendedSupport' => false
 		];
@@ -105,14 +111,14 @@ class OCSControllerTest extends TestCase {
 		$this->userSession->expects($this->once())
 			->method('isLoggedIn')
 			->willReturn(false);
-		[$major, $minor, $micro] = \OCP\Util::getVersion();
+		$serverVersion = \OCP\Server::get(ServerVersion::class);
 
 		$result = [];
 		$result['version'] = [
-			'major' => $major,
-			'minor' => $minor,
-			'micro' => $micro,
-			'string' => \OC_Util::getVersionString(),
+			'major' => $serverVersion->getMajorVersion(),
+			'minor' => $serverVersion->getMinorVersion(),
+			'micro' => $serverVersion->getPatchVersion(),
+			'string' => $serverVersion->getVersionString(),
 			'edition' => '',
 			'extendedSupport' => false
 		];
diff --git a/tests/lib/IntegrityCheck/CheckerTest.php b/tests/lib/IntegrityCheck/CheckerTest.php
index 6b6da1cc30c..5858a01203f 100644
--- a/tests/lib/IntegrityCheck/CheckerTest.php
+++ b/tests/lib/IntegrityCheck/CheckerTest.php
@@ -17,11 +17,14 @@ use OCP\App\IAppManager;
 use OCP\IAppConfig;
 use OCP\ICacheFactory;
 use OCP\IConfig;
+use OCP\ServerVersion;
 use phpseclib\Crypt\RSA;
 use phpseclib\File\X509;
 use Test\TestCase;
 
 class CheckerTest extends TestCase {
+	/** @var ServerVersion|\PHPUnit\Framework\MockObject\MockObject */
+	private $serverVersion;
 	/** @var EnvironmentHelper|\PHPUnit\Framework\MockObject\MockObject */
 	private $environmentHelper;
 	/** @var AppLocator|\PHPUnit\Framework\MockObject\MockObject */
@@ -43,6 +46,7 @@ class CheckerTest extends TestCase {
 
 	protected function setUp(): void {
 		parent::setUp();
+		$this->serverVersion = $this->createMock(ServerVersion::class);
 		$this->environmentHelper = $this->createMock(EnvironmentHelper::class);
 		$this->fileAccessHelper = $this->createMock(FileAccessHelper::class);
 		$this->appLocator = $this->createMock(AppLocator::class);
@@ -62,6 +66,7 @@ class CheckerTest extends TestCase {
 			->willReturn(new NullCache());
 
 		$this->checker = new Checker(
+			$this->serverVersion,
 			$this->environmentHelper,
 			$this->fileAccessHelper,
 			$this->appLocator,
@@ -149,7 +154,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppSignatureWithoutSignatureData(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -169,7 +174,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppSignatureWithValidSignatureData(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -208,7 +213,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppSignatureWithTamperedSignatureData(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -253,7 +258,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppSignatureWithTamperedFiles(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -314,7 +319,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppSignatureWithTamperedFilesAndAlternatePath(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -374,7 +379,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppWithDifferentScope(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -418,7 +423,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppWithDifferentScopeAndAlwaysTrustedCore(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -639,7 +644,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreSignatureWithoutSignatureData(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -659,7 +664,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreSignatureWithValidSignatureData(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -696,7 +701,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreSignatureWithValidModifiedHtaccessSignatureData(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -759,7 +764,7 @@ class CheckerTest extends TestCase {
 		// occ integrity:sign-core --privateKey=./tests/data/integritycheck/core.key --certificate=./tests/data/integritycheck/core.crt --path=./tests/data/integritycheck/mimetypeListModified
 		self::assertEquals($newFile, file_get_contents(\OC::$SERVERROOT . '/tests/data/integritycheck/mimetypeListModified/core/js/mimetypelist.js'));
 
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -786,7 +791,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreSignatureWithValidSignatureDataAndNotAlphabeticOrder(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -823,7 +828,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreSignatureWithTamperedSignatureData(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -866,7 +871,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreSignatureWithTamperedFiles(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -924,7 +929,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreWithInvalidCertificate(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -967,7 +972,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyCoreWithDifferentScope(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -1012,6 +1017,7 @@ class CheckerTest extends TestCase {
 	public function testRunInstanceVerification(): void {
 		$this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
 			->setConstructorArgs([
+				$this->serverVersion,
 				$this->environmentHelper,
 				$this->fileAccessHelper,
 				$this->appLocator,
@@ -1090,7 +1096,7 @@ class CheckerTest extends TestCase {
 	}
 
 	public function testVerifyAppSignatureWithoutSignatureDataAndCodeCheckerDisabled(): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn('stable');
@@ -1120,7 +1126,7 @@ class CheckerTest extends TestCase {
 	 * @dataProvider channelDataProvider
 	 */
 	public function testIsCodeCheckEnforced($channel, $isCodeSigningEnforced): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn($channel);
@@ -1138,7 +1144,7 @@ class CheckerTest extends TestCase {
 	 * @dataProvider channelDataProvider
 	 */
 	public function testIsCodeCheckEnforcedWithDisabledConfigSwitch($channel): void {
-		$this->environmentHelper
+		$this->serverVersion
 			->expects($this->once())
 			->method('getChannel')
 			->willReturn($channel);
diff --git a/tests/lib/IntegrityCheck/Helpers/EnvironmentHelperTest.php b/tests/lib/IntegrityCheck/Helpers/EnvironmentHelperTest.php
index b8280d9816a..379eb178b06 100644
--- a/tests/lib/IntegrityCheck/Helpers/EnvironmentHelperTest.php
+++ b/tests/lib/IntegrityCheck/Helpers/EnvironmentHelperTest.php
@@ -22,8 +22,4 @@ class EnvironmentHelperTest extends TestCase {
 	public function testGetServerRoot(): void {
 		$this->assertSame(\OC::$SERVERROOT, $this->environmentHelper->getServerRoot());
 	}
-
-	public function testGetChannel(): void {
-		$this->assertSame(\OC_Util::getChannel(), $this->environmentHelper->getChannel());
-	}
 }
diff --git a/tests/lib/PublicNamespace/UtilTest.php b/tests/lib/PublicNamespace/UtilTest.php
deleted file mode 100644
index 4fa31bd902a..00000000000
--- a/tests/lib/PublicNamespace/UtilTest.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-/**
- * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-namespace Test\PublicNamespace;
-
-class UtilTest extends \Test\TestCase {
-	/**
-	 * @dataProvider channelProvider
-	 *
-	 * @param string $channel
-	 */
-	public function testOverrideChannel($channel): void {
-		\OCP\Util::setChannel($channel);
-		$actual = \OCP\Util::getChannel($channel);
-		$this->assertEquals($channel, $actual);
-	}
-	
-	public function channelProvider() {
-		return [
-			['daily'],
-			['beta'],
-			['stable'],
-			['production']
-		];
-	}
-}
diff --git a/tests/lib/Updater/VersionCheckTest.php b/tests/lib/Updater/VersionCheckTest.php
index 94347265427..51d1625ea4d 100644
--- a/tests/lib/Updater/VersionCheckTest.php
+++ b/tests/lib/Updater/VersionCheckTest.php
@@ -12,11 +12,13 @@ use OCP\Http\Client\IClientService;
 use OCP\IAppConfig;
 use OCP\IConfig;
 use OCP\IUserManager;
+use OCP\ServerVersion;
 use OCP\Support\Subscription\IRegistry;
-use OCP\Util;
 use Psr\Log\LoggerInterface;
 
 class VersionCheckTest extends \Test\TestCase {
+	/** @var ServerVersion|\PHPUnit\Framework\MockObject\MockObject */
+	private $serverVersion;
 	/** @var IConfig| \PHPUnit\Framework\MockObject\MockObject */
 	private $config;
 	/** @var IAppConfig| \PHPUnit\Framework\MockObject\MockObject */
@@ -30,15 +32,12 @@ class VersionCheckTest extends \Test\TestCase {
 
 	protected function setUp(): void {
 		parent::setUp();
-		$this->config = $this->getMockBuilder(IConfig::class)
-			->disableOriginalConstructor()
-			->getMock();
-		$this->appConfig = $this->getMockBuilder(IAppConfig::class)
-			->disableOriginalConstructor()
-			->getMock();
-		$clientService = $this->getMockBuilder(IClientService::class)
-			->disableOriginalConstructor()
-			->getMock();
+		$this->serverVersion = $this->createMock(ServerVersion::class);
+		$this->config = $this->createMock(IConfig::class);
+		$this->appConfig = $this->createMock(IAppConfig::class);
+		$clientService = $this->createMock(IClientService::class);
+
+		$this->serverVersion->method('getChannel')->willReturn('git');
 
 		$this->registry = $this->createMock(IRegistry::class);
 		$this->registry
@@ -48,6 +47,7 @@ class VersionCheckTest extends \Test\TestCase {
 		$this->updater = $this->getMockBuilder(VersionCheck::class)
 			->setMethods(['getUrlContent'])
 			->setConstructorArgs([
+				$this->serverVersion,
 				$clientService,
 				$this->config,
 				$this->appConfig,
@@ -63,7 +63,8 @@ class VersionCheckTest extends \Test\TestCase {
 	 * @return string
 	 */
 	private function buildUpdateUrl($baseUrl) {
-		return $baseUrl . '?version=' . implode('x', Util::getVersion()) . 'xinstalledatx' . time() . 'x' . \OC_Util::getChannel() . 'xxx' . PHP_MAJOR_VERSION . 'x' . PHP_MINOR_VERSION . 'x' . PHP_RELEASE_VERSION . 'x0x0';
+		$serverVersion = \OCP\Server::get(ServerVersion::class);
+		return $baseUrl . '?version=' . implode('x', $serverVersion->getVersion()) . 'xinstalledatx' . time() . 'x' . $serverVersion->getChannel() . 'xxx' . PHP_MAJOR_VERSION . 'x' . PHP_MINOR_VERSION . 'x' . PHP_RELEASE_VERSION . 'x0x0';
 	}
 
 	public function testCheckInCache(): void {
diff --git a/tests/lib/UpdaterTest.php b/tests/lib/UpdaterTest.php
index da48e581fbc..81babee7029 100644
--- a/tests/lib/UpdaterTest.php
+++ b/tests/lib/UpdaterTest.php
@@ -12,10 +12,13 @@ use OC\IntegrityCheck\Checker;
 use OC\Updater;
 use OCP\IAppConfig;
 use OCP\IConfig;
+use OCP\ServerVersion;
 use PHPUnit\Framework\MockObject\MockObject;
 use Psr\Log\LoggerInterface;
 
 class UpdaterTest extends TestCase {
+	/** @var ServerVersion|MockObject */
+	private $serverVersion;
 	/** @var IConfig|MockObject */
 	private $config;
 	/** @var IAppConfig|MockObject */
@@ -31,23 +34,15 @@ class UpdaterTest extends TestCase {
 
 	protected function setUp(): void {
 		parent::setUp();
-		$this->config = $this->getMockBuilder(IConfig::class)
-			->disableOriginalConstructor()
-			->getMock();
-		$this->appConfig = $this->getMockBuilder(IAppConfig::class)
-			->disableOriginalConstructor()
-			->getMock();
-		$this->logger = $this->getMockBuilder(LoggerInterface::class)
-			->disableOriginalConstructor()
-			->getMock();
-		$this->checker = $this->getMockBuilder(Checker::class)
-			->disableOriginalConstructor()
-			->getMock();
-		$this->installer = $this->getMockBuilder(Installer::class)
-			->disableOriginalConstructor()
-			->getMock();
+		$this->serverVersion = $this->createMock(ServerVersion::class);
+		$this->config = $this->createMock(IConfig::class);
+		$this->appConfig = $this->createMock(IAppConfig::class);
+		$this->logger = $this->createMock(LoggerInterface::class);
+		$this->checker = $this->createMock(Checker::class);
+		$this->installer = $this->createMock(Installer::class);
 
 		$this->updater = new Updater(
+			$this->serverVersion,
 			$this->config,
 			$this->appConfig,
 			$this->checker,
diff --git a/tests/lib/UtilTest.php b/tests/lib/UtilTest.php
index 064b73d0b7e..c1dea8d5423 100644
--- a/tests/lib/UtilTest.php
+++ b/tests/lib/UtilTest.php
@@ -24,16 +24,6 @@ class UtilTest extends \Test\TestCase {
 		}
 	}
 
-	public function testGetVersionString(): void {
-		$version = \OC_Util::getVersionString();
-		$this->assertTrue(is_string($version));
-	}
-
-	public function testGetEditionString(): void {
-		$edition = \OC_Util::getEditionString();
-		$this->assertTrue(is_string($edition));
-	}
-
 	public function testSanitizeHTML(): void {
 		$badArray = [
 			'While it is unusual to pass an array',