diff --git a/core/ajax/update.php b/core/ajax/update.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f5398f41cb6178d88637b8a9a4df2a43fc07890
--- /dev/null
+++ b/core/ajax/update.php
@@ -0,0 +1,36 @@
+<?php
+set_time_limit(0);
+$RUNTIME_NOAPPS = true;
+require_once '../../lib/base.php';
+
+if (OC::checkUpgrade(false)) {
+	$updateEventSource = new OC_EventSource();
+	$updateEventSource->send('success', 'Turned on maintenance mode');
+	// Check if the .htaccess is existing - this is needed for upgrades from really old ownCloud versions
+	if (isset($_SERVER['SERVER_SOFTWARE']) && strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) {
+		if (!OC_Util::ishtaccessworking()) {
+			if (!file_exists(OC::$SERVERROOT . '/data/.htaccess')) {
+				OC_Setup::protectDataDirectory();
+			}
+		}
+	}
+	$result = OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/db_structure.xml');
+	if (!$result) {
+		$updateEventSource->send('failure', 'Error updating database');
+		$updateEventSource->close();
+		die();
+	}
+	$updateEventSource->send('success', 'Updated database');
+	$minimizerCSS = new OC_Minimizer_CSS();
+	$minimizerCSS->clearCache();
+	$minimizerJS = new OC_Minimizer_JS();
+	$minimizerJS->clearCache();
+	OC_Config::setValue('version', implode('.', OC_Util::getVersion()));
+	OC_App::checkAppsRequirements();
+	// load all apps to also upgrade enabled apps
+	OC_App::loadApps();
+	OC_Config::setValue('maintenance', false);
+	$updateEventSource->send('success', 'Turned off maintenance mode');
+	$updateEventSource->send('done', 'done');
+	$updateEventSource->close();
+}
\ No newline at end of file
diff --git a/core/css/styles.css b/core/css/styles.css
index d635916b5ae6a5ab554e54de271f0093c5963fb7..6e1cef72eda8a0a0642c64d521ac1b0cbb2775a3 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -214,7 +214,8 @@ div.jp-play-bar, div.jp-seek-bar { padding:0; }
 .pager { list-style:none; float:right; display:inline; margin:.7em 13em 0 0; }
 .pager li { display:inline-block; }
 
-li.error { width:640px; margin:4em auto; padding:1em 1em 1em 4em; background:#ffe .8em .8em no-repeat; color:#FF3B3B; border:1px solid #ccc; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; }
+li.update, li.error { width:640px; margin:4em auto; padding:1em 1em 1em 4em; background:#ffe .8em .8em no-repeat;  border:1px solid #ccc; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; cursor:default; }
+.error { color:#FF3B3B; }
 .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { overflow:hidden; text-overflow:ellipsis; }
 .hint { background-image:url('../img/actions/info.png'); background-repeat:no-repeat; color:#777777; padding-left:25px; background-position:0 0.3em;}
 .separator { display:inline; border-left:1px solid #d3d3d3; border-right:1px solid #fff; height:10px; width:0px; margin:4px; }
diff --git a/core/templates/update.php b/core/templates/update.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf3f2ab0d790083419e8a7d2dcf7c37ec3b4a586
--- /dev/null
+++ b/core/templates/update.php
@@ -0,0 +1,27 @@
+<ul>
+	<li class='update'>
+		<?php echo $l->t('Updating ownCloud from version %s to version %s, this may take a while.', array($_['installed'], $_['current'])); ?><br /><br />
+	</li>
+</ul>
+<script>
+	$(document).ready(function () {
+		OC.EventSource.requesttoken = oc_requesttoken;
+		var updateEventSource = new OC.EventSource(OC.webroot+'/core/ajax/update.php');
+		updateEventSource.listen('success', function(message) {
+			$('<span>').append(message).append('<br />').appendTo($('.update'));
+		});
+		updateEventSource.listen('error', function(message) {
+			$('<span>').addClass('error').append(message).append('<br />').appendTo($('.update'));
+		});
+		updateEventSource.listen('failure', function(message) {
+			$('<span>').addClass('error').append(message).append('<br />').appendTo($('.update'));
+			$('<span>').addClass('error bold').append('<br />').append(t('core', 'The update was unsuccessful. Please report this issue to the <a href="https://github.com/owncloud/core/issues" target="_blank">ownCloud community</a>.')).appendTo($('.update'));
+		});
+		updateEventSource.listen('done', function(message) {
+			$('<span>').addClass('bold').append('<br />').append(t('core', 'The update was successful. Redirecting you to ownCloud now.')).appendTo($('.update'));
+			setTimeout(function () {
+				window.location.href = OC.webroot;
+			}, 3000);
+		});
+	});
+</script>
\ No newline at end of file
diff --git a/lib/base.php b/lib/base.php
index eaef984df347d61316a65f3d3466838b36dcfe28..ec08ccc67be00207dbff381d10501a9ade1dd092 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -229,8 +229,10 @@ class OC
     }
 
 	public static function checkMaintenanceMode() {
-		if (OC_Config::getValue('maintenance', false)) {
+		// Allow ajax update script to execute without being stopped
+		if (OC_Config::getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
 			$tmpl = new OC_Template('', 'error', 'guest');
+			$tmpl->assign('errors', array(1 => array('error' => 'ownCloud is in maintenance mode')));
 			$tmpl->printPage();
 			exit();
 		}
@@ -241,9 +243,12 @@ class OC
 			$installedVersion = OC_Config::getValue('version', '0.0.0');
 			$currentVersion = implode('.', OC_Util::getVersion());
 			if (version_compare($currentVersion, $installedVersion, '>')) {
-				if ($showTemplate) {
+				if ($showTemplate && !OC_Config::getValue('maintenance', false)) {
+					OC_Config::setValue('maintenance', true);
 					OC_Log::write('core', 'starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, OC_Log::DEBUG);
-					$tmpl = new OC_Template('', 'error', 'guest');
+					$tmpl = new OC_Template('', 'update', 'guest');
+					$tmpl->assign('current', $currentVersion);
+					$tmpl->assign('installed', $installedVersion);
 					$tmpl->printPage();
 					exit();
 				} else {
@@ -254,33 +259,6 @@ class OC
 		}
 	}
 
-	public static function doUpgrade() {
-		if (self::checkUpgrade(false)) {
-			OC_Config::setValue('maintenance', true);
-			// Check if the .htaccess is existing - this is needed for upgrades from really old ownCloud versions
-			if (isset($_SERVER['SERVER_SOFTWARE']) && strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) {
-				if (!OC_Util::ishtaccessworking()) {
-					if (!file_exists(OC::$SERVERROOT . '/data/.htaccess')) {
-						OC_Setup::protectDataDirectory();
-					}
-				}
-			}
-			$result = OC_DB::updateDbFromStructure(OC::$SERVERROOT . '/db_structure.xml');
-			if (!$result) {
-				echo 'Error while upgrading the database';
-				die();
-			}
-			$minimizerCSS = new OC_Minimizer_CSS();
-			$minimizerCSS->clearCache();
-			$minimizerJS = new OC_Minimizer_JS();
-			$minimizerJS->clearCache();
-			OC_Config::setValue('version', implode('.', OC_Util::getVersion()));
-			OC_App::checkAppsRequirements();
-			// load all apps to also upgrade enabled apps
-			OC_App::loadApps();
-		}
-	}
-
     public static function initTemplateEngine()
     {
         // Add the stuff we need always
@@ -297,12 +275,6 @@ class OC
         OC_Util::addScript('search', 'result');
         OC_Util::addScript('router');
 
-        if (OC_Config::getValue('installed', false)) {
-            if (OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
-                OC_Util::addScript('backgroundjobs');
-            }
-        }
-
         OC_Util::addStyle("styles");
         OC_Util::addStyle("multiselect");
         OC_Util::addStyle("jquery-ui-1.8.16.custom");
@@ -433,7 +405,7 @@ class OC
         self::initSession();
         self::initTemplateEngine();
 	self::checkMaintenanceMode();
-        self::checkUpgrade();
+	self::checkUpgrade();
 
         $errors = OC_Util::checkServer();
         if (count($errors) > 0) {
@@ -508,6 +480,9 @@ class OC
         if (OC_Util::issetlocaleworking() == false) {
             OC_Log::write('core', 'setting locate to en_US.UTF-8 failed. Support is probably not installed on your system', OC_Log::ERROR);
         }
+	if (OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
+		OC_Util::addScript('backgroundjobs');
+	}
     }
 
     /**