diff --git a/.htaccess b/.htaccess
index ce89e17..526c60b 100644
--- a/.htaccess
+++ b/.htaccess
@@ -111,7 +111,8 @@ DirectoryIndex index.php index.html index.htm
 
   # Redirect common PHP files to their new locations.
   RewriteCond %{REQUEST_URI} ^(.*)?/(update.php) [OR]
-  RewriteCond %{REQUEST_URI} ^(.*)?/(install.php)
+  RewriteCond %{REQUEST_URI} ^(.*)?/(install.php) [OR]
+  RewriteCond %{REQUEST_URI} ^(.*)?/(rebuild.php)
   RewriteCond %{REQUEST_URI} !core
   RewriteRule ^ %1/core/%2 [L,QSA,R=301]
 
diff --git a/core/rebuild.php b/core/rebuild.php
new file mode 100644
index 0000000..4a83715
--- /dev/null
+++ b/core/rebuild.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Rebuilds all Drupal caches even when Drupal itself does not work.
+ *
+ * Needs a token query argument which can be calculated using the
+ * scripts/rebuild_token_calculator.sh script.
+ */
+
+use Drupal\Component\PhpStorage\PhpStorageFactory;
+use Drupal\Core\Cache\Cache;
+use Drupal\Component\Utility\Crypt;
+
+// Change the directory to the Drupal root.
+chdir('..');
+
+require_once dirname(__DIR__) . '/core/includes/bootstrap.inc';
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+
+if (settings()->get('rebuild_access', FALSE) ||
+  (isset($_GET['token'], $_GET['timestamp']) &&
+    ((REQUEST_TIME - $_GET['timestamp']) < 300) &&
+    ($_GET['token'] === Crypt::hmacBase64($_GET['timestamp'], $GLOBALS['drupal_hash_salt']))
+  )) {
+  // drupal_bootstrap(DRUPAL_BOOTSTRAP_KERNEL) will build a new kernel. This
+  // comes before DRUPAL_BOOTSTRAP_PAGE_CACHE.
+  PhpStorageFactory::get('service_container')->deleteAll();
+  PhpStorageFactory::get('twig')->deleteAll();
+  $GLOBALS['conf']['system.performance']['cache.page.use_internal'] = FALSE;
+
+  // Bootstrap up to where caches exist and clear them.
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_PAGE_CACHE);
+  foreach (Cache::getBins() as $bin) {
+    $bin->deleteAll();
+  }
+
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+  drupal_flush_all_caches();
+  drupal_set_message('Cache rebuild complete.');
+}
+
+header('Location: ' . $GLOBALS['base_url']);
diff --git a/core/scripts/rebuild_token_calculator.sh b/core/scripts/rebuild_token_calculator.sh
new file mode 100755
index 0000000..e9d8832
--- /dev/null
+++ b/core/scripts/rebuild_token_calculator.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env php
+
+<?php
+
+/**
+ * @file
+ * Command line token calculator for rebuild.php.
+ */
+
+require_once __DIR__ . '/../vendor/autoload.php';
+require_once dirname(__DIR__) . '/includes/bootstrap.inc';
+
+use Drupal\Component\Utility\Crypt;
+
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+
+if (PHP_SAPI !== 'cli') {
+  exit;
+}
+
+$timestamp = time();
+$token = Crypt::hmacBase64($timestamp, $drupal_hash_salt);
+
+print "timestamp=$timestamp&token=$token\n";
