diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index e2354f4..8b1f645 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -9,6 +9,8 @@
 
 use Drupal\Core\Config\TypedConfigManager;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Lock\LockBackendInterface;
 use Drupal\Component\Uuid\UuidInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -89,18 +91,25 @@ class ConfigImporter {
   protected $validated;
 
   /**
-   * The UUID service.
+   * The typed config manager.
    *
-   * @var \Drupal\Component\Uuid\UuidInterface
+   * @var \Drupal\Core\Config\TypedConfigManager
    */
-  protected $uuidService;
+  protected $typedConfigManager;
 
   /**
-   * The typed config manager.
+   * The module handler.
    *
-   * @var \Drupal\Core\Config\TypedConfigManager
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
    */
-  protected $typedConfigManager;
+  protected $moduleHandler;
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
 
   /**
    * Constructs a configuration import object.
@@ -116,19 +125,22 @@ class ConfigImporter {
    *   The entity manager used to import config entities.
    * @param \Drupal\Core\Lock\LockBackendInterface
    *   The lock backend to ensure multiple imports do not occur at the same time.
-   * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
-   *   The UUID service.
    * @param \Drupal\Core\Config\TypedConfigManager $typed_config
    *   The typed configuration manager.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler
    */
-  public function __construct(StorageComparerInterface $storage_comparer, EventDispatcherInterface $event_dispatcher, ConfigFactory $config_factory, EntityManagerInterface $entity_manager, LockBackendInterface $lock, UuidInterface $uuid_service, TypedConfigManager $typed_config) {
+  public function __construct(StorageComparerInterface $storage_comparer, EventDispatcherInterface $event_dispatcher, ConfigFactory $config_factory, EntityManagerInterface $entity_manager, LockBackendInterface $lock, TypedConfigManager $typed_config, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
     $this->storageComparer = $storage_comparer;
     $this->eventDispatcher = $event_dispatcher;
     $this->configFactory = $config_factory;
     $this->entityManager = $entity_manager;
     $this->lock = $lock;
-    $this->uuidService = $uuid_service;
     $this->typedConfigManager = $typed_config;
+    $this->moduleHandler = $module_handler;
+    $this->themeHandler = $theme_handler;
     $this->processed = $this->storageComparer->getEmptyChangelist();
   }
 
@@ -227,6 +239,7 @@ public function import() {
         // Another process is synchronizing configuration.
         throw new ConfigImporterException(sprintf('%s is already importing', static::ID));
       }
+      $this->handleExtensions();
       $this->importInvokeOwner();
       $this->importConfig();
       // Allow modules to react to a import.
@@ -346,4 +359,116 @@ public function getId() {
     return static::ID;
   }
 
+  /**
+   * Checks if a configuration object will be updated by the import.
+   *
+   * @param $config_name
+   *   The configuration object name.
+   *
+   * @return bool
+   *   TRUE if the configuration object will be updated.
+   */
+  protected function hasUpdate($config_name) {
+    return in_array($config_name, $this->getUnprocessed('update'));
+  }
+
+  /**
+   * Handle changes to installed modules and themes.
+   */
+  protected function handleExtensions() {
+    // Are there changes to process?
+    $module_update = $this->hasUpdate('system.module');
+    $theme_update = $this->hasUpdate('system.theme');
+    if ($module_update || $theme_update) {
+      // Set the config installer to use the staging directory instead of the
+      // extensions own default config directories.
+      \Drupal::service('config.installer')
+        ->setSyncing(TRUE)
+        ->setSourceStorage($this->storageComparer->getSourceStorage());
+
+      if ($module_update) {
+        $this->handleModules();
+      }
+
+      if ($theme_update) {
+        $this->handleThemes();
+      }
+
+      \Drupal::service('config.installer')
+        ->setSyncing(FALSE)
+        ->resetSourceStorage();
+
+      // Recalculate differences as default config could have been imported.
+      $this->storageComparer->reset();
+      $this->processed = $this->storageComparer->getEmptyChangelist();
+      drupal_flush_all_caches();
+      // Modules have been updated. Services etc might have changed.
+      // We don't reinject storage comparer because swapping out the active
+      // store during config import is a complete nonsense.
+      $this->reInjectMe();
+
+    }
+  }
+
+  /**
+   * Install or uninstall modules depending on configuration to import.
+   */
+  protected function handleModules() {
+    $current = $this->storageComparer->getTargetStorage()->read('system.module');
+    $new = $this->storageComparer->getSourceStorage()->read('system.module');
+
+    $to_enable = array_diff(array_keys($new['enabled']), array_keys($current['enabled']));
+    if (!$this->moduleHandler->install($to_enable)) {
+      throw new ConfigImporterException(sprintf('Unable to enable modules'));
+    }
+
+    $to_uninstall = array_diff(array_keys($current['enabled']), array_keys($new['enabled']));
+    if (!$this->moduleHandler->uninstall($to_uninstall)) {
+       throw new ConfigImporterException(sprintf('Unable to uninstall modules'));
+    }
+  }
+
+  /**
+   * Enable or disable themes depending on configuration to import.
+   */
+  protected function handleThemes() {
+    $current = $this->storageComparer->getTargetStorage()->read('system.theme');
+    $new = $this->storageComparer->getSourceStorage()->read('system.theme');
+
+    $enabled = isset($current['enabled']) ? $current['enabled'] : array();
+
+    $themes_to_enable = array_diff(array_keys($new['enabled']), array_keys($enabled));
+    $themes_to_disable = array_diff(array_keys($enabled), array_keys($new['enabled']));
+
+    if (!empty($themes_to_enable)) {
+      $this->themeHandler->enable($themes_to_enable);
+    }
+
+    // Are we disabling the default theme? This is not possible. Update the
+    // value to the value from the staged configuration. Enabling themes first
+    // ensures that if any of the newly enabled themes are the default theme it
+    // will be already enabled.
+    if(in_array($current['default'], $themes_to_disable)) {
+      // Use the configuration factory to write the data since system.theme
+      // might have been updated by enabling themes.
+      $this->configFactory
+        ->get('system.theme')
+        ->set('default', $new['default'])
+        ->save();
+    }
+
+    if (!empty($themes_to_disable)) {
+      $this->themeHandler->disable($themes_to_disable);
+    }
+  }
+
+  protected function reInjectMe() {
+    $this->eventDispatcher = \Drupal::service('event_dispatcher');
+    $this->configFactory = \Drupal::configFactory();
+    $this->entityManager = \Drupal::entityManager();
+    $this->lock = \Drupal::lock();
+    $this->typedConfigManager = \Drupal::service('config.typed');
+    $this->moduleHandler = \Drupal::moduleHandler();
+    $this->themeHandler = \Drupal::service('theme_handler');
+  }
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index 0be3354..ca1ebaf 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -49,6 +49,20 @@ class ConfigInstaller implements ConfigInstallerInterface {
   protected $eventDispatcher;
 
   /**
+   * The configuration storage that provides the default configuration.
+   *
+   * @var \Drupal\Core\Config\StorageInterface
+   */
+  protected $sourceStorage;
+
+  /**
+   * Is configuration being created as part of a configuration sync.
+   *
+   * @var bool
+   */
+  protected $isSyncing = FALSE;
+
+  /**
    * Constructs the configuration installer.
    *
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
@@ -75,7 +89,7 @@ public function __construct(ConfigFactory $config_factory, StorageInterface $act
    */
   public function installDefaultConfig($type, $name) {
     // Get all default configuration owned by this extension.
-    $source_storage = new ExtensionInstallStorage($this->activeStorage);
+    $source_storage = $this->getSourceStorage();
     $config_to_install = $source_storage->listAll($name . '.');
 
     // Work out if this extension provides default configuration for any other
@@ -119,7 +133,15 @@ public function installDefaultConfig($type, $name) {
         if ($data !== FALSE) {
           $new_config->setData($data);
         }
-        if ($entity_type = config_get_entity_type_by_name($name)) {
+        if (!$this->isSyncing && $entity_type = config_get_entity_type_by_name($name)) {
+          // If we are syncing do not create configuration entities. Pluggable
+          // configuration entities can have dependencies on modules that are
+          // not yet enabled. In the absence of dependency management for config
+          // entities this is a good as we can do. The problem with this
+          // approach is that any code that expects default configuration
+          // entities to exist (even if there is code the prevents this from
+          // happening) will be unstable after the module has been enabled and
+          // before the config entity has been imported.
           $this->entityManager
             ->getStorageController($entity_type)
             ->create($new_config->get())
@@ -133,4 +155,49 @@ public function installDefaultConfig($type, $name) {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setSourceStorage(StorageInterface $storage) {
+    $this->sourceStorage = $storage;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function resetSourceStorage() {
+    $this->sourceStorage = null;
+    return $this;
+  }
+
+  /**
+   * Gets the configuration storage that provides the default configuration.
+   *
+   * @return \Drupal\Core\Config\StorageInterface
+   *   The configuration storage that provides the default configuration.
+   */
+  public function getSourceStorage() {
+    if (!isset($this->sourceStorage)) {
+      // If using the the extension install storage class can not
+      return new ExtensionInstallStorage($this->activeStorage);
+    }
+    return $this->sourceStorage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setSyncing($status) {
+    $this->isSyncing = $status;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isSyncing() {
+    return $this->isSyncing;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
index 927c610..6e7c20d 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
@@ -37,4 +37,38 @@
    */
   public function installDefaultConfig($type, $name);
 
+  /**
+   * Sets the configuration storage that provides the default configuration.
+   *
+   * @param \Drupal\Core\Config\StorageInterface $storage
+   *
+   * @return self
+   *   The configuration installer.
+   */
+  public function setSourceStorage(StorageInterface $storage);
+
+  /**
+   * Resets the configuration storage that provides the default configuration.
+   *
+   * @return self
+   *   The configuration installer.
+   */
+  public function resetSourceStorage();
+
+  /**
+   * Sets the status of the isSyncing flag.
+   *
+   * @param bool $status
+   *   The status of the sync flag.
+   */
+  public function setSyncing($status);
+
+  /**
+   * Gets the syncing state.
+   *
+   * @return bool
+   *   Returns TRUE is syncing flag set.
+   */
+  public function isSyncing();
+
 }
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index a988135..49090b5 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -131,6 +131,7 @@ public function status() {
    */
   public function setSyncing($syncing) {
     $this->isSyncing = $syncing;
+    return $this;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
index 5aa737d..d24d2ac 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
@@ -64,6 +64,9 @@ public function setStatus($status);
    *
    * @param bool $status
    *   The status of the sync flag.
+   *
+   * @return \Drupal\Core\Config\Entity\ConfigEntityInterface
+   *   The class instance that this method is called on.
    */
   public function setSyncing($status);
 
diff --git a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
index 5bedbbe..5762847 100644
--- a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
+++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Config\InstallStorage;
 use Drupal\Core\Config\StorageException;
+use Drupal\Core\Config\StorageInterface;
 
 /**
  * Defines the file storage controller for metadata files.
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index d486973..7e78283 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -551,6 +551,12 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
     // Required for module installation checks.
     include_once DRUPAL_ROOT . '/core/includes/install.inc';
 
+    /** @var \Drupal\Core\Config\ConfigInstaller $config_installer */
+    $config_installer = \Drupal::service('config.installer');
+    $sync_status = $config_installer->isSyncing();
+    if ($sync_status) {
+      $source_storage = $config_installer->getSourceStorage();
+    }
     $modules_installed = array();
     foreach ($module_list as $module) {
       $enabled = $module_config->get("enabled.$module") !== NULL;
@@ -633,6 +639,12 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         $version = $versions ? max($versions) : SCHEMA_INSTALLED;
 
         // Install default configuration of the module.
+        $config_installer = \Drupal::service('config.installer');
+        if ($sync_status) {
+          $config_installer
+            ->setSyncing(TRUE)
+            ->setSourceStorage($source_storage);
+        }
         \Drupal::service('config.installer')->installDefaultConfig('module', $module);
 
         // If the module has no current updates, but has some that were
@@ -694,7 +706,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
 
           // Skip already uninstalled modules.
           if (isset($installed_modules[$dependent]) && !isset($module_list[$dependent]) && $dependent != $profile) {
-            $module_list[$dependent] = TRUE;
+            $module_list[$dependent] = $dependent;
           }
         }
       }
diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigSync.php b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php
index 8e95d7e..bee55aa 100644
--- a/core/modules/config/lib/Drupal/config/Form/ConfigSync.php
+++ b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php
@@ -9,6 +9,8 @@
 
 use Drupal\Component\Uuid\UuidInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\Lock\LockBackendInterface;
@@ -67,18 +69,25 @@ class ConfigSync extends FormBase {
   protected $urlGenerator;
 
   /**
-   * The UUID service.
+   * The typed config manager.
    *
-   * @var \Drupal\Component\Uuid\UuidInterface
+   * @var \Drupal\Core\Config\TypedConfigManager
    */
-  protected $uuidService;
+  protected $typedConfigManager;
 
   /**
-   * The typed config manager.
+   * The module handler.
    *
-   * @var \Drupal\Core\Config\TypedConfigManager
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
    */
-  protected $typedConfigManager;
+  protected $moduleHandler;
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
 
   /**
    * Constructs the object.
@@ -101,8 +110,12 @@ class ConfigSync extends FormBase {
    *   The UUID Service.
    * @param \Drupal\Core\Config\TypedConfigManager $typed_config
    *   The typed configuration manager.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler
    */
-  public function __construct(StorageInterface $sourceStorage, StorageInterface $targetStorage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigFactory $config_factory, EntityManagerInterface $entity_manager, UrlGeneratorInterface $url_generator, UuidInterface $uuid_service, TypedConfigManager $typed_config) {
+  public function __construct(StorageInterface $sourceStorage, StorageInterface $targetStorage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigFactory $config_factory, EntityManagerInterface $entity_manager, UrlGeneratorInterface $url_generator, TypedConfigManager $typed_config, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
     $this->sourceStorage = $sourceStorage;
     $this->targetStorage = $targetStorage;
     $this->lock = $lock;
@@ -110,8 +123,9 @@ public function __construct(StorageInterface $sourceStorage, StorageInterface $t
     $this->configFactory = $config_factory;
     $this->entity_manager = $entity_manager;
     $this->urlGenerator = $url_generator;
-    $this->uuidService = $uuid_service;
     $this->typedConfigManager = $typed_config;
+    $this->moduleHandler = $module_handler;
+    $this->themeHandler = $theme_handler;
   }
 
   /**
@@ -126,8 +140,9 @@ public static function create(ContainerInterface $container) {
       $container->get('config.factory'),
       $container->get('entity.manager'),
       $container->get('url_generator'),
-      $container->get('uuid'),
-      $container->get('config.typed')
+      $container->get('config.typed'),
+      $container->get('module_handler'),
+      $container->get('theme_handler')
     );
   }
 
@@ -239,8 +254,9 @@ public function submitForm(array &$form, array &$form_state) {
       $this->configFactory,
       $this->entity_manager,
       $this->lock,
-      $this->uuidService,
-      $this->typedConfigManager
+      $this->typedConfigManager,
+      $this->moduleHandler,
+      $this->themeHandler
     );
     if ($config_importer->alreadyImporting()) {
       drupal_set_message($this->t('Another request may be synchronizing configuration already.'));
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportAllTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportAllTest.php
new file mode 100644
index 0000000..4e556f7
--- /dev/null
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportAllTest.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\config\Tests\ConfigImportAllTest.
+ */
+
+namespace Drupal\config\Tests;
+
+
+use Drupal\system\Tests\Module\ModuleTestBase;
+
+class ConfigImportAllTest extends ModuleTestBase {
+
+  /**
+   * The profile to install as a basis for testing.
+   *
+   * Using the standard profile as this has a lot of additional configuration.
+   *
+   * @var string
+   */
+  protected $profile = 'standard';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Install/uninstall modules',
+      'description' => 'Install/uninstall core module and confirm table creation/deletion.',
+      'group' => 'Module',
+    );
+  }
+
+  /**
+   * Tests that a fixed set of modules can be installed and uninstalled.
+   */
+  public function testInstallUninstall() {
+
+    // Get a list of modules to enable.
+    $all_modules = system_rebuild_module_data();
+    $all_modules = array_filter($all_modules, function ($module) {
+      // Filter hidden, already enabled modules and modules in the Testing
+      // package.
+      if (!empty($module->info['hidden']) || $module->status == TRUE || $module->info['package'] == 'Testing') {
+        return FALSE;
+      }
+      return TRUE;
+    });
+
+    // Install every module possible.
+    \Drupal::moduleHandler()->install(array_keys($all_modules));
+
+    $this->assertModules(array_keys($all_modules), TRUE);
+    foreach($all_modules as $module => $info) {
+      $this->assertModuleConfig($module);
+      $this->assertModuleTablesExist($module);
+    }
+
+    // Export active config to staging
+    $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
+
+    system_list_reset();
+    $this->resetAll();
+
+    // Delete every field on the site so all modules can be disabled. For
+    // example, if a comment field exists then module becomes required and can
+    // not be uninstalled.
+    $fields = \Drupal::service('field.info')->getFields();
+    foreach ($fields as $field) {
+      entity_invoke_bundle_hook('delete', $field->entity_type, $field->entity_type . '__' . $field->name);
+      $field->delete();
+    }
+    // Purge the data.
+    field_purge_batch(1000);
+
+    system_list_reset();
+    $all_modules = system_rebuild_module_data();
+    $all_modules = array_filter($all_modules, function ($module) {
+      // Filter required and not enabled modules.
+      if (!empty($module->info['required']) || $module->status == FALSE) {
+        return FALSE;
+      }
+      return TRUE;
+    });
+
+    $this->assertTrue(isset($all_modules['comment']), 'The comment module will be disabled');
+
+    \Drupal::moduleHandler()->uninstall(array_keys($all_modules));
+
+    $this->assertModules(array_keys($all_modules), FALSE);
+    foreach($all_modules as $module => $info) {
+      $this->assertNoModuleConfig($module);
+      $this->assertModuleTablesDoNotExist($module);
+    }
+
+    $this->configImporter()->import();
+
+    $this->assertModules(array_keys($all_modules), TRUE);
+    foreach($all_modules as $module => $info) {
+      $this->assertModuleConfig($module);
+      $this->assertModuleTablesExist($module);
+    }
+
+    // Ensure that we have no configuration changes to import.
+    $admin_user = $this->drupalCreateUser(array('synchronize configuration'));
+    $this->drupalLogin($admin_user);
+    $this->drupalGet('admin/config/development/configuration');
+    $this->assertText('There are no configuration changes.');
+  }
+}
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
index e495602..9aa2463 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\config\Tests;
 
+use Drupal\Core\Config\InstallStorage;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -14,7 +15,7 @@
  */
 class ConfigImportUITest extends WebTestBase {
 
-  public static $modules = array('config', 'config_test');
+  public static $modules = array('config', 'config_test', 'config_import_test');
 
   public static function getInfo() {
     return array(
@@ -38,6 +39,7 @@ function setUp() {
   function testImport() {
     $name = 'system.site';
     $dynamic_name = 'config_test.dynamic.new';
+    /** @var \Drupal\Core\Config\StorageInterface $staging */
     $staging = $this->container->get('config.storage.staging');
 
     $this->drupalGet('admin/config/development/configuration');
@@ -63,16 +65,50 @@ function testImport() {
     $staging->write($dynamic_name, $original_dynamic_data);
     $this->assertIdentical($staging->exists($dynamic_name), TRUE, $dynamic_name . ' found.');
 
+    // Enable the Ban and Action modules during import. The Ban module is used
+    // because it creates a table during the install. The Action module is used
+    // because it creates a single simple configuration file during the install.
+    $system_module = \Drupal::config('system.module')->get();
+    $system_module['enabled']['action'] = 0;
+    $system_module['enabled']['ban'] = 0;
+    $system_module['enabled'] = module_config_sort($system_module['enabled']);
+    $staging->write('system.module', $system_module);
+
+    // Use the install storage so that we can read configuration from modules
+    // and themes that are not installed.
+    $install_storage = new InstallStorage();
+
+    // Enable the bartik theme and set it as default.
+    $system_theme = \Drupal::config('system.theme')->get();
+    $system_theme['enabled']['bartik'] = '0';
+    $system_theme['default'] = 'bartik';
+    $staging->write('system.theme', $system_theme);
+    $staging->write('bartik.settings', $install_storage->read('bartik.settings'));
+
+    // Read the action config from module default config folder.
+    $action_settings = $install_storage->read('action.settings');
+    $action_settings['recursion_limit'] = 50;
+    $staging->write('action.settings', $action_settings);
+
     // Verify that both appear as ready to import.
     $this->drupalGet('admin/config/development/configuration');
     $this->assertText($name);
     $this->assertText($dynamic_name);
+    $this->assertText('system.module');
+    $this->assertText('system.theme');
+    $this->assertText('action.settings');
+    $this->assertText('bartik.settings');
     $this->assertFieldById('edit-submit', t('Import all'));
 
     // Import and verify that both do not appear anymore.
     $this->drupalPostForm(NULL, array(), t('Import all'));
     $this->assertNoText($name);
     $this->assertNoText($dynamic_name);
+    $this->assertNoText('system.module');
+    $this->assertNoText('system.theme');
+    $this->assertNoText('action.settings');
+    $this->assertNoText('bartik.settings');
+
     $this->assertNoFieldById('edit-submit', t('Import all'));
 
     // Verify that there are no further changes to import.
@@ -86,6 +122,73 @@ function testImport() {
 
     // Verify the cache got cleared.
     $this->assertTrue(isset($GLOBALS['hook_cache_flush']));
+
+    $this->rebuildContainer();
+    $this->assertTrue(\Drupal::moduleHandler()->moduleExists('ban'), 'Ban module enabled during import.');
+    $this->assertTrue(\Drupal::database()->schema()->tableExists('ban_ip'), 'The database table ban_ip exists.');
+    $this->assertTrue(\Drupal::moduleHandler()->moduleExists('action'), 'Action module enabled during import.');
+
+    $theme_info = \Drupal::service('theme_handler')->listInfo();
+    $this->assertTrue(isset($theme_info['bartik']) && $theme_info['bartik']->status, 'Bartik theme enabled during import.');
+
+    // The configuration object system.theme will be saved twice during config
+    // import. Once during enabling the system and once during importing the
+    // new default setting.
+    $this->assertEqual(\Drupal::state()->get('ConfigImportUITest.system.theme.save', 0), 2, 'The system.theme configuration saved twice during import.');
+
+    // Verify that the action.settings configuration object was only written
+    // once during the import process and only with the value set in the staged
+    // configuration. This verifies that the module's default configuration is
+    // used during configuration import and, additionally, that after installing
+    // a module, that configuration is not synced twice.
+    $recursion_limit_values = \Drupal::state()->get('ConfigImportUITest.action.settings.recursion_limit', array());
+    $this->assertIdentical($recursion_limit_values, array(50));
+
+    $system_module = \Drupal::config('system.module')->get();
+    unset($system_module['enabled']['action']);
+    unset($system_module['enabled']['ban']);
+    $staging->write('system.module', $system_module);
+    $staging->delete('action.settings');
+
+    $system_theme = \Drupal::config('system.theme')->get();
+    unset($system_theme['enabled']['bartik']);
+    $system_theme['default'] = 'stark';
+    $system_theme['admin'] = 'stark';
+    $staging->write('system.theme', $system_theme);
+    $staging->write('system.theme.disabled', array('bartik' => 0));
+
+    // Reset counter.
+    \Drupal::state()->set('ConfigImportUITest.system.theme.save', 0);
+
+    // Verify that both appear as ready to import.
+    $this->drupalGet('admin/config/development/configuration');
+    $this->assertText('system.module');
+    $this->assertText('system.theme');
+    $this->assertText('system.theme.disabled');
+    $this->assertText('action.settings');
+
+    // Import and verify that both do not appear anymore.
+    $this->drupalPostForm(NULL, array(), t('Import all'));
+    $this->assertNoText('system.module');
+    $this->assertNoText('system.theme');
+    $this->assertNoText('system.theme.disabled');
+    $this->assertNoText('action.settings');
+
+    $this->rebuildContainer();
+    $this->assertFalse(\Drupal::moduleHandler()->moduleExists('ban'), 'Ban module uninstalled during import.');
+    $this->assertFalse(\Drupal::database()->schema()->tableExists('ban_ip'), 'The database table ban_ip does not exist.');
+    $this->assertFalse(\Drupal::moduleHandler()->moduleExists('action'), 'Action module uninstalled during import.');
+    // This is because it will be updated to change the default theme, remove
+    // Bartik and then set the admin theme.
+    $this->assertEqual(\Drupal::state()->get('ConfigImportUITest.system.theme.save', 0), 3, 'The system.theme configuration saved thrice during import.');
+
+    $theme_info = \Drupal::service('theme_handler')->listInfo();
+    $this->assertTrue(isset($theme_info['bartik']) && !$theme_info['bartik']->status, 'Bartik theme disabled during import.');
+
+    // Verify that the action.settings configuration object was only deleted
+    // once during the import process.
+    $delete_called = \Drupal::state()->get('ConfigImportUITest.action.settings.delete', 0);
+    $this->assertIdentical($delete_called, 1, "The action.settings configuration was deleted once during configuration import.");
   }
 
   /**
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
index ec445c5..2c40e02 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
@@ -61,9 +61,9 @@ function setUp() {
       $this->container->get('config.factory'),
       $this->container->get('entity.manager'),
       $this->container->get('lock'),
-      $this->container->get('uuid'),
       $this->container->get('config.typed'),
-      $this->container->get('module_handler')
+      $this->container->get('module_handler'),
+      $this->container->get('theme_handler')
     );
     $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
   }
diff --git a/core/modules/config/tests/config_import_test/config_import_test.info.yml b/core/modules/config/tests/config_import_test/config_import_test.info.yml
new file mode 100644
index 0000000..87cdd02
--- /dev/null
+++ b/core/modules/config/tests/config_import_test/config_import_test.info.yml
@@ -0,0 +1,6 @@
+name: 'Configuration import test'
+type: module
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
diff --git a/core/modules/config/tests/config_import_test/config_import_test.module b/core/modules/config/tests/config_import_test/config_import_test.module
new file mode 100644
index 0000000..936b72b
--- /dev/null
+++ b/core/modules/config/tests/config_import_test/config_import_test.module
@@ -0,0 +1,6 @@
+<?php
+
+/**
+ * @file
+ * Provides configuration import test helpers.
+ */
diff --git a/core/modules/config/tests/config_import_test/config_import_test.services.yml b/core/modules/config/tests/config_import_test/config_import_test.services.yml
new file mode 100644
index 0000000..997fd11
--- /dev/null
+++ b/core/modules/config/tests/config_import_test/config_import_test.services.yml
@@ -0,0 +1,6 @@
+services:
+  config_import_test.event_subscriber:
+    class: Drupal\config_import_test\EventSubscriber
+    tags:
+      - { name: event_subscriber }
+    arguments: ['@state']
\ No newline at end of file
diff --git a/core/modules/config/tests/config_import_test/lib/Drupal/config_import_test/EventSubscriber.php b/core/modules/config/tests/config_import_test/lib/Drupal/config_import_test/EventSubscriber.php
new file mode 100644
index 0000000..803189d
--- /dev/null
+++ b/core/modules/config/tests/config_import_test/lib/Drupal/config_import_test/EventSubscriber.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\config_import_test\EventSubscriber.
+ */
+
+namespace Drupal\config_import_test;
+
+use Drupal\Core\Config\ConfigEvent;
+use Drupal\Core\Config\ConfigImporterEvent;
+use Drupal\Core\KeyValueStore\StateInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+
+/**
+ * Config import subscriber for config import events.
+ */
+class EventSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The key value store.
+   *
+   * @var \Drupal\Core\KeyValueStore\StateInterface
+   */
+  protected $state;
+
+  /**
+   * Constructs the event subscriber.
+   *
+   * @param \Drupal\Core\KeyValueStore\StateInterface $state
+   *   The key value store.
+   */
+  public function __construct(StateInterface $state) {
+    $this->state = $state;
+  }
+
+  /**
+   * Validates the configuration to be imported.
+   *
+   * @param \Drupal\Core\Config\ConfigImporterEvent $event
+   *   The Event to process.
+   *
+   * @throws \Drupal\Core\Config\ConfigNameException
+   */
+  public function onConfigImporterValidate(ConfigImporterEvent $event) {
+
+  }
+
+  public function onConfigSave(ConfigEvent $event) {
+    $config = $event->getConfig();
+    if ($config->getName() == 'action.settings') {
+      $values = $this->state->get('ConfigImportUITest.action.settings.recursion_limit', array());
+      $values[] = $config->get('recursion_limit');
+      $this->state->set('ConfigImportUITest.action.settings.recursion_limit', $values);
+    }
+    if ($config->getName() == 'system.theme') {
+      $value = $this->state->get('ConfigImportUITest.system.theme.save', 0);
+      $this->state->set('ConfigImportUITest.system.theme.save', $value + 1);
+    }
+  }
+
+  public function onConfigDelete(ConfigEvent $event) {
+    $config = $event->getConfig();
+    if ($config->getName() == 'action.settings') {
+      $value = $this->state->get('ConfigImportUITest.action.settings.delete', 0);
+      $this->state->set('ConfigImportUITest.action.settings.delete', $value + 1);
+    }
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    //$events['config.importer.validate'][] = array('onConfigImporterValidate', 40);
+    //$events['config.installer.validate'][] = array('onConfigImporterValidate', 40);
+    $events['config.save'][] = array('onConfigSave', 40);
+    $events['config.delete'][] = array('onConfigDelete', 40);
+    return $events;
+  }
+
+}
\ No newline at end of file
diff --git a/core/modules/contact/contact.install b/core/modules/contact/contact.install
index c3802e7..1d72488 100644
--- a/core/modules/contact/contact.install
+++ b/core/modules/contact/contact.install
@@ -15,7 +15,13 @@ function contact_install() {
   if (empty($site_mail)) {
     $site_mail = ini_get('sendmail_from');
   }
-  \Drupal::config('contact.category.feedback')->set('recipients', array($site_mail))->save();
+  $config = \Drupal::config('contact.category.feedback');
+  // Update the recipients if the default configuration entity has been created.
+  // We should never rely on default config entities as during enabling a module
+  // during config sync they will not exist.
+  if (!$config->isNew()) {
+    \Drupal::config('contact.category.feedback')->set('recipients', array($site_mail))->save();
+  }
 }
 
 /**
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
index 5f98b85..73b65e2 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
@@ -711,4 +711,11 @@ public function getColumns() {
     return $this->field->getColumns();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function isDeleted() {
+    return $this->deleted;
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
index f5df93b..4c08510 100644
--- a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
@@ -40,4 +40,12 @@ public function allowBundleRename();
    */
   public function targetBundle();
 
+  /**
+   * Gets the deleted flag of the field instance.
+   *
+   * @return bool
+   *   Returns TRUE if the instance is deleted.
+   */
+  public function isDeleted();
+
 }
diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install
index 55539ae..a43da67 100644
--- a/core/modules/forum/forum.install
+++ b/core/modules/forum/forum.install
@@ -18,73 +18,75 @@ function forum_install() {
   $locked['forum'] = 'forum';
   \Drupal::state()->set('node.type.locked', $locked);
 
-  // Create the 'taxonomy_forums' field if it doesn't already exist. If forum
-  // is being enabled at the same time as taxonomy after both modules have been
-  // enabled, the field might exist but still be marked inactive.
-  if (!field_info_field('node', 'taxonomy_forums')) {
-    entity_create('field_entity', array(
-      'name' => 'taxonomy_forums',
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => 'forums',
-            'parent' => 0,
+  if (!\Drupal::service('config.installer')->isSyncing()) {
+    // Create the 'taxonomy_forums' field if it doesn't already exist. If forum
+    // is being enabled at the same time as taxonomy after both modules have been
+    // enabled, the field might exist but still be marked inactive.
+    if (!field_info_field('node', 'taxonomy_forums')) {
+      entity_create('field_entity', array(
+        'name' => 'taxonomy_forums',
+        'entity_type' => 'node',
+        'type' => 'taxonomy_term_reference',
+        'settings' => array(
+          'allowed_values' => array(
+            array(
+              'vocabulary' => 'forums',
+              'parent' => 0,
+            ),
           ),
         ),
-      ),
-    ))->save();
+      ))->save();
 
-    // Create a default forum so forum posts can be created.
-    $term = entity_create('taxonomy_term', array(
-      'name' => t('General discussion'),
-      'langcode' => language_default()->id,
-      'description' => '',
-      'parent' => array(0),
-      'vid' => 'forums',
-      'forum_container' => 0,
-    ));
-    $term->save();
+      // Create a default forum so forum posts can be created.
+      $term = entity_create('taxonomy_term', array(
+        'name' => t('General discussion'),
+        'langcode' => language_default()->id,
+        'description' => '',
+        'parent' => array(0),
+        'vid' => 'forums',
+        'forum_container' => 0,
+      ));
+      $term->save();
 
-    // Create the instance on the bundle.
-    entity_create('field_instance', array(
-      'field_name' => 'taxonomy_forums',
-      'entity_type' => 'node',
-      'label' => 'Forums',
-      'bundle' => 'forum',
-      'required' => TRUE,
-    ))->save();
+      // Create the instance on the bundle.
+      entity_create('field_instance', array(
+        'field_name' => 'taxonomy_forums',
+        'entity_type' => 'node',
+        'label' => 'Forums',
+        'bundle' => 'forum',
+        'required' => TRUE,
+      ))->save();
 
-    // Assign form display settings for the 'default' form mode.
-    entity_get_form_display('node', 'forum', 'default')
-      ->setComponent('taxonomy_forums', array(
-        'type' => 'options_select',
-      ))
-      ->save();
+      // Assign form display settings for the 'default' form mode.
+      entity_get_form_display('node', 'forum', 'default')
+        ->setComponent('taxonomy_forums', array(
+          'type' => 'options_select',
+        ))
+        ->save();
 
-    // Assign display settings for the 'default' and 'teaser' view modes.
-    entity_get_display('node', 'forum', 'default')
-      ->setComponent('taxonomy_forums', array(
-        'type' => 'taxonomy_term_reference_link',
-        'weight' => 10,
-      ))
-      ->save();
-    entity_get_display('node', 'forum', 'teaser')
-      ->setComponent('taxonomy_forums', array(
-        'type' => 'taxonomy_term_reference_link',
-        'weight' => 10,
-      ))
-      ->save();
-  }
-  // Add the comment field to the forum node type.
-  $fields = entity_load_multiple_by_properties('field_entity', array(
-    'type' => 'comment',
-    'name' => 'comment_forum',
-    'include_deleted' => FALSE,
-  ));
-  if (empty($fields)) {
-    Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'comment_forum', COMMENT_OPEN);
+      // Assign display settings for the 'default' and 'teaser' view modes.
+      entity_get_display('node', 'forum', 'default')
+        ->setComponent('taxonomy_forums', array(
+          'type' => 'taxonomy_term_reference_link',
+          'weight' => 10,
+        ))
+        ->save();
+      entity_get_display('node', 'forum', 'teaser')
+        ->setComponent('taxonomy_forums', array(
+          'type' => 'taxonomy_term_reference_link',
+          'weight' => 10,
+        ))
+        ->save();
+    }
+    // Add the comment field to the forum node type.
+    $fields = entity_load_multiple_by_properties('field_entity', array(
+      'type' => 'comment',
+      'name' => 'comment_forum',
+      'include_deleted' => FALSE,
+    ));
+    if (empty($fields)) {
+      Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'comment_forum', COMMENT_OPEN);
+    }
   }
 }
 
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index 91589a0..1e9d2ef 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -447,7 +447,9 @@ function node_uninstall() {
   $types = config_get_storage_names_with_prefix('node.type.');
   foreach ($types as $config_name) {
     $type = \Drupal::config($config_name)->get('type');
-    \Drupal::config('language.settings')->clear('node. ' . $type . '.language.default_configuration')->save();
+    if (\Drupal::moduleHandler()->moduleExists('language')) {
+      \Drupal::config('language.settings')->clear('node. ' . $type . '.language.default_configuration')->save();
+    }
   }
 
   // Delete remaining general module variables.
diff --git a/core/modules/search/lib/Drupal/search/SearchPageRepository.php b/core/modules/search/lib/Drupal/search/SearchPageRepository.php
index e2af5ff..5421586 100644
--- a/core/modules/search/lib/Drupal/search/SearchPageRepository.php
+++ b/core/modules/search/lib/Drupal/search/SearchPageRepository.php
@@ -87,7 +87,7 @@ public function getDefaultSearchPage() {
     }
 
     // Otherwise, use the first active search page.
-    return reset($search_pages);
+    return is_array($search_pages) ? reset($search_pages) : FALSE;
   }
 
   /**
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index 11a5e00..a98b990 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -147,11 +147,14 @@ function search_preprocess_block(&$variables) {
  * Implements hook_menu().
  */
 function search_menu() {
-  $items['search'] = array(
-    'title' => 'Search',
-    'type' => MENU_SUGGESTED_ITEM,
-    'route_name' => 'search.view',
-  );
+  // Create a default search page
+  if (\Drupal::service('search.search_page_repository')->getDefaultSearchPage()) {
+    $items['search'] = array(
+      'title' => 'Search',
+      'type' => MENU_SUGGESTED_ITEM,
+      'route_name' => 'search.view',
+    );
+  }
   $items['admin/config/search/settings'] = array(
     'title' => 'Search settings',
     'description' => 'Configure relevance settings for search and other indexing options.',
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index b9eb05a..3dc1768 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -1470,8 +1470,9 @@ public function configImporter() {
         $this->container->get('config.factory'),
         $this->container->get('entity.manager'),
         $this->container->get('lock'),
-        $this->container->get('uuid'),
-        $this->container->get('config.typed')
+        $this->container->get('config.typed'),
+        $this->container->get('module_handler'),
+        $this->container->get('theme_handler')
       );
     }
     // Always recalculate the changelist when called.
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index cc647a2..fe03ff8 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2642,7 +2642,6 @@ function _system_rebuild_module_data() {
     _system_rebuild_module_data_ensure_required($module, $modules);
   }
 
-
   if (isset($modules[$profile])) {
     // The installation profile is required, if it's a valid module.
     $modules[$profile]->info['required'] = TRUE;
