diff --git a/.htaccess b/.htaccess
index a69bdd4..398f960 100644
--- a/.htaccess
+++ b/.htaccess
@@ -3,7 +3,7 @@
 #
 
 # Protect files and directories from prying eyes.
-<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$">
+<FilesMatch "\.(sig|xml|engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$">
   Order allow,deny
 </FilesMatch>
 
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 35c9e0c..e14af3b 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -236,6 +236,9 @@ const REGISTRY_WRITE_LOOKUP_CACHE = 2;
  */
 const DRUPAL_PHP_FUNCTION_PATTERN = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';
 
+// Will go away when we've converted to PSR-0
+require_once DRUPAL_ROOT . '/core/includes/config.inc';
+
 /**
  * Provides a caching wrapper to be used in place of large array structures.
  *
@@ -767,7 +770,7 @@ function drupal_settings_initialize() {
   global $base_url, $base_path, $base_root;
 
   // Export the following settings.php variables to the global namespace
-  global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url;
+  global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $drupal_config_directory_name, $drupal_config_key;
   $conf = array();
 
   if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
@@ -1343,8 +1346,10 @@ function drupal_page_header() {
  * response is sent.
  */
 function drupal_serve_page_from_cache(stdClass $cache) {
+  $config = config('system.performance');
+
   // Negotiate whether to use compression.
-  $page_compression = variable_get('page_compression', TRUE) && extension_loaded('zlib');
+  $page_compression = $config->get('page_compression') && extension_loaded('zlib');
   $return_compressed = $page_compression && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE;
 
   // Get headers set in hook_boot(). Keys are lower-case.
@@ -1370,7 +1375,7 @@ function drupal_serve_page_from_cache(stdClass $cache) {
   // max-age > 0, allowing the page to be cached by external proxies, when a
   // session cookie is present unless the Vary header has been replaced or
   // unset in hook_boot().
-  $max_age = !isset($_COOKIE[session_name()]) || isset($hook_boot_headers['vary']) ? variable_get('page_cache_maximum_age', 0) : 0;
+  $max_age = !isset($_COOKIE[session_name()]) || isset($hook_boot_headers['vary']) ? $config->get('page_cache_maximum_age') : 0;
   $default_headers['Cache-Control'] = 'public, max-age=' . $max_age;
 
   // Entity tag should change if the output changes.
@@ -2341,7 +2346,8 @@ function _drupal_bootstrap_page_cache() {
   }
   else {
     drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES, FALSE);
-    $cache_enabled = variable_get('cache');
+    $config = config('system.performance');
+    $cache_enabled = $config->get('cache');
   }
   drupal_block_denied(ip_address());
   // If there is no session cookie and cache is enabled (or forced), try
diff --git a/core/includes/cache.inc b/core/includes/cache.inc
index e8c7477..301dd35 100644
--- a/core/includes/cache.inc
+++ b/core/includes/cache.inc
@@ -362,7 +362,8 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
     // timer. The cache variable is loaded into the $user object by
     // _drupal_session_read() in session.inc. If the data is permanent or we're
     // not enforcing a minimum cache lifetime always return the cached data.
-    if ($cache->expire != CACHE_PERMANENT && variable_get('cache_lifetime', 0) && $user->cache > $cache->created) {
+    $config = config('system.performance');
+    if ($cache->expire != CACHE_PERMANENT && $config->get('cache_lifetime') && $user->cache > $cache->created) {
       // This cache data is too old and thus not valid for us, ignore it.
       return FALSE;
     }
diff --git a/core/includes/common.inc b/core/includes/common.inc
index c117d43..6e3a677 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2566,7 +2566,8 @@ function drupal_page_footer() {
   // Commit the user session, if needed.
   drupal_session_commit();
 
-  if (variable_get('cache', 0) && ($cache = drupal_page_set_cache())) {
+  $config = config('system.performance');
+  if ($config->get('cache') && ($cache = drupal_page_set_cache())) {
     drupal_serve_page_from_cache($cache);
   }
   else {
@@ -3134,7 +3135,14 @@ function drupal_group_css($css) {
  * @see system_element_info()
  */
 function drupal_aggregate_css(&$css_groups) {
-  $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
+  // Only aggregate during normal site operation.
+  if (defined('MAINTENANCE_MODE')) {
+    $preprocess_css = FALSE;
+  }
+  else {
+    $config = config('system.performance');
+    $preprocess_css = $config->get('preprocess_css');
+  }
 
   // For each group that needs aggregation, aggregate its items.
   foreach ($css_groups as $key => $group) {
@@ -4367,9 +4375,18 @@ function drupal_group_js($javascript) {
  * @see drupal_pre_render_scripts()
  */
 function drupal_aggregate_js(&$js_groups) {
+  // Only aggregate during normal site operation.
+  if (defined('MAINTENANCE_MODE')) {
+    $preprocess_js = FALSE;
+  }
+  else {
+    $config = config('system.performance');
+    $preprocess_js = $config->get('preprocess_js');
+  }
+
   // Only aggregate when the site is configured to do so, and not during an
   // update.
-  if (variable_get('preprocess_js', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update')) {
+  if ($preprocess_js) {
     foreach ($js_groups as $key => $group) {
       if ($group['type'] == 'file' && $group['preprocess']) {
         $js_groups[$key]['data'] = drupal_build_js_cache($group['items']);
@@ -5118,6 +5135,7 @@ function _drupal_bootstrap_full() {
  */
 function drupal_page_set_cache() {
   global $base_root;
+  $config = config('system.performance');
 
   if (drupal_page_is_cacheable()) {
     $cache = (object) array(
@@ -5144,7 +5162,7 @@ function drupal_page_set_cache() {
     }
 
     if ($cache->data['body']) {
-      if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
+      if ($config->get('page_compression') && extension_loaded('zlib')) {
         $cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
       }
       cache('page')->set($cache->cid, $cache->data, $cache->expire);
@@ -6516,6 +6534,69 @@ function drupal_array_set_nested_value(array &$array, array $parents, $value, $f
 }
 
 /**
+ * Unsets a value in a nested array with variable depth.
+ *
+ * This helper function should be used when the depth of the array element you
+ * are changing may vary (that is, the number of parent keys is variable). It
+ * is primarily used for form structures and renderable arrays.
+ *
+ * Example:
+ * @code
+ * // Assume you have a 'signature' element somewhere in a form. It might be:
+ * $form['signature_settings']['signature'] = array(
+ *   '#type' => 'text_format',
+ *   '#title' => t('Signature'),
+ * );
+ * // Or, it might be further nested:
+ * $form['signature_settings']['user']['signature'] = array(
+ *   '#type' => 'text_format',
+ *   '#title' => t('Signature'),
+ * );
+ * @endcode
+ *
+ * To deal with the situation, the code needs to figure out the route to the
+ * element, given an array of parents that is either
+ * @code array('signature_settings', 'signature') @endcode in the first case or
+ * @code array('signature_settings', 'user', 'signature') @endcode in the second
+ * case.
+ *
+ * Without this helper function the only way to unset the signature element in
+ * one line would be using eval(), which should be avoided:
+ * @code
+ * // Do not do this! Avoid eval().
+ * eval('unset($form[\'' . implode("']['", $parents) . '\']);');
+ * @endcode
+ *
+ * Instead, use this helper function:
+ * @code
+ * drupal_array_unset_nested_value($form, $parents, $element);
+ * @endcode
+ *
+ * However if the number of array parent keys is static, the value should always
+ * be set directly rather than calling this function. For instance, for the
+ * first example we could just do:
+ * @code
+ * unset($form['signature_settings']['signature']);
+ * @endcode
+ *
+ * @param $array
+ *   A reference to the array to modify.
+ * @param $parents
+ *   An array of parent keys, starting with the outermost key and including the
+ *   key to be unset.
+ *
+ * @see drupal_array_set_nested_value()
+ */
+function drupal_array_unset_nested_value(array &$array, array $parents) {
+  $ref = &$array;
+  $unset_key = array_pop($parents);
+  foreach ($parents as $parent) {
+    $ref = &$ref[$parent];
+  }
+  unset($ref[$unset_key]);
+}
+
+/**
  * Retrieves a value from a nested array with variable depth.
  *
  * This helper function should be used when the depth of the array element being
diff --git a/core/includes/config.inc b/core/includes/config.inc
new file mode 100644
index 0000000..14047ea
--- /dev/null
+++ b/core/includes/config.inc
@@ -0,0 +1,718 @@
+<?php
+
+/**
+ * @file
+ * This is the API for configuration storage.
+ */
+
+/**
+ * Gets the randomly generated config directory name.
+ *
+ * @return
+ *   The directory name.
+ */
+function config_get_config_directory() {
+  global $drupal_config_directory_name;
+
+  return conf_path() . '/files/' . $drupal_config_directory_name;
+}
+
+/**
+ * Moves the default config supplied by a module to the live config directory.
+ *
+ * @param
+ *   The name of the module we are installing.
+ */
+function config_install_default_config($module) {
+  $module_config_dir = drupal_get_path('module', $module) . '/config';
+  $drupal_config_dir = config_get_config_directory();
+  if (is_dir(drupal_get_path('module', $module) . '/config')) {
+    $files = glob($module_config_dir . '/' . '*.xml');
+    foreach ($files as $key => $file) {
+      // Load config data into the active store and write it out to the
+      // file system in the drupal config directory. Note the config name
+      // needs to be the same as the file name WITHOUT the extension.
+      // @todo Make this acknowledge other storage engines rather than having
+      //   SQL be hardcoded.
+      $parts = explode('/', $file);
+      $file = array_pop($parts);
+      $config_name = str_replace('.xml', '', $file);
+
+      $verified_storage = new DrupalVerifiedStorageSQL($config_name);
+      $verified_storage->write(file_get_contents($module_config_dir . '/' . $file));
+    }
+  }
+}
+
+/**
+ * Retrieves an iterable array which lists the children under a config 'branch'.
+ *
+ * Given the following configuration files:
+ * - core.entity.node_type.article.xml
+ * - core.entity.node_type.page.xml
+ *
+ * You can pass a prefix 'core.entity.node_type' and get back an array of the
+ * filenames that match. This allows you to iterate through all files in a
+ * branch. Note that this will only work on the level above the tips, so
+ * a prefix of 'core.entity' would return an empty array.
+ *
+ * @param $prefix
+ *   The prefix of the files we are searching for.
+ *
+ * @return
+ *   An array of file names under a branch.
+ */
+function config_get_signed_file_storage_names_with_prefix($prefix = '') {
+  $files = glob(config_get_config_directory() . '/' . $prefix . '*.xml');
+  $clean_name = function ($value) {
+    return basename($value, '.xml');
+  };
+  return array_map($clean_name, $files);
+}
+
+/**
+ * Generates a hash of a config file's contents using our encryption key.
+ *
+ * @param $data
+ *   The contents of a configuration file.
+ *
+ * @return
+ *   A hash of the data.
+ */
+function config_sign_data($data) {
+  // The configuration key is loaded from settings.php and imported into the global namespace
+  global $drupal_config_key;
+
+  // SHA-512 is both secure and very fast on 64 bit CPUs.
+  // @todo What about 32-bit CPUs?
+  return hash_hmac('sha512', $data, $drupal_config_key);
+}
+
+/**
+ * @todo
+ *
+ * @param $prefix
+ *   @todo
+ *
+ * @return
+ *   @todo
+ */
+function config_get_verified_storage_names_with_prefix($prefix = '') {
+  return DrupalVerifiedStorageSQL::getNamesWithPrefix($prefix);
+}
+
+/**
+ * @todo
+ *
+ * @param $prefix
+ *   @todo
+ *
+ * @return
+ *   @todo
+ */
+function config_get_names_with_prefix($prefix) {
+  return config_get_verified_storage_names_with_prefix($prefix);
+}
+
+/**
+ * Retrieves a configuration object.
+ *
+ * This is the main entry point to the configuration API. Calling
+ * @code config(book.admin) @endcode will return a configuration object in which
+ * the book module can store its administrative settings.
+ *
+ * @param $name
+ *   The name of the configuration object to retrieve. The name corresponds to
+ *   an XML configuration file. For @code config(book.admin) @endcode, the
+ *   config object returned will contain the contents of book.admin.xml.
+ * @param $class
+ *   The class name of the config object to be returned. Defaults to
+ *   DrupalConfig.
+ *
+ * @return
+ *   An instance of the class specified in the $class parameter.
+ *
+ */
+function config($name, $class = 'DrupalConfig') {
+  // @todo Replace this with an appropriate factory.
+  return new $class(new DrupalVerifiedStorageSQL($name));
+}
+
+/**
+ * Decodes configuration data from its native format to an associative array.
+ *
+ * @param $data
+ *   Configuration data.
+ *
+ * @return
+ *   An associative array representation of the data.
+ */
+function config_decode($data) {
+  if (empty($data)) {
+    return array();
+  }
+  $xml = new SimpleXMLElement($data);
+  $json = json_encode($xml);
+  return json_decode($json, TRUE);
+}
+
+/**
+ * Standardizes SimpleXML object output into simple arrays for easier use.
+ *
+ * @param $xmlObject
+ *   A valid XML string.
+ *
+ * @return
+ *   An array representation of A SimpleXML object.
+ */
+function config_xml_to_array($data) {
+  $out = array();
+  $xmlObject = simplexml_load_string($data);
+
+  if (is_object($xmlObject)) {
+    $attributes = (array) $xmlObject->attributes();
+    if (isset($attributes['@attributes'])) {
+      $out['#attributes'] = $attributes['@attributes'];
+    }
+  }
+  if (trim((string) $xmlObject)) {
+    return trim((string) $xmlObject);
+  }
+  foreach ($xmlObject as $index => $content) {
+    if (is_object($content)) {
+      $out[$index] = config_xml2array($content);
+    }
+  }
+
+  return $out;
+}
+
+/**
+ * Encodes an array into the native configuration format.
+ *
+ * @param $data
+ *   An associative array or an object
+ *
+ * @return
+ *   A representation of this array or object in the native configuration
+ *   format.
+ *
+ * @todo This needs to work for objects as well and currently doesn't.
+ */
+function config_encode($data) {
+  // creating object of SimpleXMLElement
+  $xml_object = new SimpleXMLElement("<?xml version=\"1.0\"?><config></config>");
+
+  // function call to convert array to xml
+  config_array_to_xml($data, $xml_object);
+
+  // Pretty print the result
+  $dom = new DOMDocument('1.0');
+  $dom->preserveWhiteSpace = false;
+  $dom->formatOutput = true;
+  $dom->loadXML($xml_object->asXML());
+  return $dom->saveXML();
+}
+
+/**
+ * Encodes an array into XML
+ *
+ * @param $data
+ *   An associative array or an object
+ *
+ * @return
+ *   A representation of this array or object in the native configuration
+ *   format.
+ *
+ * @todo This needs to work for objects as well and currently doesn't.
+ */
+function config_array_to_xml($array, &$xml_object) {
+  foreach ($array as $key => $value) {
+    if (is_array($value)) {
+      if (!is_numeric($key)){
+        $subnode = $xml_object->addChild("$key");
+        config_array_to_xml($value, $subnode);
+      }
+      else {
+        config_array_to_xml($value, $xml_object);
+      }
+    }
+    else {
+      $xml_object->addChild("$key", "$value");
+    }
+  }
+}
+
+/**
+ * @todo
+ */
+class ConfigException extends Exception {}
+
+/**
+ * @todo
+ */
+class ConfigFileStorageException extends ConfigException {}
+
+/**
+ * @todo
+ */
+class ConfigFileStorageReadException extends ConfigFileStorageException {}
+
+/**
+ * @todo
+ */
+class ConfigFileStorageSignatureException extends ConfigFileStorageException {}
+
+/**
+ * Represents the signed file storage interface.
+ *
+ * Classes implementing this interface allow reading and writing configuration
+ * data to and from disk, while automatically managing and verifying
+ * cryptographic signatures.
+ */
+class SignedFileStorage {
+
+  /**
+   * Constructs a SignedFileStorage object.
+   *
+   * @param string $name
+   *   The name for the configuration data. Should be lowercase.
+   */
+  public function __construct($name) {
+    $this->name = $name;
+  }
+
+  /**
+   * Reads and returns a signed file and its signature.
+   *
+   * @return
+   *   An array with "signature" and "data" keys.
+   *
+   * @throws
+   *   Exception
+   */
+  protected function readWithSignature() {
+    // @todo Optimize with explicit offsets?
+    $content = file_get_contents($this->getFilePath());
+    if ($content === FALSE) {
+      throw new Exception('Read file is invalid.');
+    }
+    $signature = file_get_contents($this->getFilePath() . '.sig');
+    if ($signature === FALSE) {
+      throw new Exception('Signature file is invalid.');
+    }
+    return array('data' => $content, 'signature' => $signature);
+  }
+
+  /**
+   * Checks whether the XML configuration file already exists on disk.
+   *
+   * @return
+   *   @todo
+   */
+  protected function exists() {
+    return file_exists($this->getFilePath());
+  }
+
+  /**
+   * Returns the path to the XML configuration file.
+   *
+   * @return
+   *   @todo
+   */
+  public function getFilePath() {
+    return config_get_config_directory() . '/' . $this->name  . '.xml';
+  }
+
+  /**
+   * Recreates the signature for the file.
+   */
+  public function resign() {
+    if ($this->exists()) {
+      $parts = $this->readWithSignature();
+      $this->write($parts['data']);
+    }
+  }
+
+  /**
+   * Cryptographically verifies the integrity of the configuration file.
+   *
+   * @param $contentOnSuccess
+   *   Whether or not to return the contents of the verified configuration file.
+   *
+   * @return mixed
+   *   If $contentOnSuccess was TRUE, returns the contents of the verified
+   *   configuration file; otherwise returns TRUE on success. Always returns
+   *   FALSE if the configuration file was not successfully verified.
+   */
+  public function verify($contentOnSuccess = FALSE) {
+    if ($this->exists()) {
+      $split = $this->readWithSignature();
+      $expected_signature = config_sign_data($split['data']);
+      if ($expected_signature === $split['signature']) {
+        if ($contentOnSuccess) {
+          return $split['data'];
+        }
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+
+  /**
+   * Writes the contents of the configuration file to disk.
+   *
+   * @param $data
+   *   The data to be written to the file.
+   *
+   * @throws
+   *   Exception
+   *
+   * @todo What format is $data in?
+   */
+  public function write($data) {
+    $signature = config_sign_data($data);
+    if (!file_put_contents($this->getFilePath(), $data)) {
+      throw new Exception('Failed to write configuration file.');
+    }
+    if (!file_put_contents($this->getFilePath() . '.sig', $signature)) {
+      throw new Exception('Failed to write signature file.');
+    }
+  }
+
+  /**
+   * Returns the contents of the configuration file.
+   *
+   * @return
+   *   @todo
+   */
+  public function read() {
+    if ($this->exists()) {
+      $verification = $this->verify(TRUE);
+      if ($verification === FALSE) {
+        throw new Exception('Invalid signature in file header.');
+      }
+      return $verification;
+    }
+  }
+
+  /**
+   * Deletes a configuration file.
+   */
+  public function delete() {
+    // Needs error handling and etc.
+    @drupal_unlink($this->getFilePath());
+    @drupal_unlink($this->getFilePath() . '.sig');
+  }
+}
+
+/**
+ * Defines an interface for verified storage manipulation.
+ *
+ * This class allows reading and writing configuration data from/to the
+ * verified storage and copying to/from the signed file storing the same data.
+ */
+interface DrupalConfigVerifiedStorageInterface {
+
+  /**
+   * Constructs a verified storage manipulation class.
+   *
+   * @param $name
+   *   Lowercase string, the name for the configuration data.
+   */
+  function __construct($name);
+
+  /**
+   * Reads the configuration data from the verified storage.
+   */
+  function read();
+
+  /**
+   * Copies the configuration data from the verified storage into a file.
+   */
+  function copyToFile();
+
+  /**
+   * Copies the configuration data from the file into the verified storage.
+   */
+  function copyFromFile();
+
+  /**
+   * Deletes the configuration data file.
+   */
+  function deleteFile();
+
+  /**
+   * Checks whether the file and the verified storage is in sync.
+   *
+   * @return
+   *   TRUE if the file and the verified storage contains the same data, FALSE
+   *   if not.
+   */
+  function isOutOfSync();
+
+  /**
+   * Writes the configuration data into the active storage but not the file.
+   *
+   * Use this function if you need to make temporary changes to your
+   * configuration.
+   *
+   * @param $data
+   *   The configuration data to write into active storage.
+   */
+  function writeToActive($data);
+
+  /**
+   * Writes the configuration data into the active storage and the file.
+   *
+   * @param $data
+   *   The configuration data to write.
+   */
+  function write($data);
+
+  /**
+   * Gets names starting with this prefix.
+   *
+   * @param $prefix
+   *   @todo
+   */
+  static function getNamesWithPrefix($prefix);
+}
+
+/**
+ * @todo
+ */
+abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorageInterface {
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::__construct().
+   */
+  function __construct($name) {
+    $this->name = $name;
+  }
+
+  /**
+   * @todo
+   *
+   * @return
+   *   @todo
+   */
+  protected function signedFileStorage() {
+    return new SignedFileStorage($this->name);
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::copyToFile().
+   */
+  public function copyToFile() {
+    return $this->signedFileStorage()->write($this->read());
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::deleteFile().
+   */
+  public function deleteFile() {
+    return $this->signedFileStorage()->delete();
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::copyFromFile().
+   */
+  public function copyFromFile() {
+    return $this->writeToActive($this->readFromFile());
+  }
+
+  /**
+   * @todo
+   *
+   * @return
+   *   @todo
+   */
+  public function readFromFile() {
+    return $this->signedFileStorage()->read($this->name);
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::isOutOfSync().
+   */
+  public function isOutOfSync() {
+    return $this->read() !== $this->readFromFile();
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::write().
+   */
+  public function write($data) {
+    $this->writeToActive($data);
+    $this->copyToFile();
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::delete().
+   */
+  public function delete() {
+    $this->deleteFromActive();
+    $this->deleteFile();
+  }
+}
+
+/**
+ * Represents an SQL-based configuration storage object.
+ */
+class DrupalVerifiedStorageSQL extends DrupalConfigVerifiedStorage {
+
+  /**
+   * Overrides DrupalConfigVerifiedStorage::read().
+   */
+  public function read() {
+    // There are situations, like in the installer, where we may attempt a
+    // read without actually having the database available. This is a
+    // workaround and there is probably a better solution to be had at
+    // some point.
+    if (!empty($GLOBALS['databases']) && db_table_exists('config')) {
+      return db_query('SELECT data FROM {config} WHERE name = :name', array(':name' => $this->name))->fetchField();
+    }
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::writeToActive().
+   */
+  public function writeToActive($data) {
+    return db_merge('config')
+      ->key(array('name' => $this->name))
+      ->fields(array('data' => $data))
+      ->execute();
+  }
+
+  /**
+   * @todo
+   */
+  public function deleteFromActive() {
+    db_delete('config')
+      ->condition('name', $this->name)
+      ->execute();
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::getNamesWithPrefix().
+   */
+  static public function getNamesWithPrefix($prefix = '') {
+    return db_query('SELECT name FROM {config} WHERE name LIKE :name', array(':name' => db_like($prefix) . '%'))->fetchCol();
+  }
+}
+
+/**
+ * Represents the default configuration storage object.
+ */
+class DrupalConfig {
+
+  /**
+   * The storage engine to save this config object to.
+   *
+   * @var DrupalConfigVerifiedStorageInterface
+   */
+  protected $_verifiedStorage;
+
+  protected $data = array();
+
+  /**
+   * Constructs a DrupalConfig object.
+   *
+   * @param DrupalConfigVerifiedStorageInterface $verified_storage
+   *   The storage engine where this config object should be saved.
+   */
+  public function __construct(DrupalConfigVerifiedStorageInterface $verified_storage) {
+    $this->_verifiedStorage = $verified_storage;
+    $this->read();
+  }
+
+  /**
+   * Reads config data from the active store into our object.
+   */
+  public function read() {
+    $active = (array) config_decode($this->_verifiedStorage->read());
+    foreach ($active as $key => $value) {
+      $this->set($key, $value);
+    }
+  }
+
+  /**
+   * Checks whether a particular value is overridden.
+   *
+   * @param $key
+   *   @todo
+   *
+   * @return
+   *   @todo
+   */
+  public function isOverridden($key) {
+    return isset($this->_overrides[$key]);
+  }
+
+  /**
+   * Gets value in this config object.
+   *
+   * @param $key
+   *   @todo
+   *
+   * @return
+   *   @todo
+   */
+  public function get($key) {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      return isset($this->data[$key]) ? $this->data[$key] : NULL;
+    }
+    else {
+      return drupal_array_get_nested_value($this->data, $parts);
+    }
+  }
+
+  /**
+   * Sets value in this config object.
+   *
+   * @param $key
+   *   @todo
+   * @param $value
+   *   @todo
+   */
+  public function set($key, $value) {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      $this->data[$key] = $value;
+    }
+    else {
+      drupal_array_set_nested_value($this->data, $parts, $value);
+    }
+  }
+
+  /**
+   * Unsets value in this config object.
+   *
+   * @param $key
+   *   @todo
+   */
+  public function clear($key) {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      unset($this->data[$key]);
+    }
+    else {
+      drupal_array_unset_nested_value($this->data, $parts);
+    }
+  }
+
+  /**
+   * Saves the configuration object to disk as XML.
+   */
+  public function save() {
+    $this->_verifiedStorage->write(config_encode($this->data));
+  }
+
+  /**
+   * Deletes the configuration object on disk.
+   */
+  public function delete() {
+    $this->_verifiedStorage->delete();
+  }
+}
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index f76606b..37fdb9e 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -992,7 +992,31 @@ function install_settings_form_submit($form, &$form_state) {
     'value'    => drupal_hash_base64(drupal_random_bytes(55)),
     'required' => TRUE,
   );
+
+  $settings['drupal_config_key'] = array(
+    'value'    => drupal_hash_base64(drupal_random_bytes(55)),
+    'required' => TRUE,
+  );
+
+  // This duplicates drupal_get_token() because that function can't work yet.
+  // Wondering if it makes sense to move this later in the process, but its
+  // nice having all the settings stuff here.
+  //
+  // @todo This is actually causing a bug right now, because you can install
+  // without hitting install_settings_form_submit() if your settings.php
+  // already has the db stuff in it, and right now in that case your
+  // config directory never gets created. So this needs to be moved elsewhere.
+  $settings['drupal_config_directory_name'] = array(
+    'value'     => 'config_' . drupal_hmac_base64('', session_id() . $settings['drupal_config_key']['value'] . $settings['drupal_hash_salt']['value']),
+    'required'  => TRUE,
+  );
+
   drupal_rewrite_settings($settings);
+  // Actually create the config directory named above.
+  $config_path = conf_path() . '/files/' . $settings['drupal_config_directory_name']['value'];
+  if (!file_prepare_directory($config_path, FILE_CREATE_DIRECTORY)) {
+    // How best to handle errors here?
+  };
   // Indicate that the settings file has been verified, and check the database
   // for the last completed task, now that we have a valid connection. This
   // last step is important since we want to trigger an error if the new
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 533678f..a7b4dc7 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -730,6 +730,7 @@ function drupal_install_system() {
       ))
     ->execute();
   system_rebuild_module_data();
+  config_install_default_config('system');
 }
 
 /**
diff --git a/core/includes/module.inc b/core/includes/module.inc
index f61436e..8b0d8d0 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -437,6 +437,9 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
         $versions = drupal_get_schema_versions($module);
         $version = $versions ? max($versions) : SCHEMA_INSTALLED;
 
+        // Copy any default configuration data to the system config directory/
+        config_install_default_config($module);
+
         // If the module has no current updates, but has some that were
         // previously removed, set the version to the value of
         // hook_update_last_removed().
diff --git a/core/modules/block/config/block.performance.xml b/core/modules/block/config/block.performance.xml
new file mode 100644
index 0000000..39f55d9
--- /dev/null
+++ b/core/modules/block/config/block.performance.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<config>
+	<block_cache>0</block_cache>
+</config>
diff --git a/core/modules/config/config.info b/core/modules/config/config.info
new file mode 100644
index 0000000..96987e8
--- /dev/null
+++ b/core/modules/config/config.info
@@ -0,0 +1,6 @@
+name = Configuration manager
+version = VERSION
+core = 8.x
+files[] = config.module
+files[] = config.test
+package = Core
diff --git a/core/modules/config/config.module b/core/modules/config/config.module
new file mode 100644
index 0000000..a4abe2d
--- /dev/null
+++ b/core/modules/config/config.module
@@ -0,0 +1,2 @@
+<?php
+
diff --git a/core/modules/config/config.test b/core/modules/config/config.test
new file mode 100644
index 0000000..80d68a5
--- /dev/null
+++ b/core/modules/config/config.test
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Tests for Configuration module.
+ */
+
+/**
+ * Tests the secure file writer.
+ */
+class SecureFileTestCase extends DrupalUnitTestCase {
+  protected $filename = 'foo.bar';
+
+  /**
+   * @todo
+   */
+  protected $testContent = 'Good morning, Denver!';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Secure file tests',
+      'description' => 'Tests the saving of secure files.',
+      'group' => 'Configuration',
+    );
+  }
+
+  /**
+   * Tests that a file written by this system has a valid signature.
+   */
+  function testFileVerify() {
+    $file = new SignedFileStorage($this->filename);
+    $file->write($this->testContent);
+
+    $this->assertTrue($file->verify(), 'A file verifies after being written.');
+
+    unset($file);
+
+    // Load the file again, so that there is no stale data from the old object.
+    $file = new SignedFileStorage($this->filename);
+    $this->assertTrue($file->verify(), 'A file verifies after being written and reloaded.');
+  }
+
+  /**
+   * Tests that a file written by this system can be successfully read back.
+   */
+  function testFilePersist() {
+    $file = new SignedFileStorage($this->filename);
+    $file->write($this->testContent);
+
+    unset($file);
+
+    // Reading should throw an exception in case of bad validation.
+    // Note that if any other exception is thrown, we let the test system
+    // handle catching and reporting it.
+    try {
+      $file = new SignedFileStorage($this->filename);
+      $saved_content = $file->read();
+
+      $this->assertEqual($saved_content, $this->testContent, 'A file can be read back successfully.');
+    }
+    catch (Exception $e) {
+      $this->fail('File failed verification when being read.');
+    }
+  }
+
+  /**
+   * Tests that a file fails validation if it's been monkeyed with.
+   */
+  function testFileNotVerify() {
+    $file = new SignedFileStorage($this->filename);
+    $file->write($this->testContent);
+
+    // Manually overwrite the body of the secure file. Note that we skip the
+    // first line, which is reserved for the signature and such, to overwrite
+    // just the payload.
+    $raw_file = new SplFileObject($file->getFilePath(), 'a+');
+    $raw_file->fwrite('Good morning, Detroit!');
+    $raw_file->fflush();
+    unset($raw_file);
+
+    unset($file);
+
+    $file = new SignedFileStorage($this->filename);
+    $this->assertFalse($file->verify(), 'Corrupted file does not verify.');
+  }
+}
+
+/**
+ * Tests reading and writing file contents.
+ */
+class FileContentsTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Config file content tests',
+      'description' => 'Tests the reading and writing of config settings.',
+      'group' => 'Configuration',
+    );
+  }
+
+  /**
+   * Tests that a simple setting can be written and read.
+   */
+  public function testReadWriteConfig() {
+    $config = config('foo.bar');
+    $config->set('foo', 'bar');
+    $config->save();
+    $this->assertEqual('bar', config('foo.bar')->get('foo'), 'Content retrived from written config data.');
+  }
+}
diff --git a/core/modules/image/config/image.styles.large.xml b/core/modules/image/config/image.styles.large.xml
new file mode 100644
index 0000000..62448c1
--- /dev/null
+++ b/core/modules/image/config/image.styles.large.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<config>
+  <name>large</name>
+  <effects>
+    <image_scale_480_480_1>
+      <name>image_scale</name>
+      <ieid>image_scale_480_480_1</ieid>
+      <data>
+        <width>480</width>
+        <height>480</height>
+        <upscale>1</upscale>
+      </data>
+      <weight>0</weight>
+    </image_scale_480_480_1>
+  </effects>
+</config>
diff --git a/core/modules/image/config/image.styles.medium.xml b/core/modules/image/config/image.styles.medium.xml
new file mode 100644
index 0000000..d301877
--- /dev/null
+++ b/core/modules/image/config/image.styles.medium.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<config>
+  <name>medium</name>
+  <effects>
+    <image_scale_220_220_1>
+      <name>image_scale</name>
+      <ieid>image_scale_220_220_1</ieid>
+      <data>
+        <width>220</width>
+        <height>220</height>
+        <upscale>1</upscale>
+      </data>
+      <weight>0</weight>
+    </image_scale_220_220_1>
+  </effects>
+</config>
diff --git a/core/modules/image/config/image.styles.thumbnail.xml b/core/modules/image/config/image.styles.thumbnail.xml
new file mode 100644
index 0000000..385abe6
--- /dev/null
+++ b/core/modules/image/config/image.styles.thumbnail.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<config>
+  <name>thumbnail</name>
+  <effects>
+    <image_scale_100_100_1>
+      <name>image_scale</name>
+      <ieid>image_scale_100_100_1</ieid>
+      <data>
+        <width>100</width>
+        <height>100</height>
+        <upscale>1</upscale>
+      </data>
+      <weight>0</weight>
+    </image_scale_100_100_1>
+  </effects>
+</config>
diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index 85712e6..b721407 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -38,13 +38,6 @@ function image_style_form($form, &$form_state, $style) {
   $title = t('Edit %name style', array('%name' => $style['name']));
   drupal_set_title($title, PASS_THROUGH);
 
-  // Adjust this form for styles that must be overridden to edit.
-  $editable = (bool) ($style['storage'] & IMAGE_STORAGE_EDITABLE);
-
-  if (!$editable && empty($form_state['input'])) {
-    drupal_set_message(t('This image style is currently being provided by a module. Click the "Override defaults" button to change its settings.'), 'warning');
-  }
-
   $form_state['image_style'] = $style;
   $form['#tree'] = TRUE;
   $form['#attached']['css'][drupal_get_path('module', 'image') . '/image.admin.css'] = array();
@@ -56,27 +49,15 @@ function image_style_form($form, &$form_state, $style) {
     '#markup' => theme('image_style_preview', array('style' => $style)),
   );
 
-  // Allow the name of the style to be changed, unless this style is
-  // provided by a module's hook_default_image_styles().
-  if ($style['storage'] & IMAGE_STORAGE_MODULE) {
-    $form['name'] = array(
-      '#type' => 'item',
-      '#title' => t('Image style name'),
-      '#markup' => $style['name'],
-      '#description' => t('This image style is being provided by %module module and may not be renamed.', array('%module' => $style['module'])),
-    );
-  }
-  else {
-    $form['name'] = array(
-      '#type' => 'textfield',
-      '#size' => '64',
-      '#title' => t('Image style name'),
-      '#default_value' => $style['name'],
-      '#description' => t('The name is used in URLs for generated images. Use only lowercase alphanumeric characters, underscores (_), and hyphens (-).'),
-      '#element_validate' => array('image_style_name_validate'),
-      '#required' => TRUE,
-    );
-  }
+  $form['name'] = array(
+    '#type' => 'textfield',
+    '#size' => '64',
+    '#title' => t('Image style name'),
+    '#default_value' => $style['name'],
+    '#description' => t('The name is used in URLs for generated images. Use only lowercase alphanumeric characters, underscores (_), and hyphens (-).'),
+    '#element_validate' => array('image_style_name_validate'),
+    '#required' => TRUE,
+  );
 
   // Build the list of existing image effects for this image style.
   $form['effects'] = array(
@@ -95,25 +76,19 @@ function image_style_form($form, &$form_state, $style) {
       '#title' => t('Weight for @title', array('@title' => $effect['label'])),
       '#title_display' => 'invisible',
       '#default_value' => $effect['weight'],
-      '#access' => $editable,
     );
 
-    // Only attempt to display these fields for editable styles as the 'ieid'
-    // key is not set for styles defined in code.
-    if ($editable) {
-      $form['effects'][$key]['configure'] = array(
-        '#type' => 'link',
-        '#title' => t('edit'),
-        '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $effect['ieid'],
-        '#access' => $editable && isset($effect['form callback']),
-      );
-      $form['effects'][$key]['remove'] = array(
-        '#type' => 'link',
-        '#title' => t('delete'),
-        '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $effect['ieid'] . '/delete',
-        '#access' => $editable,
-      );
-    }
+    $form['effects'][$key]['configure'] = array(
+      '#type' => 'link',
+      '#title' => t('edit'),
+      '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $key,
+      '#access' => isset($effect['form callback']),
+    );
+    $form['effects'][$key]['remove'] = array(
+      '#type' => 'link',
+      '#title' => t('delete'),
+      '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $key . '/delete',
+    );
   }
 
   // Build the new image effect addition form and add it to the effect list.
@@ -124,7 +99,6 @@ function image_style_form($form, &$form_state, $style) {
   $form['effects']['new'] = array(
     '#tree' => FALSE,
     '#weight' => isset($form_state['input']['weight']) ? $form_state['input']['weight'] : NULL,
-    '#access' => $editable,
   );
   $form['effects']['new']['new'] = array(
     '#type' => 'select',
@@ -148,17 +122,9 @@ function image_style_form($form, &$form_state, $style) {
 
   // Show the Override or Submit button for this style.
   $form['actions'] = array('#type' => 'actions');
-  $form['actions']['override'] = array(
-    '#type' => 'submit',
-    '#value' => t('Override defaults'),
-    '#validate' => array(),
-    '#submit' => array('image_style_form_override_submit'),
-    '#access' => !$editable,
-  );
   $form['actions']['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Update style'),
-    '#access' => $editable,
   );
 
   return $form;
@@ -188,42 +154,44 @@ function image_style_form_add_submit($form, &$form_state) {
   }
   // If there's no form, immediately add the image effect.
   else {
-    $effect['isid'] = $style['isid'];
-    $effect['weight'] = $form_state['values']['weight'];
-    image_effect_save($effect);
+    $effect = array(
+      'name' => $effect['name'],
+      'data' => array(),
+      'weight' => $form_state['values']['weight'],
+    );
+    image_effect_save($style['name'], $effect);
     drupal_set_message(t('The image effect was successfully applied.'));
   }
 }
 
 /**
- * Submit handler for overriding a module-defined style.
- */
-function image_style_form_override_submit($form, &$form_state) {
-  drupal_set_message(t('The %style style has been overridden, allowing you to change its settings.', array('%style' => $form_state['image_style']['name'])));
-  image_default_style_save($form_state['image_style']);
-}
-
-/**
  * Submit handler for saving an image style.
  */
 function image_style_form_submit($form, &$form_state) {
-  // Update the image style name if it has changed.
   $style = $form_state['image_style'];
-  if (isset($form_state['values']['name']) && $style['name'] != $form_state['values']['name']) {
-    $style['name'] = $form_state['values']['name'];
-  }
 
   // Update image effect weights.
   if (!empty($form_state['values']['effects'])) {
     foreach ($form_state['values']['effects'] as $ieid => $effect_data) {
       if (isset($style['effects'][$ieid])) {
-        $effect = $style['effects'][$ieid];
-        $effect['weight'] = $effect_data['weight'];
-        image_effect_save($effect);
+        $effect = array(
+          'name' => $style['effects'][$ieid]['name'],
+          'data' => $style['effects'][$ieid]['data'],
+          'weight' => $effect_data['weight'],
+        );
+        $style['effects'][$ieid] = $effect;
       }
     }
   }
 
+  // Update the image style name if it has changed. We also need to delete the
+  // old style, because there is no concept of rename at the moment, just
+  // create and delete.
+  if (isset($form_state['values']['name']) && $style['name'] != $form_state['values']['name']) {
+    image_style_delete($style);
+    $style['name'] = $form_state['values']['name'];
+  }
+
   image_style_save($style);
   if ($form_state['values']['op'] == t('Update style')) {
     drupal_set_message(t('Changes to the style have been saved.'));
@@ -273,7 +241,7 @@ function image_style_add_form_submit($form, &$form_state) {
 function image_style_name_validate($element, $form_state) {
   // Check for duplicates.
   $styles = image_styles();
-  if (isset($styles[$element['#value']]) && (!isset($form_state['image_style']['isid']) || $styles[$element['#value']]['isid'] != $form_state['image_style']['isid'])) {
+  if (isset($styles[$element['#value']]) && (!isset($form_state['image_style']['name']) || $styles[$element['#value']]['name'] != $form_state['image_style']['name'])) {
     form_set_error($element['#name'], t('The image style name %name is already in use.', array('%name' => $element['#value'])));
   }
 
@@ -324,30 +292,6 @@ function image_style_delete_form_submit($form, &$form_state) {
 }
 
 /**
- * Confirmation form to revert a database style to its default.
- */
-function image_style_revert_form($form, $form_state, $style) {
-  $form_state['image_style'] = $style;
-
-  return confirm_form(
-    $form,
-    t('Revert the %style style?', array('%style' => $style['name'])),
-    'admin/config/media/image-styles',
-    t('Reverting this style will delete the customized settings and restore the defaults provided by the @module module.', array('@module' => $style['module'])),
-    t('Revert'),  t('Cancel')
-  );
-}
-
-/**
- * Submit handler to convert an overridden style to its default.
- */
-function image_style_revert_form_submit($form, &$form_state) {
-  drupal_set_message(t('The %style style has been revert to its defaults.', array('%style' => $form_state['image_style']['name'])));
-  image_default_style_revert($form_state['image_style']);
-  $form_state['redirect'] = 'admin/config/media/image-styles';
-}
-
-/**
  * Form builder; Form for adding and editing image effects.
  *
  * This form is used universally for editing all image effects. Each effect adds
@@ -416,12 +360,14 @@ function image_effect_form($form, &$form_state, $style, $effect) {
  * Submit handler for updating an image effect.
  */
 function image_effect_form_submit($form, &$form_state) {
-  $style = $form_state['image_style'];
-  $effect = array_merge($form_state['image_effect'], $form_state['values']);
-  $effect['isid'] = $style['isid'];
-  image_effect_save($effect);
+  $effect = array(
+    'name' => $form_state['image_effect']['name'],
+    'data' => $form_state['values']['data'],
+    'weight' => $form_state['values']['weight'],
+  );
+  image_effect_save($form_state['image_style']['name'], $effect);
   drupal_set_message(t('The image effect was successfully applied.'));
-  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
+  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $form_state['image_style']['name'];
 }
 
 /**
@@ -449,7 +395,7 @@ function image_effect_delete_form_submit($form, &$form_state) {
   $style = $form_state['image_style'];
   $effect = $form_state['image_effect'];
 
-  image_effect_delete($effect);
+  image_effect_delete($style['name'], $effect);
   drupal_set_message(t('The image effect %name has been deleted.', array('%name' => $effect['label'])));
   $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
 }
@@ -645,31 +591,19 @@ function image_rotate_form($data) {
 function theme_image_style_list($variables) {
   $styles = $variables['styles'];
 
-  $header = array(t('Style name'), t('Settings'), array('data' => t('Operations'), 'colspan' => 3));
+  $header = array(t('Style name'), array('data' => t('Operations'), 'colspan' => 3));
   $rows = array();
+  $link_attributes = array(
+    'attributes' => array(
+      'class' => array('image-style-link'),
+    ),
+  );
+
   foreach ($styles as $style) {
     $row = array();
     $row[] = l($style['name'], 'admin/config/media/image-styles/edit/' . $style['name']);
-    $link_attributes = array(
-      'attributes' => array(
-        'class' => array('image-style-link'),
-      ),
-    );
-    if ($style['storage'] == IMAGE_STORAGE_NORMAL) {
-      $row[] = t('Custom');
-      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
-      $row[] = l(t('delete'), 'admin/config/media/image-styles/delete/' . $style['name'], $link_attributes);
-    }
-    elseif ($style['storage'] == IMAGE_STORAGE_OVERRIDE) {
-      $row[] = t('Overridden');
-      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
-      $row[] = l(t('revert'), 'admin/config/media/image-styles/revert/' . $style['name'], $link_attributes);
-    }
-    else {
-      $row[] = t('Default');
-      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
-      $row[] = '';
-    }
+    $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
+    $row[] = l(t('delete'), 'admin/config/media/image-styles/delete/' . $style['name'], $link_attributes);
     $rows[] = $row;
   }
 
@@ -694,13 +628,12 @@ function theme_image_style_list($variables) {
  */
 function theme_image_style_effects($variables) {
   $form = $variables['form'];
-
   $rows = array();
 
   foreach (element_children($form) as $key) {
     $row = array();
     $form[$key]['weight']['#attributes']['class'] = array('image-effect-order-weight');
-    if (is_numeric($key)) {
+    if ($key != 'new') {
       $summary = drupal_render($form[$key]['summary']);
       $row[] = drupal_render($form[$key]['label']) . (empty($summary) ? '' : ' ' . $summary);
       $row[] = drupal_render($form[$key]['weight']);
@@ -728,7 +661,7 @@ function theme_image_style_effects($variables) {
     array('data' => t('Operations'), 'colspan' => 2),
   );
 
-  if (count($rows) == 1 && $form['new']['#access']) {
+  if (count($rows) == 1 && (!isset($form['new']['#access']) || $form['new']['#access'])) {
     array_unshift($rows, array(array(
       'data' => t('There are currently no effects in this style. Add one by selecting an option below.'),
       'colspan' => 4,
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index f577b76..9b3c9a0 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -135,15 +135,6 @@ function image_menu() {
     'access arguments' => array('administer image styles'),
     'file' => 'image.admin.inc',
   );
-  $items['admin/config/media/image-styles/revert/%image_style'] = array(
-    'title' => 'Revert style',
-    'description' => 'Revert an image style.',
-    'load arguments' => array(NULL, (string) IMAGE_STORAGE_OVERRIDE),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('image_style_revert_form', 5),
-    'access arguments' => array('administer image styles'),
-    'file' => 'image.admin.inc',
-  );
   $items['admin/config/media/image-styles/edit/%image_style/effects/%image_effect'] = array(
     'title' => 'Edit image effect',
     'description' => 'Edit an existing effect within a style.',
@@ -331,45 +322,6 @@ function image_file_predelete($file) {
 }
 
 /**
- * Implements hook_image_default_styles().
- */
-function image_image_default_styles() {
-  $styles = array();
-
-  $styles['thumbnail'] = array(
-    'effects' => array(
-      array(
-        'name' => 'image_scale',
-        'data' => array('width' => 100, 'height' => 100, 'upscale' => 1),
-        'weight' => 0,
-      ),
-    )
-  );
-
-  $styles['medium'] = array(
-    'effects' => array(
-      array(
-        'name' => 'image_scale',
-        'data' => array('width' => 220, 'height' => 220, 'upscale' => 1),
-        'weight' => 0,
-      ),
-    )
-  );
-
-  $styles['large'] = array(
-    'effects' => array(
-      array(
-        'name' => 'image_scale',
-        'data' => array('width' => 480, 'height' => 480, 'upscale' => 0),
-        'weight' => 0,
-      ),
-    )
-  );
-
-  return $styles;
-}
-
-/**
  * Implements hook_image_style_save().
  */
 function image_image_style_save($style) {
@@ -493,41 +445,19 @@ function image_styles() {
     else {
       $styles = array();
 
-      // Select the module-defined styles.
-      foreach (module_implements('image_default_styles') as $module) {
-        $module_styles = module_invoke($module, 'image_default_styles');
-        foreach ($module_styles as $style_name => $style) {
-          $style['name'] = $style_name;
-          $style['module'] = $module;
-          $style['storage'] = IMAGE_STORAGE_DEFAULT;
-          foreach ($style['effects'] as $key => $effect) {
-            $definition = image_effect_definition_load($effect['name']);
-            $effect = array_merge($definition, $effect);
-            $style['effects'][$key] = $effect;
-          }
-          $styles[$style_name] = $style;
+      // Select the styles we have configured.
+      foreach (config_get_signed_file_storage_names_with_prefix('image.styles') as $config_name) {
+        $style = array();
+        $config = config($config_name);
+        $style['name'] = $config->get('name');
+        $style['effects'] = array();
+        foreach ($config->get('effects') as $key => $effect) {
+          $definition = image_effect_definition_load($effect['name']);
+          $effect = array_merge($definition, $effect);
+          $style['effects'][$key] = $effect;
         }
+        $styles[$style['name']] = $style;
       }
-
-      // Select all the user-defined styles.
-      $user_styles = db_select('image_styles', NULL, array('fetch' => PDO::FETCH_ASSOC))
-        ->fields('image_styles')
-        ->orderBy('name')
-        ->execute()
-        ->fetchAllAssoc('name', PDO::FETCH_ASSOC);
-
-      // Allow the user styles to override the module styles.
-      foreach ($user_styles as $style_name => $style) {
-        $style['module'] = NULL;
-        $style['storage'] = IMAGE_STORAGE_NORMAL;
-        $style['effects'] = image_style_effects($style);
-        if (isset($styles[$style_name]['module'])) {
-          $style['module'] = $styles[$style_name]['module'];
-          $style['storage'] = IMAGE_STORAGE_OVERRIDE;
-        }
-        $styles[$style_name] = $style;
-      }
-
       drupal_alter('image_styles', $styles);
       cache()->set('image_styles', $styles);
     }
@@ -541,41 +471,19 @@ function image_styles() {
  *
  * @param $name
  *   The name of the style.
- * @param $isid
- *   Optional. The numeric id of a style if the name is not known.
- * @param $include
- *   If set, this loader will restrict to a specific type of image style, may be
- *   one of the defined Image style storage constants.
  * @return
  *   An image style array containing the following keys:
- *   - "isid": The unique image style ID.
  *   - "name": The unique image style name.
  *   - "effects": An array of image effects within this image style.
- *   If the image style name or ID is not valid, an empty array is returned.
+ *   If the image style name is not valid, an empty array is returned.
  * @see image_effect_load()
  */
-function image_style_load($name = NULL, $isid = NULL, $include = NULL) {
+function image_style_load($name = NULL) {
   $styles = image_styles();
 
   // If retrieving by name.
   if (isset($name) && isset($styles[$name])) {
-    $style = $styles[$name];
-  }
-
-  // If retrieving by image style id.
-  if (!isset($name) && isset($isid)) {
-    foreach ($styles as $name => $database_style) {
-      if (isset($database_style['isid']) && $database_style['isid'] == $isid) {
-        $style = $database_style;
-        break;
-      }
-    }
-  }
-
-  // Restrict to the specific type of flag. This bitwise operation basically
-  // states "if the storage is X, then allow".
-  if (isset($style) && (!isset($include) || ($style['storage'] & (int) $include))) {
-    return $style;
+    return $styles[$name];
   }
 
   // Otherwise the style was not found.
@@ -591,19 +499,16 @@ function image_style_load($name = NULL, $isid = NULL, $include = NULL) {
  *   An image style array. In the case of a new style, 'isid' will be populated.
  */
 function image_style_save($style) {
-  if (isset($style['isid']) && is_numeric($style['isid'])) {
-    // Load the existing style to make sure we account for renamed styles.
-    $old_style = image_style_load(NULL, $style['isid']);
-    image_style_flush($old_style);
-    drupal_write_record('image_styles', $style, 'isid');
-    if ($old_style['name'] != $style['name']) {
-      $style['old_name'] = $old_style['name'];
-    }
+  $config = config('image.styles.' . $style['name']);
+  $config->set('name', $style['name']);
+  if ($style['effects']) {
+    $config->set('effects', $style['effects']);
   }
   else {
-    drupal_write_record('image_styles', $style);
-    $style['is_new'] = TRUE;
+    $config->set('effects', array());
   }
+  $config->save();
+  $style['is_new'] = TRUE;
 
   // Let other modules update as necessary on save.
   module_invoke_all('image_style_save', $style);
@@ -628,8 +533,8 @@ function image_style_save($style) {
 function image_style_delete($style, $replacement_style_name = '') {
   image_style_flush($style);
 
-  db_delete('image_effects')->condition('isid', $style['isid'])->execute();
-  db_delete('image_styles')->condition('isid', $style['isid'])->execute();
+  $config = config('image.styles.' . $style['name']);
+  $config->delete();
 
   // Let other modules update as necessary on save.
   $style['old_name'] = $style['name'];
@@ -876,15 +781,15 @@ function image_style_flush($style) {
  *
  * @param $style_name
  *   The name of the style to be used with this image.
- * @param $uri
+ * @param $path
  *   The path to the image.
  * @return
  *   The absolute URL where a style image can be downloaded, suitable for use
  *   in an <img> tag. Requesting the URL will cause the image to be created.
  * @see image_style_deliver()
  */
-function image_style_url($style_name, $uri) {
-  $uri = image_style_path($style_name, $uri);
+function image_style_url($style_name, $path) {
+  $uri = image_style_path($style_name, $path);
 
   // If not using clean URLs, the image derivative callback is only available
   // with the query string. If the file does not exist, use url() to ensure
@@ -925,44 +830,6 @@ function image_style_path($style_name, $uri) {
 }
 
 /**
- * Save a default image style to the database.
- *
- * @param style
- *   An image style array provided by a module.
- * @return
- *   An image style array. The returned style array will include the new 'isid'
- *   assigned to the style.
- */
-function image_default_style_save($style) {
-  $style = image_style_save($style);
-  $effects = array();
-  foreach ($style['effects'] as $effect) {
-    $effect['isid'] = $style['isid'];
-    $effect = image_effect_save($effect);
-    $effects[$effect['ieid']] = $effect;
-  }
-  $style['effects'] = $effects;
-  return $style;
-}
-
-/**
- * Revert the changes made by users to a default image style.
- *
- * @param style
- *   An image style array.
- * @return
- *   Boolean TRUE if the operation succeeded.
- */
-function image_default_style_revert($style) {
-  image_style_flush($style);
-
-  db_delete('image_effects')->condition('isid', $style['isid'])->execute();
-  db_delete('image_styles')->condition('isid', $style['isid'])->execute();
-
-  return TRUE;
-}
-
-/**
  * Pull in image effects exposed by modules implementing hook_image_effect_info().
  *
  * @return
@@ -1015,8 +882,6 @@ function image_effect_definitions() {
  *
  * @param $effect
  *   The name of the effect definition to load.
- * @param $style
- *   An image style array to which this effect will be added.
  * @return
  *   An array containing the image effect definition with the following keys:
  *   - "effect": The unique name for the effect being performed. Usually prefixed
@@ -1028,18 +893,8 @@ function image_effect_definitions() {
  *   - "summary": (optional) The name of a theme function that will display a
  *     one-line summary of the effect. Does not include the "theme_" prefix.
  */
-function image_effect_definition_load($effect, $style_name = NULL) {
+function image_effect_definition_load($effect) {
   $definitions = image_effect_definitions();
-
-  // If a style is specified, do not allow loading of default style
-  // effects.
-  if (isset($style_name)) {
-    $style = image_style_load($style_name, NULL);
-    if ($style['storage'] == IMAGE_STORAGE_DEFAULT) {
-      return FALSE;
-    }
-  }
-
   return isset($definitions[$effect]) ? $definitions[$effect] : FALSE;
 }
 
@@ -1078,8 +933,8 @@ function image_effects() {
 /**
  * Load a single image effect.
  *
- * @param $ieid
- *   The image effect ID.
+ * @param $name
+ *   The image effect name.
  * @param $style_name
  *   The image style name.
  * @param $include
@@ -1098,9 +953,9 @@ function image_effects() {
  * @see image_style_load()
  * @see image_effect_definition_load()
  */
-function image_effect_load($ieid, $style_name, $include = NULL) {
-  if (($style = image_style_load($style_name, NULL, $include)) && isset($style['effects'][$ieid])) {
-    return $style['effects'][$ieid];
+function image_effect_load($name, $style_name) {
+  if (($style = image_style_load($style_name)) && isset($style['effects'][$name])) {
+    return $style['effects'][$name];
   }
   return FALSE;
 }
@@ -1108,19 +963,37 @@ function image_effect_load($ieid, $style_name, $include = NULL) {
 /**
  * Save an image effect.
  *
+ * @param $style_name
+ *   The image style this effect belongs to.
  * @param $effect
  *   An image effect array.
  * @return
  *   An image effect array. In the case of a new effect, 'ieid' will be set.
  */
-function image_effect_save($effect) {
+function image_effect_save($style_name, $effect) {
+  $config = config('image.styles.' . $style_name);
+
   if (!empty($effect['ieid'])) {
-    drupal_write_record('image_effects', $effect, 'ieid');
+    $old_effect = $config->get('effects.' . $effect['ieid']);
+    foreach ($old_effect as $key => $value) {
+      $old_effect[$key] = $effect[$key];
+      $config->set('effects.' . $effect['ieid'], $old_effect);
+    }
   }
   else {
-    drupal_write_record('image_effects', $effect);
+    // We need to generate the ieid and save the new effect.
+    // The machine name is all the elements of the data array concatenated
+    // together, delimited by underscores.
+    $machine_name = $effect['name'];
+
+    foreach ($effect['data'] as $key => $value) {
+      $machine_name .= '_' . $value;
+    }
+    $effect['ieid'] = $machine_name;
+    $config->set('effects.' . $machine_name, $effect);
   }
-  $style = image_style_load(NULL, $effect['isid']);
+  $config->save();
+  $style = image_style_load(NULL, $style_name);
   image_style_flush($style);
   return $effect;
 }
@@ -1128,12 +1001,16 @@ function image_effect_save($effect) {
 /**
  * Delete an image effect.
  *
+ * @param $style_name
+ *   The image style this effect belongs to.
  * @param $effect
  *   An image effect array.
  */
-function image_effect_delete($effect) {
-  db_delete('image_effects')->condition('ieid', $effect['ieid'])->execute();
-  $style = image_style_load(NULL, $effect['isid']);
+function image_effect_delete($style_name, $effect) {
+  $config = config('image.styles.' . $style_name);
+  $config->clear('effects.' . $effect['ieid']);
+  $config->save();
+  $style = image_style_load($style_name);
   image_style_flush($style);
 }
 
@@ -1159,7 +1036,7 @@ function image_effect_apply($image, $effect) {
  * @param $variables
  *   An associative array containing:
  *   - style_name: The name of the style to be used to alter the original image.
- *   - uri: The path of the image file relative to the Drupal files directory.
+ *   - path: The path of the image file relative to the Drupal files directory.
  *     This function does not work with images outside the files directory nor
  *     with remotely hosted images.
  *   - width: The width of the source image (if known).
@@ -1184,7 +1061,7 @@ function theme_image_style($variables) {
   $variables['height'] = $dimensions['height'];
 
   // Determine the url for the styled image.
-  $variables['uri'] = image_style_url($variables['style_name'], $variables['uri']);
+  $variables['path'] = image_style_url($variables['style_name'], $variables['path']);
   return theme('image', $variables);
 }
 
diff --git a/core/modules/simpletest/tests/bootstrap.test b/core/modules/simpletest/tests/bootstrap.test
index 13fdf07..88f3d41 100644
--- a/core/modules/simpletest/tests/bootstrap.test
+++ b/core/modules/simpletest/tests/bootstrap.test
@@ -291,14 +291,18 @@ class HookBootExitTestCase extends DrupalWebTestCase {
    */
   function testHookBootExit() {
     // Test with cache disabled. Boot and exit should always fire.
-    variable_set('cache', 0);
+    $config = config('system.performance');
+    $config->set('cache', 0);
+    $config->save();
+
     $this->drupalGet('');
     $calls = 1;
     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot called with disabled cache.'));
     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_exit'))->fetchField(), $calls, t('hook_exit called with disabled cache.'));
 
     // Test with normal cache. Boot and exit should be called.
-    variable_set('cache', 1);
+    $config->set('cache', 1);
+    $config->save();
     $this->drupalGet('');
     $calls++;
     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot called with normal cache.'));
diff --git a/core/modules/system/config/system.performance.xml b/core/modules/system/config/system.performance.xml
new file mode 100644
index 0000000..faa9950
--- /dev/null
+++ b/core/modules/system/config/system.performance.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<config>
+	<cache>0</cache>
+	<cache_lifetime>0</cache_lifetime>
+	<page_cache_maximum_age>0</page_cache_maximum_age>
+	<page_compression>0</page_compression>
+	<preprocess_css>0</preprocess_css>
+	<preprocess_js>0</preprocess_js>
+</config>
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 6dca80b..4350c85 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -1638,10 +1638,11 @@ function system_logging_settings() {
  * Form builder; Configure site performance settings.
  *
  * @ingroup forms
- * @see system_settings_form()
+ * @see system_performance_settings_submit().
  */
-function system_performance_settings() {
+function system_performance_settings($form, &$form_state) {
   drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
+  $config = config('system.performance');
 
   $form['clear_cache'] = array(
     '#type' => 'fieldset',
@@ -1659,11 +1660,10 @@ function system_performance_settings() {
     '#title' => t('Caching'),
   );
 
-  $cache = variable_get('cache', 0);
   $form['caching']['cache'] = array(
     '#type' => 'checkbox',
     '#title' => t('Cache pages for anonymous users'),
-    '#default_value' => $cache,
+    '#default_value' => $config->get('cache'),
     '#weight' => -2,
   );
   $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval');
@@ -1671,16 +1671,16 @@ function system_performance_settings() {
   $form['caching']['cache_lifetime'] = array(
     '#type' => 'select',
     '#title' => t('Minimum cache lifetime'),
-    '#default_value' => variable_get('cache_lifetime', 0),
+    '#default_value' => $config->get('cache_lifetime'),
     '#options' => $period,
-    '#description' => t('Cached pages will not be re-created until at least this much time has elapsed.')
+    '#description' => t('Cached pages will not be re-created until at least this much time has elapsed.'),
   );
   $form['caching']['page_cache_maximum_age'] = array(
     '#type' => 'select',
     '#title' => t('Expiration of cached pages'),
-    '#default_value' => variable_get('page_cache_maximum_age', 0),
+    '#default_value' => $config->get('page_cache_maximum_age'),
     '#options' => $period,
-    '#description' => t('The maximum time an external cache can use an old version of a page.')
+    '#description' => t('The maximum time an external cache can use an old version of a page.'),
   );
 
   $directory = 'public://';
@@ -1697,34 +1697,57 @@ function system_performance_settings() {
     '#description' => t('External resources can be optimized automatically, which can reduce both the size and number of requests made to your website.') . $disabled_message,
   );
 
-  $js_hide = $cache ? '' : ' class="js-hide"';
+  $js_hide = $config->get('cache') ? '' : ' class="js-hide"';
   $form['bandwidth_optimization']['page_compression'] = array(
     '#type' => 'checkbox',
     '#title' => t('Compress cached pages.'),
-    '#default_value' => variable_get('page_compression', TRUE),
+    '#default_value' => $config->get('page_compression'),
     '#prefix' => '<div id="page-compression-wrapper"' . $js_hide . '>',
     '#suffix' => '</div>',
   );
   $form['bandwidth_optimization']['preprocess_css'] = array(
     '#type' => 'checkbox',
     '#title' => t('Aggregate and compress CSS files.'),
-    '#default_value' => intval(variable_get('preprocess_css', 0) && $is_writable),
+    '#default_value' => $config->get('preprocess_css'),
     '#disabled' => $disabled,
   );
   $form['bandwidth_optimization']['preprocess_js'] = array(
     '#type' => 'checkbox',
     '#title' => t('Aggregate JavaScript files.'),
-    '#default_value' => intval(variable_get('preprocess_js', 0) && $is_writable),
+    '#default_value' => $config->get('preprocess_js'),
     '#disabled' => $disabled,
   );
 
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+
   $form['#submit'][] = 'drupal_clear_css_cache';
   $form['#submit'][] = 'drupal_clear_js_cache';
   // This form allows page compression settings to be changed, which can
   // invalidate the page cache, so it needs to be cleared on form submit.
   $form['#submit'][] = 'system_clear_page_cache_submit';
+  $form['#submit'][] = 'system_performance_settings_submit';
 
-  return system_settings_form($form);
+  return $form;
+}
+
+/**
+ * Form submission handler for system_performance_settings().
+ *
+ * @ingroup forms
+ */
+function system_performance_settings_submit($form, &$form_state) {
+  $config = config('system.performance');
+  $config->set('cache', $form_state['values']['cache']);
+  $config->set('cache_lifetime', $form_state['values']['cache_lifetime']);
+  $config->set('page_cache_maximum_age', $form_state['values']['page_cache_maximum_age']);
+  $config->set('page_compression', $form_state['values']['page_compression']);
+  $config->set('preprocess_css', $form_state['values']['preprocess_css']);
+  $config->set('preprocess_js', $form_state['values']['preprocess_js']);
+  $config->save();
 }
 
 /**
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 20e1dc1..a2aaf19 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -690,6 +690,28 @@ function system_schema() {
   $schema['cache_path'] = $schema['cache'];
   $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
 
+  $schema['config'] = array(
+    'description' => 'Default active store 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 .json.php).',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'data' => array(
+        'description' => 'The raw JSON data for this configuration entry.',
+        'type' => 'blob',
+        'not null' => TRUE,
+        'size' => 'big',
+        'translatable' => TRUE,
+      ),
+    ),
+    'primary key' => array('name'),
+  );
+
+
   $schema['date_format_type'] = array(
     'description' => 'Stores configured date format types.',
     'fields' => array(
@@ -1661,6 +1683,36 @@ function system_update_8002() {
 }
 
 /**
+ * Adds {config} table for new Configuration system.
+ */
+function system_update_8003() {
+  // @todo Temporary.
+  if (db_table_exists('config')) {
+    db_drop_table('config');
+  }
+  db_create_table('config', array(
+    'description' => 'Default active store 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 .json.php).',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'data' => array(
+        'description' => 'The raw JSON data for this configuration entry.',
+        'type' => 'blob',
+        'not null' => TRUE,
+        'size' => 'big',
+        'translatable' => TRUE,
+      ),
+    ),
+    'primary key' => array('name'),
+  ));
+}
+
+/**
  * @} End of "defgroup updates-7.x-to-8.x"
  * The next series of updates should start at 9000.
  */
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 725cad7..47ed6a4 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2785,12 +2785,27 @@ function system_settings_form_submit($form, &$form_state) {
   // Exclude unnecessary elements.
   form_state_values_clean($form_state);
 
+  $config_objects = array();
   foreach ($form_state['values'] as $key => $value) {
+    if (isset($form_state['config'][$key])) {
+      $config_name = $form_state['config'][$key]['name'];
+      $config_key = $form_state['config'][$key]['path'];
+      if (empty($config_objects[$config_name])) {
+        $config_objects[$config_name] = config($config_name);
+      }
+      if (!empty($config_objects[$config_name])) {
+        $config_objects[$config_name]->set($config_key, $value);
+        continue;
+      }
+    }
     if (is_array($value) && isset($form_state['values']['array_filter'])) {
       $value = array_keys(array_filter($value));
     }
     variable_set($key, $value);
   }
+  foreach ($config_objects as $config) {
+    $config->save();
+  }
 
   drupal_set_message(t('The configuration options have been saved.'));
 }
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 360e556..763df4f 100755
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -235,6 +235,28 @@ $update_free_access = FALSE;
 $drupal_hash_salt = '';
 
 /**
+ * Location of the site configuration files.
+ *
+ * By default, Drupal configuration files are stored in a randomly named
+ * directory under the default public files path. On install the
+ * named directory is created in the default files directory. For enhanced
+ * security, you may set this variable to a location outside your docroot.
+ *
+ * @todo Flesh this out, provide more details, etc.
+ *
+ * Example:
+ *   $drupal_config_directory_name = '/some/directory/outside/webroot';
+ */
+$drupal_config_directory_name = '';
+
+/**
+ * Configuration key.
+ *
+ * Drupal configuration files are signed using this key.
+ */
+$drupal_config_key = '';
+
+/**
  * Base URL (optional).
  *
  * If Drupal is generating incorrect URLs on your site, which could
