diff --git a/core/core.services.yml b/core/core.services.yml
index f3c6cd91d1c285ec1a18839304eee31aad7f85b5..baf6fe42a84437e43008f63d29fea727812700cd 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -74,16 +74,9 @@ services:
     factory_method: get
     factory_service: cache_factory
     arguments: [discovery]
-  config.cachedstorage.storage:
-    class: Drupal\Core\Config\FileStorage
-    factory_class: Drupal\Core\Config\FileStorageFactory
-    factory_method: getActive
   config.manager:
     class: Drupal\Core\Config\ConfigManager
     arguments: ['@entity.manager', '@config.factory', '@config.typed', '@string_translation', '@config.storage']
-  config.storage:
-    class: Drupal\Core\Config\CachedStorage
-    arguments: ['@config.cachedstorage.storage', '@cache.config']
   config.factory:
     class: Drupal\Core\Config\ConfigFactory
     tags:
@@ -92,6 +85,15 @@ services:
   config.installer:
     class: Drupal\Core\Config\ConfigInstaller
     arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher']
+  config.storage:
+    alias: config.storage.active
+  config.storage.active:
+    class: Drupal\Core\Config\DatabaseStorage
+    arguments: ['@database', 'config']
+  config.storage.file:
+    class: Drupal\Core\Config\FileStorage
+    factory_class: Drupal\Core\Config\FileStorageFactory
+    factory_method: getActive
   config.storage.staging:
     class: Drupal\Core\Config\FileStorage
     factory_class: Drupal\Core\Config\FileStorageFactory
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index f1cad478f80abba4eb187dbe28ba964075f809df..09c340aec8040e06a052f30dc6fb7be9aeee6285 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -438,7 +438,7 @@ function install_begin_request(&$install_state) {
   // Ensure that the active configuration directory is empty before installation
   // starts.
   if ($install_state['config_verified'] && empty($task)) {
-    $config = glob(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY) . '/*.' . FileStorage::getFileExtension());
+    $config = \Drupal::service('config.storage')->listAll();
     if (!empty($config)) {
       $task = NULL;
       throw new AlreadyInstalledException($container->get('string_translation'));
diff --git a/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php b/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php
index e075261e04d3ecfd46e3ffbdd6380a16eb7d3796..ffc8f48f03fefe37deb66f47a106aff8242c1250 100644
--- a/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php
+++ b/core/lib/Drupal/Core/Config/BootstrapConfigStorageFactory.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Config;
 
+use Drupal\Core\Database\Database;
 use Drupal\Component\Utility\Settings;
 
 /**
@@ -21,13 +22,29 @@ class BootstrapConfigStorageFactory {
    *   A configuration storage implementation.
    */
   public static function get() {
-    $drupal_bootstrap_config_storage = Settings::get('drupal_bootstrap_config_storage');
-    if ($drupal_bootstrap_config_storage && is_callable($drupal_bootstrap_config_storage)) {
-      return call_user_func($drupal_bootstrap_config_storage);
-    }
-    else {
-      return new FileStorage(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
+    $bootstrap_config_storage = Settings::get('bootstrap_config_storage');
+    if (!empty($bootstrap_config_storage) && is_callable($bootstrap_config_storage)) {
+      return call_user_func($bootstrap_config_storage);
     }
+    // Fallback to the DatabaseStorage.
+    return self::getDatabaseStorage();
+  }
+
+  /**
+   * Returns a Database configuration storage implementation.
+   *
+   * @return \Drupal\Core\Config\DatabaseStorage
+   */
+  public static function getDatabaseStorage() {
+    return new DatabaseStorage(Database::getConnection(), 'config');
   }
 
+  /**
+   * Returns a File-based configuration storage implementation.
+   *
+   * @return \Drupal\Core\Config\FileStorage
+   */
+  public static function getFileStorage() {
+    return new FileStorage(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
+  }
 }
diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php
index 7cbe2eba6ccfb1b1a18cc5d92fe9e71021bfacf7..76a5b333e8cc631758ad9e6c29343f462f26d4f9 100644
--- a/core/lib/Drupal/Core/Config/Config.php
+++ b/core/lib/Drupal/Core/Config/Config.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\Core\Config\Config.
+ * Contains \Drupal\Core\Config\Config.
  */
 
 namespace Drupal\Core\Config;
@@ -215,6 +215,11 @@ public function save() {
         $this->data[$key] = $this->castValue($key, $value);
       }
     }
+    else {
+      foreach ($this->data as $key => $value) {
+        $this->validateValue($key, $value);
+      }
+    }
 
     $this->storage->write($this->name, $this->data);
     $this->isNew = FALSE;
diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php
index e1e7faca8180050bb8ce4f76e8714da12753518e..11ab691230b2f0f74af41319aa85a189b361baed 100644
--- a/core/lib/Drupal/Core/Config/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php
@@ -2,13 +2,14 @@
 
 /**
  * @file
- * Definition of Drupal\Core\Config\DatabaseStorage.
+ * Contains \Drupal\Core\Config\DatabaseStorage.
  */
 
 namespace Drupal\Core\Config;
 
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\SchemaObjectExistsException;
 
 /**
  * Defines the Database storage.
@@ -56,24 +57,23 @@ public function __construct(Connection $connection, $table, array $options = arr
    * Implements Drupal\Core\Config\StorageInterface::exists().
    */
   public function exists($name) {
-    return (bool) $this->connection->queryRange('SELECT 1 FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name = :name', 0, 1, array(
-      ':name' => $name,
-    ), $this->options)->fetchField();
+    try {
+      return (bool) $this->connection->queryRange('SELECT 1 FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name = :name', 0, 1, array(
+        ':name' => $name,
+      ), $this->options)->fetchField();
+    }
+    catch (\Exception $e) {
+      // If we attempt a read without actually having the database or the table
+      // available, just return FALSE so the caller can handle it.
+      return FALSE;
+    }
   }
 
   /**
-   * Implements Drupal\Core\Config\StorageInterface::read().
-   *
-   * @throws PDOException
-   * @throws \Drupal\Core\Database\DatabaseExceptionWrapper
-   *   Only thrown in case $this->options['throw_exception'] is TRUE.
+   * {@inheritdoc}
    */
   public function read($name) {
     $data = FALSE;
-    // There are situations, like in the installer, where we may attempt a
-    // read without actually having the database available. In this case,
-    // catch the exception and just return an empty array so the caller can
-    // handle it if need be.
     try {
       $raw = $this->connection->query('SELECT data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name = :name', array(':name' => $name), $this->options)->fetchField();
       if ($raw !== FALSE) {
@@ -81,6 +81,8 @@ public function read($name) {
       }
     }
     catch (\Exception $e) {
+      // If we attempt a read without actually having the database or the table
+      // available, just return FALSE so the caller can handle it.
     }
     return $data;
   }
@@ -89,10 +91,6 @@ public function read($name) {
    * {@inheritdoc}
    */
   public function readMultiple(array $names) {
-    // There are situations, like in the installer, where we may attempt a
-    // read without actually having the database available. In this case,
-    // catch the exception and just return an empty array so the caller can
-    // handle it if need be.
     $list = array();
     try {
       $list = $this->connection->query('SELECT name, data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name IN (:names)', array(':names' => $names), $this->options)->fetchAllKeyed();
@@ -100,20 +98,42 @@ public function readMultiple(array $names) {
         $data = $this->decode($data);
       }
     }
-    catch (Exception $e) {
+    catch (\Exception $e) {
+      // If we attempt a read without actually having the database or the table
+      // available, just return an empty array so the caller can handle it.
     }
     return $list;
   }
 
   /**
-   * Implements Drupal\Core\Config\StorageInterface::write().
-   *
-   * @throws PDOException
-   *
-   * @todo Ignore slave targets for data manipulation operations.
+   * {@inheritdoc}
    */
   public function write($name, array $data) {
     $data = $this->encode($data);
+    try {
+      return $this->doWrite($name, $data);
+    }
+    catch (\Exception $e) {
+      // If there was an exception, try to create the table.
+      if ($this->ensureTableExists()) {
+        return $this->doWrite($name, $data);
+      }
+      // Some other failure that we can not recover from.
+      throw $e;
+    }
+  }
+
+  /**
+   * Helper method so we can re-try a write.
+   *
+   * @param string $name
+   *   The config name.
+   * @param string $data
+   *   The config data, already dumped to a string.
+   *
+   * @return bool
+   */
+  protected function doWrite($name, $data) {
     $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
     return (bool) $this->connection->merge($this->table, $options)
       ->key('name', $name)
@@ -121,6 +141,60 @@ public function write($name, array $data) {
       ->execute();
   }
 
+  /**
+   * Check if the config table exists and create it if not.
+   *
+   * @return bool
+   *   TRUE if the table was created, FALSE otherwise.
+   *
+   * @throws \Drupal\Core\Config\StorageException
+   *   If a database error occurs.
+   */
+  protected function ensureTableExists()  {
+    try {
+      if (!$this->connection->schema()->tableExists($this->table)) {
+        $this->connection->schema()->createTable($this->table, static::schemaDefinition());
+        return TRUE;
+      }
+    }
+    // If another process has already created the config table, attempting to
+    // recreate it will throw an exception. In this case just catch the
+    // exception and do nothing.
+    catch (SchemaObjectExistsException $e) {
+      return TRUE;
+    }
+    catch (\Exception $e) {
+      throw new StorageException($e->getMessage(), NULL, $e);
+    }
+    return FALSE;
+  }
+
+  /**
+   * Defines the schema for the configuration table.
+   */
+  protected static function schemaDefinition() {
+    $schema = array(
+      'description' => 'The base table for configuration data.',
+      'fields' => array(
+        'name' => array(
+          'description' => 'Primary Key: Unique config object name.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'data' => array(
+          'description' => 'A serialized configuration object data.',
+          'type' => 'blob',
+          'not null' => FALSE,
+          'size' => 'big',
+        ),
+      ),
+      'primary key' => array('name'),
+    );
+    return $schema;
+  }
+
   /**
    * Implements Drupal\Core\Config\StorageInterface::delete().
    *
@@ -168,29 +242,31 @@ public function decode($raw) {
   }
 
   /**
-   * Implements Drupal\Core\Config\StorageInterface::listAll().
-   *
-   * @throws PDOException
-   * @throws \Drupal\Core\Database\DatabaseExceptionWrapper
-   *   Only thrown in case $this->options['throw_exception'] is TRUE.
+   * {@inheritdoc}
    */
   public function listAll($prefix = '') {
-    return $this->connection->query('SELECT name FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name LIKE :name', array(
-      ':name' => db_like($prefix) . '%',
-    ), $this->options)->fetchCol();
+    try {
+      return $this->connection->query('SELECT name FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name LIKE :name', array(
+        ':name' => $this->connection->escapeLike($prefix) . '%',
+      ), $this->options)->fetchCol();
+    }
+    catch (\Exception $e) {
+      return array();
+    }
   }
 
   /**
-   * Implements Drupal\Core\Config\StorageInterface::deleteAll().
-   *
-   * @throws PDOException
-   * @throws \Drupal\Core\Database\DatabaseExceptionWrapper
-   *   Only thrown in case $this->options['throw_exception'] is TRUE.
+   * {@inheritdoc}
    */
   public function deleteAll($prefix = '') {
-    $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
-    return (bool) $this->connection->delete($this->table, $options)
-      ->condition('name', $prefix . '%', 'LIKE')
-      ->execute();
+    try {
+      $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
+      return (bool) $this->connection->delete($this->table, $options)
+        ->condition('name', $prefix . '%', 'LIKE')
+        ->execute();
+    }
+    catch (\Exception $e) {
+      return FALSE;
+    }
   }
 }
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index fbb997051a83b21989e45b65c0659f86e7d6a5b0..0b0466b9135ffc1044600d3b266a001d6af44270 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -68,6 +68,18 @@ public static function getFileExtension() {
     return 'yml';
   }
 
+  /**
+   * Check if the directory exists and create it if not.
+   */
+  protected function ensureStorage() {
+    $success = file_prepare_directory($this->directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    $success = $success && file_save_htaccess($this->directory, TRUE, TRUE);
+    if (!$success) {
+      throw new StorageException("Failed to create config directory {$this->directory}");
+    }
+    return $this;
+  }
+
   /**
    * Implements Drupal\Core\Config\StorageInterface::exists().
    */
@@ -105,21 +117,23 @@ public function readMultiple(array $names) {
   }
 
   /**
-   * Implements Drupal\Core\Config\StorageInterface::write().
-   *
-   * @throws \Drupal\Core\Config\UnsupportedDataTypeConfigException
-   * @throws \Drupal\Core\Config\StorageException
+   * {@inheritdoc}
    */
   public function write($name, array $data) {
     try {
       $data = $this->encode($data);
     }
     catch(DumpException $e) {
-      throw new UnsupportedDataTypeConfigException(String::format('Invalid data type for used in config: @name', array('@name' => $name)));
+      throw new StorageException(String::format('Invalid data type for used in config: @name', array('@name' => $name)));
     }
 
     $target = $this->getFilePath($name);
     $status = @file_put_contents($target, $data);
+    if ($status === FALSE) {
+      // Try to make sure the directory exists and try witing again.
+      $this->ensureStorage();
+      $status = @file_put_contents($target, $data);
+    }
     if ($status === FALSE) {
       throw new StorageException('Failed to write configuration file: ' . $this->getFilePath($name));
     }
@@ -213,7 +227,7 @@ public function listAll($prefix = '') {
     // glob() silently ignores the error of a non-existing search directory,
     // even with the GLOB_ERR flag.
     if (!file_exists($this->directory)) {
-      throw new StorageException($this->directory . '/ not found.');
+      return array();
     }
     $extension = '.' . static::getFileExtension();
     // \GlobIterator on Windows requires an absolute path.
diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php
index 8aa292bc7c8290ea2a1b2e3bb41f2bd7cd6ad3a6..18c0f07a11574520915fe03ad2ce6ad5dd568bb7 100644
--- a/core/lib/Drupal/Core/Config/StorableConfigBase.php
+++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php
@@ -131,6 +131,27 @@ protected function getSchemaWrapper() {
     return $this->schemaWrapper;
   }
 
+  /**
+   * Validate the values are allowed data types.
+   *
+   * @throws UnsupportedDataTypeConfigException
+   *   If there is any invalid value.
+   */
+  protected function validateValue($key, $value) {
+    // Minimal validation. Should not try to serialize resources or non-arrays.
+    if (is_array($value)) {
+      foreach ($value as $nested_value_key => $nested_value) {
+        $this->validateValue($key . '.' . $nested_value_key, $nested_value);
+      }
+    }
+    elseif ($value !== NULL && !is_scalar($value)) {
+      throw new UnsupportedDataTypeConfigException(String::format('Invalid data type for config element @name:@key', array(
+        '@name' => $this->getName(),
+        '@key' => $key,
+      )));
+    }
+  }
+
   /**
    * Casts the value to correct data type using the configuration schema.
    *
diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php
index 35cdf8aab9944789948b3e7da94ca41796385b94..8b997841ad2a2b6c71810ff7220cd710def796f2 100644
--- a/core/lib/Drupal/Core/Config/StorageInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageInterface.php
@@ -41,7 +41,7 @@ public function read($name);
   /**
    * Reads configuration data from the storage.
    *
-   * @param array $name
+   * @param array $names
    *   List of names of the configuration objects to load.
    *
    * @return array
@@ -60,6 +60,9 @@ public function readMultiple(array $names);
    *
    * @return bool
    *   TRUE on success, FALSE in case of an error.
+   *
+   * @throws \Drupal\Core\Config\StorageException
+   *   If the back-end storage does not exist and cannot be created.
    */
   public function write($name, array $data);
 
diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php b/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
index aa3c709bf687159aa15e3c22aa9fe7cab8348ad1..4239d64522d425074fe0b7e138450311f12d6f8a 100644
--- a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
+++ b/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
@@ -28,11 +28,11 @@ public function register(ContainerBuilder $container) {
       $container
         ->register('lock', 'Drupal\Core\Lock\NullLockBackend');
 
-      // Prevent config from accessing {cache_config}.
-      // @see $conf['cache_classes'], update_prepare_d8_bootstrap()
-      $container
-        ->register('config.storage', 'Drupal\Core\Config\FileStorage')
-        ->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
+      // Prevent config from being accessed via a cache wrapper by removing
+      // any existing definition and setting an alias to the actual storage.
+      $container->removeDefinition('config.storage');
+      $container->setAlias('config.storage', 'config.storage.active');
+
       $container->register('module_handler', 'Drupal\Core\Extension\UpdateModuleHandler')
         ->addArgument('%container.modules%');
       $container
diff --git a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php
index 18f628704014d894e29cac685ce0370970a1a266..c79b8cb4bd1a53f22a92c2a92e55fe4a90fc45f1 100644
--- a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php
+++ b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\system\FileDownloadController;
+use Symfony\Component\Yaml\Dumper;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -81,13 +82,15 @@ public function __construct(StorageInterface $target_storage, StorageInterface $
    * Downloads a tarball of the site configuration.
    */
   public function downloadExport() {
+    file_unmanaged_delete(file_directory_temp() . '/config.tar.gz');
+
+    $dumper = new Dumper();
+    $dumper->setIndentation(2);
+
     $archiver = new ArchiveTar(file_directory_temp() . '/config.tar.gz', 'gz');
-    $config_dir = config_get_config_directory();
-    $config_files = array();
-    foreach (\Drupal::service('config.storage')->listAll() as $config_name) {
-      $config_files[] = $config_dir . '/' . $config_name . '.yml';
+    foreach (\Drupal::service('config.storage')->listAll() as $name) {
+      $archiver->addString("$name.yml", $dumper->dump(\Drupal::config($name)->get(), PHP_INT_MAX, 0, TRUE));
     }
-    $archiver->createModify($config_files, '', config_get_config_directory());
 
     $request = new Request(array('file' => 'config.tar.gz'));
     return $this->fileDownloadController->download($request, 'temporary');
diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigSingleExportForm.php b/core/modules/config/lib/Drupal/config/Form/ConfigSingleExportForm.php
index 101dacbd069e89518cb454086f5504bb60e746f1..cdb76cc72eadbc6bcc471047ba1402a12ac667d1 100644
--- a/core/modules/config/lib/Drupal/config/Form/ConfigSingleExportForm.php
+++ b/core/modules/config/lib/Drupal/config/Form/ConfigSingleExportForm.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Form\FormBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Yaml\Dumper;
 
 /**
  * Provides a form for exporting a single configuration file.
@@ -32,6 +33,13 @@ class ConfigSingleExportForm extends FormBase {
    */
   protected $configStorage;
 
+  /**
+   * The YAML dumper.
+   *
+   * @var \Symfony\Component\Yaml\Dumper
+   */
+  protected $dumper;
+
   /**
    * Tracks the valid config entity type definitions.
    *
@@ -46,10 +54,14 @@ class ConfigSingleExportForm extends FormBase {
    *   The entity manager.
    * @param \Drupal\Core\Config\StorageInterface $config_storage
    *   The config storage.
+   * @param \Symfony\Component\Yaml\Dumper $dumper
+   *   The yaml dumper.
    */
-  public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage) {
+  public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage, Dumper $dumper) {
     $this->entityManager = $entity_manager;
     $this->configStorage = $config_storage;
+    $this->dumper = $dumper;
+    $this->dumper->setIndentation(2);
   }
 
   /**
@@ -58,7 +70,8 @@ public function __construct(EntityManagerInterface $entity_manager, StorageInter
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('entity.manager'),
-      $container->get('config.storage')
+      $container->get('config.storage'),
+      new Dumper()
     );
   }
 
@@ -151,8 +164,7 @@ public function updateExport($form, &$form_state) {
       $name = $form_state['values']['config_name'];
     }
     // Read the raw data for this config name, encode it, and display it.
-    $data = $this->configStorage->read($name);
-    $form['export']['#value'] = $this->configStorage->encode($data);
+    $form['export']['#value'] = $this->dumper->dump($this->configStorage->read($name), PHP_INT_MAX);
     $form['export']['#description'] = $this->t('The filename is %name.', array('%name' => $name . '.yml'));
     return $form['export'];
   }
diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigSingleImportForm.php b/core/modules/config/lib/Drupal/config/Form/ConfigSingleImportForm.php
index 129586271e19ad9c279034e1d85166ed7ddf63ed..e20afdeb478b0f5bbcb67229e103d08a762d5913 100644
--- a/core/modules/config/lib/Drupal/config/Form/ConfigSingleImportForm.php
+++ b/core/modules/config/lib/Drupal/config/Form/ConfigSingleImportForm.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Yaml\Yaml;
 
 /**
  * Provides a form for importing a single configuration file.
@@ -31,6 +32,13 @@ class ConfigSingleImportForm extends ConfirmFormBase {
    */
   protected $configStorage;
 
+  /**
+   * The YAML component.
+   *
+   * @var \Symfony\Component\Yaml\Yaml
+   */
+  protected $yaml;
+
   /**
    * If the config exists, this is that object. Otherwise, FALSE.
    *
@@ -52,10 +60,13 @@ class ConfigSingleImportForm extends ConfirmFormBase {
    *   The entity manager.
    * @param \Drupal\Core\Config\StorageInterface $config_storage
    *   The config storage.
+   * @param \Symfony\Component\Yaml\Yaml $yaml
+   *   The YAML component.
    */
-  public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage) {
+  public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage, Yaml $yaml) {
     $this->entityManager = $entity_manager;
     $this->configStorage = $config_storage;
+    $this->yaml = $yaml;
   }
 
   /**
@@ -64,7 +75,8 @@ public function __construct(EntityManagerInterface $entity_manager, StorageInter
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('entity.manager'),
-      $container->get('config.storage')
+      $container->get('config.storage'),
+      new Yaml()
     );
   }
 
@@ -184,7 +196,7 @@ public function validateForm(array &$form, array &$form_state) {
     }
 
     // Decode the submitted import.
-    $data = $this->configStorage->decode($form_state['values']['import']);
+    $data = $this->yaml->parse($form_state['values']['import']);
 
     // Validate for config entities.
     if ($form_state['values']['config_type'] !== 'system.simple') {
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
index 7576163c395a4c98ec7f1708f823b0f333d7fdf4..f10a1202a94733f41e6f258f46552b6edcda7163 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Config\ConfigNameException;
 use Drupal\simpletest\DrupalUnitTestBase;
 use Drupal\Core\Config\FileStorage;
+use Drupal\Core\Config\DatabaseStorage;
 use Drupal\Core\Config\UnsupportedDataTypeConfigException;
 
 /**
@@ -192,10 +193,10 @@ function testNameValidation() {
    */
   public function testDataTypes() {
     \Drupal::moduleHandler()->install(array('config_test'));
-    $storage = new FileStorage($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]);
+    $storage = new DatabaseStorage($this->container->get('database'), 'config');
     $name = 'config_test.types';
     $config = $this->container->get('config.factory')->get($name);
-    $original_content = file_get_contents($storage->getFilePath($name));
+    $original_content = file_get_contents(drupal_get_path('module', 'config_test') . "/config/$name.yml");
     $this->verbose('<pre>' . $original_content . "\n" . var_export($storage->read($name), TRUE));
 
     // Verify variable data types are intact.
@@ -220,7 +221,7 @@ public function testDataTypes() {
     $this->assertIdentical($config->get(), $data);
     // Assert the data against the file storage.
     $this->assertIdentical($storage->read($name), $data);
-    $this->verbose('<pre>' . file_get_contents($storage->getFilePath($name)) . var_export($storage->read($name), TRUE));
+    $this->verbose('<pre>' . $name . var_export($storage->read($name), TRUE));
 
     // Set data using config::setData().
     $config->setData($data)->save();
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigSingleImportExportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigSingleImportExportTest.php
index 46a14d472dc40faf4341a32a9155613b86722b9d..b131d8ade145c816db96b3b65824997735b9e182 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigSingleImportExportTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigSingleImportExportTest.php
@@ -8,7 +8,7 @@
 namespace Drupal\config\Tests;
 
 use Drupal\simpletest\WebTestBase;
-use Symfony\Component\Yaml\Yaml;
+use Symfony\Component\Yaml\Dumper;
 
 /**
  * Tests the user interface for importing/exporting a single configuration.
@@ -22,6 +22,13 @@ class ConfigSingleImportExportTest extends WebTestBase {
    */
   public static $modules = array('config', 'config_test');
 
+  /**
+   * The YAML dumper.
+   *
+   * @var \Symfony\Component\Yaml\Dumper
+   */
+  protected $dumper;
+
   public static function getInfo() {
     return array(
       'name' => 'Configuration Single Import/Export UI',
@@ -30,6 +37,15 @@ public static function getInfo() {
     );
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->dumper = new Dumper();
+    $this->dumper->setIndentation(2);
+  }
+
   /**
    * Tests importing a single configuration file.
    */
@@ -111,12 +127,11 @@ public function testImport() {
    */
   public function testImportSimpleConfiguration() {
     $this->drupalLogin($this->drupalCreateUser(array('import configuration')));
-    $yaml = new Yaml();
     $config = \Drupal::config('system.site')->set('name', 'Test simple import');
     $edit = array(
       'config_type' => 'system.simple',
       'config_name' => $config->getName(),
-      'import' => $yaml->dump($config->get()),
+      'import' => $this->dumper->dump($config->get(), PHP_INT_MAX),
     );
     $this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import'));
     $this->assertRaw(t('Are you sure you want to update the %name @type?', array('%name' => $config->getName(), '@type' => 'simple configuration')));
@@ -152,7 +167,7 @@ public function testExport() {
     $this->assertFieldByXPath('//select[@name="config_name"]//option[@selected="selected"]', t('Fallback date format'), 'The fallback date format config entity is selected when specified in the URL.');
 
     $fallback_date = \Drupal::entityManager()->getStorage('date_format')->load('fallback');
-    $data = \Drupal::service('config.storage')->encode($fallback_date->toArray());
+    $data = $this->dumper->dump($fallback_date->toArray(), PHP_INT_MAX);
     $this->assertFieldByXPath('//textarea[@name="export"]', $data, 'The fallback date format config entity export code is displayed.');
   }
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
index 140b50a009c20f59d913dacdd484d8fa65479591..cef916b25503d13a09f53e236b3bc85747cdc5e7 100644
--- a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
@@ -95,6 +95,10 @@ function testCRUD() {
     $result = $this->invalidStorage->read($name);
     $this->assertIdentical($result, FALSE);
 
+    // Listing on a non-existing storage bin returns an empty array.
+    $result = $this->invalidStorage->listAll();
+    $this->assertIdentical($result, array());
+
     // Deleting all names with prefix deletes the appropriate data and returns
     // TRUE.
     $files = array(
@@ -111,15 +115,6 @@ function testCRUD() {
     $this->assertIdentical($result, TRUE);
     $this->assertIdentical($names, array());
 
-    // Writing to a non-existing storage bin throws an exception.
-    try {
-      $this->invalidStorage->write($name, array('foo' => 'bar'));
-      $this->fail('Exception not thrown upon writing to a non-existing storage bin.');
-    }
-    catch (\Exception $e) {
-      $class = get_class($e);
-      $this->pass($class . ' thrown upon writing to a non-existing storage bin.');
-    }
 
     // Deleting from a non-existing storage bin throws an exception.
     try {
@@ -131,16 +126,6 @@ function testCRUD() {
       $this->pass($class . ' thrown upon deleting from a non-existing storage bin.');
     }
 
-    // Listing on a non-existing storage bin throws an exception.
-    try {
-      $this->invalidStorage->listAll();
-      $this->fail('Exception not thrown upon listing from a non-existing storage bin.');
-    }
-    catch (\Exception $e) {
-      $class = get_class($e);
-      $this->pass($class . ' thrown upon listing from a non-existing storage bin.');
-    }
-
     // Test renaming an object that does not exist throws an exception.
     try {
       $this->storage->rename('config_test.storage_does_not_exist', 'config_test.storage_does_not_exist_rename');
@@ -159,6 +144,10 @@ function testCRUD() {
       $this->pass($class . ' thrown upon renaming a nonexistent storage bin.');
     }
 
+    // Writing to a non-existing storage bin creates the bin.
+    $this->invalidStorage->write($name, array('foo' => 'bar'));
+    $result = $this->invalidStorage->read($name);
+    $this->assertIdentical($result, array('foo' => 'bar'));
   }
 
   /**
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/DatabaseStorageTest.php b/core/modules/config/lib/Drupal/config/Tests/Storage/DatabaseStorageTest.php
index 66cdb995d7d76c380c5ec1d3ca2594103cf11520..7dbf17bb461ac7bc156b715e13a67358c0190af6 100644
--- a/core/modules/config/lib/Drupal/config/Tests/Storage/DatabaseStorageTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/DatabaseStorageTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\config\Tests\Storage\DatabaseStorageTest.
+ * Contains \Drupal\config\Tests\Storage\DatabaseStorageTest.
  */
 
 namespace Drupal\config\Tests\Storage;
@@ -24,28 +24,6 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $schema['config'] = array(
-      'description' => 'Database storage for the configuration system.',
-      'fields' => array(
-        'name' => array(
-          'description' => 'The identifier for the configuration entry, such as module.example (the name of the file, minus the file extension).',
-          'type' => 'varchar',
-          'length' => 255,
-          'not null' => TRUE,
-          'default' => '',
-        ),
-        'data' => array(
-          'description' => 'The raw data for this configuration entry.',
-          'type' => 'blob',
-          'not null' => TRUE,
-          'size' => 'big',
-          'translatable' => TRUE,
-        ),
-      ),
-      'primary key' => array('name'),
-    );
-    db_create_table('config', $schema['config']);
-
     $this->storage = new DatabaseStorage($this->container->get('database'), 'config');
     $this->invalidStorage = new DatabaseStorage($this->container->get('database'), 'invalid');
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php b/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php
index dd6c4009d12254982eb92978967cbc121ca9665e..96bdb428f4b0400b26d1ab6b312c150081e21985 100644
--- a/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php
@@ -29,6 +29,7 @@ function setUp() {
 
     // FileStorage::listAll() requires other configuration data to exist.
     $this->storage->write('system.performance', \Drupal::config('system.performance')->get());
+    $this->storage->write('core.extension', array('module' => array()));
   }
 
   protected function read($name) {
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php
index 405aaf568b9dcd729cf416db689565b69325a909..cb07cd4227b8f21909ae7a5158da156016624e29 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php
@@ -368,7 +368,6 @@ public function testContactConfigEntityTranslation() {
    */
   public function testDateFormatTranslation() {
     $this->drupalLogin($this->admin_user);
-    $file_storage = new FileStorage($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]);
 
     $this->drupalGet('admin/config/regional/date-time');
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
index 75e3f781a0028f817bbb18d6cdb9af0af897ced7..3d35566419acf5af840e7b6366e9c8fd307a7c6c 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
@@ -229,8 +229,9 @@ public function containerBuild(ContainerBuilder $container) {
     $container->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory');
 
     $container
-      ->register('config.storage', 'Drupal\Core\Config\FileStorage')
-      ->addArgument($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]);
+      ->register('config.storage.active', 'Drupal\Core\Config\DatabaseStorage')
+      ->addArgument(Database::getConnection())
+      ->addArgument('config');
 
     $this->settingsSet('keyvalue_default', 'keyvalue.memory');
     $container->set('keyvalue.memory', $this->keyValueFactory);
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 3eac57467a4712b7b19f04f842b666eeb6908465..b2ce930eff03beac67c0642f521c6adc064c4178 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -600,6 +600,19 @@
  */
 # $cookie_domain = '.example.com';
 
+/**
+ * Active configuration settings.
+ *
+ * By default, the active configuration is stored in the database in the
+ * {config} table. To install Drupal with a different active configuration
+ * storage, you need to override the setting here, in addition to overriding
+ * the config.storage.active service definition in a module or profile.
+ *
+ * The 'bootstrap_config_storage' setting needs to be a callable that returns
+ * core.services.yml.
+ */
+ # $settings['bootstrap_config_storage'] = array('Drupal\Core\Config\BootstrapConfigStorageFactory', 'getFileStorage');
+
 /**
  * Configuration overrides.
  *