diff --git a/core/INSTALL.txt b/core/INSTALL.txt
index 72a3dd1..079130b 100644
--- a/core/INSTALL.txt
+++ b/core/INSTALL.txt
@@ -151,12 +151,12 @@ INSTALLATION
       which is normally in the directory sites/default (to avoid problems when
       upgrading, Drupal is not packaged with this file). If auto-creation fails,
       you will need to create this file yourself, using the file
-      sites/default/default.settings.php as a template.
+      core/default.settings.php as a template.
 
       For example, on a Unix/Linux command line, you can make a copy of the
       default.settings.php file with the command:
 
-        cp sites/default/default.settings.php sites/default/settings.php
+        cp core/default.settings.php sites/default/settings.php
 
       Next, grant write privileges to the file to everyone (including the web
       server) with the command:
diff --git a/core/UPGRADE.txt b/core/UPGRADE.txt
index f035b6c..57021fb 100644
--- a/core/UPGRADE.txt
+++ b/core/UPGRADE.txt
@@ -163,10 +163,6 @@ following the instructions in the INTRODUCTION section at the top of this file:
    no longer need their data, then you can uninstall them under the Uninstall
    tab after disabling them.
 
-8. On the command line or in your FTP client, remove the file
-
-     sites/default/default.settings.php
-
 9. Remove all old core files and directories, except for the 'sites' directory
    and any custom files you added elsewhere.
 
diff --git a/core/default.settings.php b/core/default.settings.php
new file mode 100644
index 0000000..1244094
--- /dev/null
+++ b/core/default.settings.php
@@ -0,0 +1,712 @@
+<?php
+
+/**
+ * @file
+ * Drupal configuration file.
+ *
+ * IMPORTANT NOTE:
+ * This file may have been set to read-only by the Drupal installation program.
+ * If you make changes to this file, be sure to protect it again after making
+ * your modifications. Failure to remove write permissions to this file is a
+ * security risk.
+ *
+ * The configuration file to be loaded is based upon the rules below. However
+ * if the multisite aliasing is enabled, the aliases in the $sites array will
+ * override the default directory rules below.
+ *
+ * The configuration directory will be discovered by stripping the website's
+ * hostname from left to right and pathname from right to left. The first
+ * configuration file found will be used and any others will be ignored. If no
+ * other configuration file is found then the default configuration file at
+ * 'sites/default' will be used.
+ *
+ * For example, for a fictitious site installed at
+ * http://www.drupal.org:8080/mysite/test/, the 'settings.php' file is searched
+ * for in the following directories:
+ *
+ * - sites/8080.www.drupal.org.mysite.test
+ * - sites/www.drupal.org.mysite.test
+ * - sites/drupal.org.mysite.test
+ * - sites/org.mysite.test
+ *
+ * - sites/8080.www.drupal.org.mysite
+ * - sites/www.drupal.org.mysite
+ * - sites/drupal.org.mysite
+ * - sites/org.mysite
+ *
+ * - sites/8080.www.drupal.org
+ * - sites/www.drupal.org
+ * - sites/drupal.org
+ * - sites/org
+ *
+ * - sites/default
+ *
+ * Note that if you are installing on a non-standard port number, prefix the
+ * hostname with that number. For example,
+ * http://www.drupal.org:8080/mysite/test/ could be loaded from
+ * sites/8080.www.drupal.org.mysite.test/.
+ */
+
+/**
+ * Multi-site functionality and aliases.
+ *
+ * Uncomment the $sites variable below to enable Drupal's multi-site
+ * functionality, which allows to serve multiple different sites from the same
+ * code-base.
+ *
+ * An empty $sites variable just enables the sites directory discovery process.
+ * You can additionally define aliases that map hostnames, ports, and path names
+ * to specific site directories. These aliases are applied prior to scanning for
+ * directories and exempt from the discovery rules.
+ *
+ * Aliases are useful on development servers, where the domain name may not be
+ * the same as the domain of the live server. Since Drupal stores file paths in
+ * the database (files, system table, etc.) this will ensure the paths are
+ * correct when the site is deployed to a live server.
+ *
+ * Aliases are defined in an associative array named $sites. The array is
+ * written in the format: '<port>.<domain>.<path>' => 'directory'. As an
+ * example, to map http://www.drupal.org:8080/mysite/test to the configuration
+ * directory sites/example.com, the array should be defined as:
+ * @code
+ * $sites = array(
+ *   '8080.www.drupal.org.mysite.test' => 'example.com',
+ * );
+ * @endcode
+ * The URL, http://www.drupal.org:8080/mysite/test/, could be a symbolic link or
+ * an Apache Alias directive that points to the Drupal root containing
+ * index.php. An alias could also be created for a subdomain. See the
+ * @link http://drupal.org/documentation/install online Drupal installation guide @endlink
+ * for more information on setting up domains, subdomains, and subdirectories.
+ *
+ * The following examples look for a site configuration in sites/example.com:
+ * @code
+ * URL: http://dev.drupal.org
+ * $sites['dev.drupal.org'] = 'example.com';
+ *
+ * URL: http://localhost/example
+ * $sites['localhost.example'] = 'example.com';
+ *
+ * URL: http://localhost:8080/example
+ * $sites['8080.localhost.example'] = 'example.com';
+ *
+ * URL: http://www.drupal.org:8080/mysite/test/
+ * $sites['8080.www.drupal.org.mysite.test'] = 'example.com';
+ * @endcode
+ *
+ * @see default.settings.php
+ * @see \Drupal\Core\Site\Site::getPath()
+ * @see http://drupal.org/documentation/install/multi-site
+ */
+# $sites = array();
+# $sites['localhost.example'] = 'example.com';
+
+/**
+ * Database settings:
+ *
+ * The $databases array specifies the database connection or
+ * connections that Drupal may use.  Drupal is able to connect
+ * to multiple databases, including multiple types of databases,
+ * during the same request.
+ *
+ * Each database connection is specified as an array of settings,
+ * similar to the following:
+ * @code
+ * array(
+ *   'driver' => 'mysql',
+ *   'database' => 'databasename',
+ *   'username' => 'username',
+ *   'password' => 'password',
+ *   'host' => 'localhost',
+ *   'port' => 3306,
+ *   'prefix' => 'myprefix_',
+ *   'collation' => 'utf8_general_ci',
+ * );
+ * @endcode
+ *
+ * The "driver" property indicates what Drupal database driver the
+ * connection should use.  This is usually the same as the name of the
+ * database type, such as mysql or sqlite, but not always.  The other
+ * properties will vary depending on the driver.  For SQLite, you must
+ * specify a database file name in a directory that is writable by the
+ * webserver.  For most other drivers, you must specify a
+ * username, password, host, and database name.
+ *
+ * Transaction support is enabled by default for all drivers that support it,
+ * including MySQL. To explicitly disable it, set the 'transactions' key to
+ * FALSE.
+ * Note that some configurations of MySQL, such as the MyISAM engine, don't
+ * support it and will proceed silently even if enabled. If you experience
+ * transaction related crashes with such configuration, set the 'transactions'
+ * key to FALSE.
+ *
+ * For each database, you may optionally specify multiple "target" databases.
+ * A target database allows Drupal to try to send certain queries to a
+ * different database if it can but fall back to the default connection if not.
+ * That is useful for master/slave replication, as Drupal may try to connect
+ * to a slave server when appropriate and if one is not available will simply
+ * fall back to the single master server.
+ *
+ * The general format for the $databases array is as follows:
+ * @code
+ * $databases['default']['default'] = $info_array;
+ * $databases['default']['slave'][] = $info_array;
+ * $databases['default']['slave'][] = $info_array;
+ * $databases['extra']['default'] = $info_array;
+ * @endcode
+ *
+ * In the above example, $info_array is an array of settings described above.
+ * The first line sets a "default" database that has one master database
+ * (the second level default).  The second and third lines create an array
+ * of potential slave databases.  Drupal will select one at random for a given
+ * request as needed.  The fourth line creates a new database with a name of
+ * "extra".
+ *
+ * For a single database configuration, the following is sufficient:
+ * @code
+ * $databases['default']['default'] = array(
+ *   'driver' => 'mysql',
+ *   'database' => 'databasename',
+ *   'username' => 'username',
+ *   'password' => 'password',
+ *   'host' => 'localhost',
+ *   'prefix' => 'main_',
+ *   'collation' => 'utf8_general_ci',
+ * );
+ * @endcode
+ *
+ * You can optionally set prefixes for some or all database table names
+ * by using the 'prefix' setting. If a prefix is specified, the table
+ * name will be prepended with its value. Be sure to use valid database
+ * characters only, usually alphanumeric and underscore. If no prefixes
+ * are desired, leave it as an empty string ''.
+ *
+ * To have all database names prefixed, set 'prefix' as a string:
+ * @code
+ *   'prefix' => 'main_',
+ * @endcode
+ * To provide prefixes for specific tables, set 'prefix' as an array.
+ * The array's keys are the table names and the values are the prefixes.
+ * The 'default' element is mandatory and holds the prefix for any tables
+ * not specified elsewhere in the array. Example:
+ * @code
+ *   'prefix' => array(
+ *     'default'   => 'main_',
+ *     'users'     => 'shared_',
+ *     'sessions'  => 'shared_',
+ *     'role'      => 'shared_',
+ *     'authmap'   => 'shared_',
+ *   ),
+ * @endcode
+ * You can also use a reference to a schema/database as a prefix. This may be
+ * useful if your Drupal installation exists in a schema that is not the default
+ * or you want to access several databases from the same code base at the same
+ * time.
+ * Example:
+ * @code
+ *   'prefix' => array(
+ *     'default'   => 'main.',
+ *     'users'     => 'shared.',
+ *     'sessions'  => 'shared.',
+ *     'role'      => 'shared.',
+ *     'authmap'   => 'shared.',
+ *   );
+ * @endcode
+ * NOTE: MySQL and SQLite's definition of a schema is a database.
+ *
+ * Advanced users can add or override initial commands to execute when
+ * connecting to the database server, as well as PDO connection settings. For
+ * example, to enable MySQL SELECT queries to exceed the max_join_size system
+ * variable, and to reduce the database connection timeout to 5 seconds:
+ *
+ * @code
+ * $databases['default']['default'] = array(
+ *   'init_commands' => array(
+ *     'big_selects' => 'SET SQL_BIG_SELECTS=1',
+ *   ),
+ *   'pdo' => array(
+ *     PDO::ATTR_TIMEOUT => 5,
+ *   ),
+ * );
+ * @endcode
+ *
+ * WARNING: These defaults are designed for database portability. Changing them
+ * may cause unexpected behavior, including potential data loss.
+ *
+ * @see DatabaseConnection_mysql::__construct
+ * @see DatabaseConnection_pgsql::__construct
+ * @see DatabaseConnection_sqlite::__construct
+ *
+ * Database configuration format:
+ * @code
+ *   $databases['default']['default'] = array(
+ *     'driver' => 'mysql',
+ *     'database' => 'databasename',
+ *     'username' => 'username',
+ *     'password' => 'password',
+ *     'host' => 'localhost',
+ *     'prefix' => '',
+ *   );
+ *   $databases['default']['default'] = array(
+ *     'driver' => 'pgsql',
+ *     'database' => 'databasename',
+ *     'username' => 'username',
+ *     'password' => 'password',
+ *     'host' => 'localhost',
+ *     'prefix' => '',
+ *   );
+ *   $databases['default']['default'] = array(
+ *     'driver' => 'sqlite',
+ *     'database' => '/path/to/databasefilename',
+ *   );
+ * @endcode
+ */
+$databases = array();
+
+/**
+ * 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:
+ * @code
+ *   $config_directories = array(
+ *     CONFIG_ACTIVE_DIRECTORY => '/some/directory/outside/webroot',
+ *     CONFIG_STAGING_DIRECTORY => '/another/directory/outside/webroot',
+ *   );
+ * @endcode
+ */
+$config_directories = array();
+
+/**
+ * Settings:
+ *
+ * $settings contains environment-specific configuration, such as the files
+ * directory and reverse proxy address, and temporary configuration, such as
+ * turning on Twig debugging and security overrides.
+ *
+ * @see \Drupal\Component\Utility\Settings::get()
+ */
+
+/**
+ * Salt for one-time login links, cancel links, form tokens, etc.
+ *
+ * This variable will be set to a random value by the installer. All one-time
+ * login links will be invalidated if the value is changed. Note that if your
+ * site is deployed on a cluster of web servers, you must ensure that this
+ * variable has the same value on each server.
+ *
+ * For enhanced security, you may set this variable to a value using the
+ * contents of a file outside your docroot that is never saved together
+ * with any backups of your Drupal files and database.
+ *
+ * Example:
+ * @code
+ *   $settings['hash_salt'] = file_get_contents('/home/example/salt.txt');
+ * @endcode
+ */
+$settings['hash_salt'] = '';
+
+/**
+ * Access control for update.php script.
+ *
+ * If you are updating your Drupal installation using the update.php script but
+ * are not logged in using either an account with the "Administer software
+ * updates" permission or the site maintenance account (the account that was
+ * created during installation), you will need to modify the access check
+ * statement below. Change the FALSE to a TRUE to disable the access check.
+ * After finishing the upgrade, be sure to open this file again and change the
+ * TRUE back to a FALSE!
+ */
+$settings['update_free_access'] = FALSE;
+
+/**
+ * Twig debugging:
+ *
+ * When debugging is enabled:
+ * - The markup of each Twig template is surrounded by HTML comments that
+ *   contain theming information, such as template file name suggestions.
+ * - Note that this debugging markup will cause automated tests that directly
+ *   check rendered HTML to fail. When running automated tests, 'twig_debug'
+ *   should be set to FALSE.
+ * - The dump() function can be used in Twig templates to output information
+ *   about template variables.
+ * - Twig templates are automatically recompiled whenever the source code
+ *   changes (see twig_auto_reload below).
+ *
+ * For more information about debugging Twig templates, see
+ * http://drupal.org/node/1906392.
+ *
+ * Not recommended in production environments (Default: FALSE).
+ */
+# $settings['twig_debug'] = TRUE;
+
+/**
+ * Twig auto-reload:
+ *
+ * Automatically recompile Twig templates whenever the source code changes. If
+ * you don't provide a value for twig_auto_reload, it will be determined based
+ * on the value of twig_debug.
+ *
+ * Not recommended in production environments (Default: NULL).
+ */
+# $settings['twig_auto_reload'] = TRUE;
+
+/**
+ * Twig cache:
+ *
+ * By default, Twig templates will be compiled and stored in the filesystem to
+ * increase performance. Disabling the Twig cache will recompile the templates
+ * from source each time they are used. In most cases the twig_auto_reload
+ * setting above should be enabled rather than disabling the Twig cache.
+ *
+ * Not recommended in production environments (Default: TRUE).
+ */
+# $settings['twig_cache'] = FALSE;
+
+/**
+ * External access proxy settings:
+ *
+ * If your site must access the Internet via a web proxy then you can enter
+ * the proxy settings here. Currently only basic authentication is supported
+ * by using the username and password variables. The proxy_user_agent variable
+ * can be set to NULL for proxies that require no User-Agent header or to a
+ * non-empty string for proxies that limit requests to a specific agent. The
+ * proxy_exceptions variable is an array of host names to be accessed directly,
+ * not via proxy.
+ */
+# $settings['proxy_server'] = '';
+# $settings['proxy_port'] = 8080;
+# $settings['proxy_username'] = '';
+# $settings['proxy_password'] = '';
+# $settings['proxy_user_agent'] = '';
+# $settings['proxy_exceptions'] = array('127.0.0.1', 'localhost');
+
+/**
+ * Reverse Proxy Configuration:
+ *
+ * Reverse proxy servers are often used to enhance the performance
+ * of heavily visited sites and may also provide other site caching,
+ * security, or encryption benefits. In an environment where Drupal
+ * is behind a reverse proxy, the real IP address of the client should
+ * be determined such that the correct client IP address is available
+ * to Drupal's logging, statistics, and access management systems. In
+ * the most simple scenario, the proxy server will add an
+ * X-Forwarded-For header to the request that contains the client IP
+ * address. However, HTTP headers are vulnerable to spoofing, where a
+ * malicious client could bypass restrictions by setting the
+ * X-Forwarded-For header directly. Therefore, Drupal's proxy
+ * configuration requires the IP addresses of all remote proxies to be
+ * specified in $settings['reverse_proxy_addresses'] to work correctly.
+ *
+ * Enable this setting to get Drupal to determine the client IP from
+ * the X-Forwarded-For header (or $settings['reverse_proxy_header'] if set).
+ * If you are unsure about this setting, do not have a reverse proxy,
+ * or Drupal operates in a shared hosting environment, this setting
+ * should remain commented out.
+ *
+ * In order for this setting to be used you must specify every possible
+ * reverse proxy IP address in $settings['reverse_proxy_addresses'].
+ * If a complete list of reverse proxies is not available in your
+ * environment (for example, if you use a CDN) you may set the
+ * $_SERVER['REMOTE_ADDR'] variable directly in settings.php.
+ * Be aware, however, that it is likely that this would allow IP
+ * address spoofing unless more advanced precautions are taken.
+ */
+# $settings['reverse_proxy'] = TRUE;
+
+/**
+ * Specify every reverse proxy IP address in your environment.
+ * This setting is required if $settings['reverse_proxy'] is TRUE.
+ */
+# $settings['reverse_proxy_addresses'] = array('a.b.c.d', ...);
+
+/**
+ * Set this value if your proxy server sends the client IP in a header
+ * other than X-Forwarded-For.
+ */
+# $settings['reverse_proxy_header'] = 'HTTP_X_CLUSTER_CLIENT_IP';
+
+/**
+ * Page caching:
+ *
+ * By default, Drupal sends a "Vary: Cookie" HTTP header for anonymous page
+ * views. This tells a HTTP proxy that it may return a page from its local
+ * cache without contacting the web server, if the user sends the same Cookie
+ * header as the user who originally requested the cached page. Without "Vary:
+ * Cookie", authenticated users would also be served the anonymous page from
+ * the cache. If the site has mostly anonymous users except a few known
+ * editors/administrators, the Vary header can be omitted. This allows for
+ * better caching in HTTP proxies (including reverse proxies), i.e. even if
+ * clients send different cookies, they still get content served from the cache.
+ * However, authenticated users should access the site directly (i.e. not use an
+ * HTTP proxy, and bypass the reverse proxy if one is used) in order to avoid
+ * getting cached pages from the proxy.
+ */
+# $settings['omit_vary_cookie'] = TRUE;
+
+/**
+ * Class Loader.
+ *
+ * By default, Drupal uses Composer's ClassLoader, which is best for
+ * development, as it does not break when code is moved on the file
+ * system. It is possible, however, to wrap the class loader with a
+ * cached class loader solution for better performance, which is
+ * recommended for production sites.
+ *
+ * Examples:
+ *   $settings['class_loader'] = 'apc';
+ *   $settings['class_loader'] = 'default';
+ */
+# $settings['class_loader'] = 'apc';
+
+/**
+ * Authorized file system operations:
+ *
+ * The Update Manager module included with Drupal provides a mechanism for
+ * site administrators to securely install missing updates for the site
+ * directly through the web user interface. On securely-configured servers,
+ * the Update manager will require the administrator to provide SSH or FTP
+ * credentials before allowing the installation to proceed; this allows the
+ * site to update the new files as the user who owns all the Drupal files,
+ * instead of as the user the webserver is running as. On servers where the
+ * webserver user is itself the owner of the Drupal files, the administrator
+ * will not be prompted for SSH or FTP credentials (note that these server
+ * setups are common on shared hosting, but are inherently insecure).
+ *
+ * Some sites might wish to disable the above functionality, and only update
+ * the code directly via SSH or FTP themselves. This setting completely
+ * disables all functionality related to these authorized file operations.
+ *
+ * @see http://drupal.org/node/244924
+ *
+ * Remove the leading hash signs to disable.
+ */
+# $settings['allow_authorize_operations'] = FALSE;
+
+/**
+ * Mixed-mode sessions:
+ *
+ * Set to TRUE to create both secure and insecure sessions when using HTTPS.
+ * Defaults to FALSE.
+ */
+# $settings['mixed_mode_sessions'] = TRUE;
+
+/**
+ * Default mode for for directories and files written by Drupal.
+ *
+ * Value should be in PHP Octal Notation, with leading zero.
+ */
+# $settings['file_chmod_directory'] = 0775;
+# $settings['file_chmod_file'] = 0664;
+
+/**
+ * Public file path:
+ *
+ * A local file system path where public files will be stored. This directory
+ * must exist and be writable by Drupal. This directory must be relative to
+ * the Drupal installation directory and be accessible over the web.
+ */
+# $settings['file_public_path'] = 'sites/default/files';
+
+/**
+ * Session write interval:
+ *
+ * Set the minimum interval between each session write to database.
+ * For performance reasons it defaults to 180.
+ */
+# $settings['session_write_interval'] = 180;
+
+/**
+ * String overrides:
+ *
+ * To override specific strings on your site with or without enabling the Locale
+ * module, add an entry to this list. This functionality allows you to change
+ * a small number of your site's default English language interface strings.
+ *
+ * Remove the leading hash signs to enable.
+ *
+ * The "en" part of the variable name, is dynamic and can be any langcode of
+ * any enabled language. (eg locale_custom_strings_de for german).
+ */
+# $settings['locale_custom_strings_en'][''] = array(
+#   'forum'      => 'Discussion board',
+#   '@count min' => '@count minutes',
+# );
+
+/**
+ * A custom theme for the offline page:
+ *
+ * This applies when the site is explicitly set to maintenance mode through the
+ * administration page or when the database is inactive due to an error.
+ * The template file should also be copied into the theme. It is located inside
+ * 'core/modules/system/templates/maintenance-page.html.twig'.
+ *
+ * Note: This setting does not apply to installation and update pages.
+ */
+# $settings['maintenance_theme'] = 'bartik';
+
+/**
+ * Enable access to rebuild.php.
+ *
+ * This setting can be enabled to allow Drupal's php and database cached
+ * storage to be cleared via the rebuild.php page. Access to this page can also
+ * be gained by generating a query string from rebuild_token_calculator.sh and
+ * using these parameters in a request to rebuild.php.
+ */
+# $settings['rebuild_access'] = TRUE;
+
+/**
+ * Base URL (optional).
+ *
+ * If Drupal is generating incorrect URLs on your site, which could
+ * be in HTML headers (links to CSS and JS files) or visible links on pages
+ * (such as in menus), uncomment the Base URL statement below (remove the
+ * leading hash sign) and fill in the absolute URL to your Drupal installation.
+ *
+ * You might also want to force users to use a given domain.
+ * See the .htaccess file for more information.
+ *
+ * Examples:
+ *   $base_url = 'http://www.example.com';
+ *   $base_url = 'http://www.example.com:8888';
+ *   $base_url = 'http://www.example.com/drupal';
+ *   $base_url = 'https://www.example.com:8888/drupal';
+ *
+ * It is not allowed to have a trailing slash; Drupal will add it
+ * for you.
+ */
+# $base_url = 'http://www.example.com';  // NO trailing slash!
+
+/**
+ * PHP settings:
+ *
+ * To see what PHP settings are possible, including whether they can be set at
+ * runtime (by using ini_set()), read the PHP documentation:
+ * http://php.net/manual/ini.list.php
+ * See drupal_environment_initialize() in core/includes/bootstrap.inc for
+ * required runtime settings and the .htaccess file for non-runtime settings.
+ * Settings defined there should not be duplicated here so as to avoid conflict
+ * issues.
+ */
+
+/**
+ * Some distributions of Linux (most notably Debian) ship their PHP
+ * installations with garbage collection (gc) disabled. Since Drupal depends on
+ * PHP's garbage collection for clearing sessions, ensure that garbage
+ * collection occurs by using the most common settings.
+ */
+ini_set('session.gc_probability', 1);
+ini_set('session.gc_divisor', 100);
+
+/**
+ * Set session lifetime (in seconds), i.e. the time from the user's last visit
+ * to the active session may be deleted by the session garbage collector. When
+ * a session is deleted, authenticated users are logged out, and the contents
+ * of the user's $_SESSION variable is discarded.
+ */
+ini_set('session.gc_maxlifetime', 200000);
+
+/**
+ * Set session cookie lifetime (in seconds), i.e. the time from the session is
+ * created to the cookie expires, i.e. when the browser is expected to discard
+ * the cookie. The value 0 means "until the browser is closed".
+ */
+ini_set('session.cookie_lifetime', 2000000);
+
+/**
+ * If you encounter a situation where users post a large amount of text, and
+ * the result is stripped out upon viewing but can still be edited, Drupal's
+ * output filter may not have sufficient memory to process it.  If you
+ * experience this issue, you may wish to uncomment the following two lines
+ * and increase the limits of these variables.  For more information, see
+ * http://php.net/manual/pcre.configuration.php.
+ */
+# ini_set('pcre.backtrack_limit', 200000);
+# ini_set('pcre.recursion_limit', 200000);
+
+/**
+ * Drupal automatically generates a unique session cookie name for each site
+ * based on its full domain name. If you have multiple domains pointing at the
+ * same Drupal site, you can either redirect them all to a single domain (see
+ * comment in .htaccess), or uncomment the line below and specify their shared
+ * base domain. Doing so assures that users remain logged in as they cross
+ * between your various domains. Make sure to always start the $cookie_domain
+ * with a leading dot, as per RFC 2109.
+ */
+# $cookie_domain = '.example.com';
+
+/**
+ * Configuration overrides.
+ *
+ * To globally override specific configuration values for this site,
+ * set them here. You usually don't need to use this feature. This is
+ * useful in a configuration file for a vhost or directory, rather than
+ * the default settings.php.
+ *
+ * Note that any values you provide in these variable overrides will not be
+ * modifiable from the Drupal administration interface.
+ */
+# $config['system.site']['name'] = 'My Drupal site';
+# $config['system.theme']['default'] = 'stark';
+# $config['user.settings']['anonymous'] = 'Visitor';
+
+/**
+ * CSS/JS aggregated file gzip compression:
+ *
+ * By default, when CSS or JS aggregation and clean URLs are enabled Drupal will
+ * store a gzip compressed (.gz) copy of the aggregated files. If this file is
+ * available then rewrite rules in the default .htaccess file will serve these
+ * files to browsers that accept gzip encoded content. This allows pages to load
+ * faster for these users and has minimal impact on server load. If you are
+ * using a webserver other than Apache httpd, or a caching reverse proxy that is
+ * configured to cache and compress these files itself you may want to uncomment
+ * one or both of the below lines, which will prevent gzip files being stored.
+ */
+# $config['system.performance']['css']['gzip'] = FALSE;
+# $config['system.performance']['js']['gzip'] = FALSE;
+
+/**
+ * Fast 404 pages:
+ *
+ * Drupal can generate fully themed 404 pages. However, some of these responses
+ * are for images or other resource files that are not displayed to the user.
+ * This can waste bandwidth, and also generate server load.
+ *
+ * The options below return a simple, fast 404 page for URLs matching a
+ * specific pattern:
+ * - $conf['system.performance]['fast_404']['exclude_paths']: A regular
+ *   expression to match paths to exclude, such as images generated by image
+ *   styles, or dynamically-resized images. If you need to add more paths, you
+ *   can add '|path' to the expression.
+ * - $conf['system.performance]['fast_404']['paths']: A regular expression to
+ *   match paths that should return a simple 404 page, rather than the fully
+ *   themed 404 page. If you don't have any aliases ending in htm or html you
+ *   can add '|s?html?' to the expression.
+ * - $conf['system.performance]['fast_404']['html']: The html to return for
+ *   simple 404 pages.
+ *
+ * Remove the leading hash signs if you would like to alter this functionality.
+ */
+# $config['system.performance']['fast_404']['exclude_paths'] = '/\/(?:styles)\//';
+# $config['system.performance']['fast_404']['paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i';
+# $config['system.performance']['fast_404']['html'] = '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>';
+
+/**
+ * Load local development override configuration, if available.
+ *
+ * Use settings.local.php to override variables on secondary (staging,
+ * development, etc) installations of this site. Typically used to disable
+ * caching, JavaScript/CSS compression, re-routing of outgoing e-mails, and
+ * other things that should not happen on development and testing sites.
+ *
+ * Keep this code block at the end of this file to take full effect.
+ */
+# if (file_exists(DRUPAL_ROOT . '/' . $conf_path . '/settings.local.php')) {
+#   include DRUPAL_ROOT . '/' . $conf_path . '/settings.local.php';
+# }
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 8f78e26..8c4073d 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -10,6 +10,7 @@
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Database\Database;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Site\Site;
 use Drupal\Core\Utility\Title;
 use Drupal\Core\Utility\Error;
 use Symfony\Component\ClassLoader\ApcClassLoader;
@@ -218,116 +219,6 @@
 define('DRUPAL_ROOT', dirname(dirname(__DIR__)));
 
 /**
- * Returns the appropriate configuration directory.
- *
- * Returns the configuration path based on the site's hostname, port, and
- * pathname. Uses find_conf_path() to find the current configuration directory.
- * See default.settings.php for examples on how the URL is converted to a
- * directory.
- *
- * @param bool $require_settings
- *   Only configuration directories with an existing settings.php file
- *   will be recognized. Defaults to TRUE. During initial installation,
- *   this is set to FALSE so that Drupal can detect a matching directory,
- *   then create a new settings.php file in it.
- * @param bool $reset
- *   Force a full search for matching directories even if one had been
- *   found previously. Defaults to FALSE.
- *
- * @return
- *   The path of the matching directory.
- *
- * @see default.settings.php
- */
-function conf_path($require_settings = TRUE, $reset = FALSE) {
-  static $conf_path;
-
-  if (isset($conf_path) && !$reset) {
-    return $conf_path;
-  }
-
-  // Check for a simpletest override.
-  if ($test_prefix = drupal_valid_test_ua()) {
-    $conf_path = 'sites/simpletest/' . substr($test_prefix, 10);
-    return $conf_path;
-  }
-
-  // Otherwise, use the normal $conf_path.
-  $script_name = $_SERVER['SCRIPT_NAME'];
-  if (!$script_name) {
-    $script_name = $_SERVER['SCRIPT_FILENAME'];
-  }
-  $http_host = $_SERVER['HTTP_HOST'];
-  $conf_path = find_conf_path($http_host, $script_name, $require_settings);
-  return $conf_path;
-}
-
-/**
- * Finds the appropriate configuration directory for a given host and path.
- *
- * Finds a matching configuration directory file by stripping the website's
- * hostname from left to right and pathname from right to left. By default,
- * the directory must contain a 'settings.php' file for it to match. If the
- * parameter $require_settings is set to FALSE, then a directory without a
- * 'settings.php' file will match as well. The first configuration
- * file found will be used and the remaining ones will be ignored. If no
- * configuration file is found, returns a default value '$confdir/default'. See
- * default.settings.php for examples on how the URL is converted to a directory.
- *
- * If a file named sites.php is present in the $confdir, it will be loaded
- * prior to scanning for directories. That file can define aliases in an
- * associative array named $sites. The array is written in the format
- * '<port>.<domain>.<path>' => 'directory'. As an example, to create a
- * directory alias for http://www.drupal.org:8080/mysite/test whose configuration
- * file is in sites/example.com, the array should be defined as:
- * @code
- * $sites = array(
- *   '8080.www.drupal.org.mysite.test' => 'example.com',
- * );
- * @endcode
- *
- * @param $http_host
- *   The hostname and optional port number, e.g. "www.example.com" or
- *   "www.example.com:8080".
- * @param $script_name
- *   The part of the URL following the hostname, including the leading slash.
- * @param $require_settings
- *   Defaults to TRUE. If TRUE, then only match directories with a
- *   'settings.php' file. Otherwise match any directory.
- *
- * @return
- *   The path of the matching configuration directory.
- *
- * @see default.settings.php
- * @see example.sites.php
- * @see conf_path()
- */
-function find_conf_path($http_host, $script_name, $require_settings = TRUE) {
-  // Determine whether multi-site functionality is enabled.
-  if (!file_exists(DRUPAL_ROOT . '/sites/sites.php')) {
-    return 'sites/default';
-  }
-
-  $sites = array();
-  include DRUPAL_ROOT . '/sites/sites.php';
-
-  $uri = explode('/', $script_name);
-  $server = explode('.', implode('.', array_reverse(explode(':', rtrim($http_host, '.')))));
-  for ($i = count($uri) - 1; $i > 0; $i--) {
-    for ($j = count($server); $j > 0; $j--) {
-      $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
-      if (isset($sites[$dir]) && file_exists(DRUPAL_ROOT . '/sites/' . $sites[$dir])) {
-        $dir = $sites[$dir];
-      }
-      if (file_exists(DRUPAL_ROOT . '/sites/' . $dir . '/settings.php') || (!$require_settings && file_exists(DRUPAL_ROOT . '/sites/' . $dir))) {
-        return "sites/$dir";
-      }
-    }
-  }
-  return 'sites/default';
-}
-
-/**
  * Returns the path of a configuration directory.
  *
  * @param string $type
@@ -378,7 +269,7 @@ function config_get_config_directory($type = CONFIG_ACTIVE_DIRECTORY) {
  *   excluding any GET request but including the script name
  *   (e.g., http://www.example.com/mysite/index.php).
  *
- * @see conf_path()
+ * @see \Drupal\Core\Site\Site::getPath()
  * @see request_uri()
  * @see \Symfony\Component\HttpFoundation\Request::getClientIP()
  */
@@ -411,7 +302,7 @@ function drupal_override_server_variables($variables = array()) {
   // Replace elements of the $_SERVER array, as appropriate.
   $request->server->replace($variables + $server_vars + $defaults);
 
-  // @todo remove once conf_path() no longer uses $_SERVER.
+  // @todo remove once Site::determinePath() no longer uses $_SERVER.
   $_SERVER = $request->server->all();
 }
 
@@ -450,7 +341,7 @@ function drupal_environment_initialize() {
   error_reporting(E_STRICT | E_ALL | error_reporting());
 
   // Override PHP settings required for Drupal to work properly.
-  // sites/default/default.settings.php contains more runtime settings.
+  // settings.php contains more runtime settings.
   // The .htaccess file contains settings that cannot be changed at runtime.
 
   // Use session cookies, not transparent sessions that puts the session id in
@@ -488,9 +379,23 @@ function drupal_settings_initialize() {
   $settings = array();
   $config = array();
 
-  // Make conf_path() available as local variable in settings.php.
-  $conf_path = conf_path();
-  if (is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) {
+  // Read the global /settings.php file.
+  // Allow it to set/override the following variables:
+  $sites = NULL;
+  $conf_path = NULL;
+  // Exclude it for test requests to prevent settings of the test runner from
+  // leaking into the test environment.
+  if (!drupal_valid_test_ua() && is_readable(DRUPAL_ROOT . '/settings.php')) {
+    require DRUPAL_ROOT . '/settings.php';
+  }
+
+  // Discover the site directory.
+  Site::init(DRUPAL_ROOT, $sites, $conf_path);
+
+  // Read settings.php of the actual site, unless it is the root/default site.
+  // Concatenation is safe here, since $conf_path is known to be not empty.
+  $conf_path = Site::getPath();
+  if ($conf_path !== '' && is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) {
     require DRUPAL_ROOT . '/' . $conf_path . '/settings.php';
   }
   // Initialize Settings.
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 1f88d4a..54c1ec5 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -12,6 +12,7 @@
 use Drupal\Core\Database\Install\TaskException;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\Site\Site;
 use Drupal\Core\StringTranslation\Translator\FileTranslation;
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
@@ -270,12 +271,6 @@ function install_begin_request(&$install_state) {
     drupal_override_server_variables($install_state['server']);
   }
 
-  // Initialize conf_path().
-  // This primes the site path to be used during installation. By not requiring
-  // settings.php, a bare site folder can be prepared in the /sites directory,
-  // which will be used for installing Drupal.
-  conf_path(FALSE);
-
   // If the hash salt leaks, it becomes possible to forge a valid testing user
   // agent, install a new copy of Drupal, and take over the original site.
   // The user agent header is used to pass a database prefix in the request when
@@ -286,7 +281,21 @@ function install_begin_request(&$install_state) {
     exit;
   }
 
+  // Initialize the Site directory.
+  // This primes the site path to be used during installation, to allow a bare
+  // site folder to be prepared in the /sites directory, which will be used for
+  // installing Drupal.
+  Site::initInstaller(DRUPAL_ROOT);
+
+  // Bootstrap the minimal base system.
+  // drupal_settings_initialize() MUST be called. If the non-interactive
+  // installer is invoked from a test, then it is not, because Drupal has a
+  // bootstrapped to a later phase already.
+  $current_phase = drupal_get_bootstrap_phase();
   drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+  if ($current_phase > DRUPAL_BOOTSTRAP_CONFIGURATION) {
+    drupal_settings_initialize();
+  }
 
   // Ensure that procedural dependencies are loaded as early as possible,
   // since the error/exception handlers depend on them.
@@ -1078,8 +1087,7 @@ function install_verify_database_settings() {
   global $databases;
   if (!empty($databases)) {
     $database = $databases['default']['default'];
-    $settings_file = './' . conf_path(FALSE) . '/settings.php';
-    $errors = install_database_errors($database, $settings_file);
+    $errors = install_database_errors($database);
     if (empty($errors)) {
       return TRUE;
     }
@@ -1100,9 +1108,6 @@ function install_verify_database_settings() {
 function install_settings_form($form, &$form_state, &$install_state) {
   global $databases;
 
-  $conf_path = './' . conf_path(FALSE);
-  $settings_file = $conf_path . '/settings.php';
-
   drupal_set_title(t('Database configuration'));
 
   $drivers = drupal_get_database_types();
@@ -1171,7 +1176,6 @@ function install_settings_form($form, &$form_state, &$install_state) {
   );
 
   $form['errors'] = array();
-  $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file);
 
   return $form;
 }
@@ -1192,7 +1196,7 @@ function install_settings_form_validate($form, &$form_state) {
   $database['driver'] = $driver;
 
   $form_state['storage']['database'] = $database;
-  $errors = install_database_errors($database, $form_state['values']['settings_file']);
+  $errors = install_database_errors($database);
   foreach ($errors as $name => $message) {
     form_set_error($name, $form_state, $message);
   }
@@ -1201,7 +1205,7 @@ function install_settings_form_validate($form, &$form_state) {
 /**
  * Checks a database connection and returns any errors.
  */
-function install_database_errors($database, $settings_file) {
+function install_database_errors($database) {
   global $databases;
   $errors = array();
 
@@ -1209,7 +1213,11 @@ function install_database_errors($database, $settings_file) {
   $database_types = drupal_get_database_types();
   $driver = $database['driver'];
   if (!isset($database_types[$driver])) {
-    $errors['driver'] = t("In your %settings_file file you have configured @drupal to use a %driver server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '@drupal' => drupal_install_profile_distribution_name(), '%driver' => $driver));
+    $errors['driver'] = t("In your %settings_file file you have configured @drupal to use a %driver server, however your PHP installation currently does not support this database type.", array(
+      '%settings_file' => Site::getPath('settings.php'),
+      '@drupal' => drupal_install_profile_distribution_name(),
+      '%driver' => $driver,
+    ));
   }
   else {
     // Run driver specific validation
@@ -1485,7 +1493,7 @@ function install_translations_directory() {
     $directory = $GLOBALS['conf']['locale.settings']['translation.path'];
   }
   else {
-    $directory = conf_path() . '/files/translations';
+    $directory = Site::getPath('files/translations');
   }
   return $directory;
 }
@@ -2062,8 +2070,8 @@ function install_configure_form($form, &$form_state, &$install_state) {
   drupal_set_title(t('Configure site'));
 
   // Warn about settings.php permissions risk
-  $settings_dir = conf_path();
-  $settings_file = $settings_dir . '/settings.php';
+  $settings_dir = Site::getPath();
+  $settings_file = Site::getPath('settings.php');
   // Check that $_POST is empty so we only show this message when the form is
   // first displayed, not on the next page after it is submitted. (We do not
   // want to repeat it multiple times because it is a general warning that is
@@ -2072,7 +2080,7 @@ function install_configure_form($form, &$form_state, &$install_state) {
   // distract from the message that the Drupal installation has completed
   // successfully.)
   $post_params = \Drupal::request()->request->all();
-  if (empty($post_params) && (!drupal_verify_install_file(DRUPAL_ROOT . '/' . $settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE) || !drupal_verify_install_file(DRUPAL_ROOT . '/' . $settings_dir, FILE_NOT_WRITABLE, 'dir'))) {
+  if (empty($post_params) && (!drupal_verify_install_file(Site::getAbsolutePath('settings.php'), FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE) || !drupal_verify_install_file(Site::getAbsolutePath(), FILE_NOT_WRITABLE, 'dir'))) {
     drupal_set_message(t('All necessary changes to %dir and %file have been made, so you should remove write permissions to them now in order to avoid security risks. If you are unsure how to do so, consult the <a href="@handbook_url">online handbook</a>.', array('%dir' => $settings_dir, '%file' => $settings_file, '@handbook_url' => 'http://drupal.org/server-permissions')), 'warning');
   }
 
@@ -2218,8 +2226,8 @@ function install_check_translations($install_state) {
   $readable = FALSE;
   $writable = FALSE;
   // @todo: Make this configurable.
-  $files_directory = conf_path() . '/files';
-  $translations_directory = conf_path() . '/files/translations';
+  $files_directory = Site::getPath('files');
+  $translations_directory = Site::getPath('files/translations');
   $translations_directory_exists = FALSE;
   $translation_available = FALSE;
   $online = FALSE;
@@ -2372,15 +2380,13 @@ function install_check_requirements($install_state) {
   if (!$install_state['settings_verified']) {
     $readable = FALSE;
     $writable = FALSE;
-    $conf_path = './' . conf_path(FALSE);
-    $settings_file = $conf_path . '/settings.php';
-    $default_settings_file = './sites/default/default.settings.php';
-    $file = $conf_path;
+    $settings_file = Site::getAbsolutePath('settings.php');
+    $default_settings_file = './core/default.settings.php';
+    $file = Site::getPath('settings.php');
     $exists = FALSE;
     // Verify that the directory exists.
-    if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) {
+    if (drupal_verify_install_file(Site::getAbsolutePath(), FILE_EXIST, 'dir')) {
       // Check if a settings.php file already exists.
-      $file = $settings_file;
       if (drupal_verify_install_file($settings_file, FILE_EXIST)) {
         // If it does, make sure it is writable.
         $readable = drupal_verify_install_file($settings_file, FILE_READABLE);
@@ -2389,20 +2395,11 @@ function install_check_requirements($install_state) {
       }
     }
 
-    // If default.settings.php does not exist, or is not readable, throw an
-    // error.
-    if (!drupal_verify_install_file($default_settings_file, FILE_EXIST|FILE_READABLE)) {
-      $requirements['default settings file exists'] = array(
-        'title'       => t('Default settings file'),
-        'value'       => t('The default settings file does not exist.'),
-        'severity'    => REQUIREMENT_ERROR,
-        'description' => t('The @drupal installer requires that the %default-file file not be modified in any way from the original download.', array('@drupal' => drupal_install_profile_distribution_name(), '%default-file' => $default_settings_file)),
-      );
-    }
     // Otherwise, if settings.php does not exist yet, we can try to copy
     // default.settings.php to create it.
-    elseif (!$exists) {
-      $copied = drupal_verify_install_file($conf_path, FILE_EXIST|FILE_WRITABLE, 'dir') && @copy($default_settings_file, $settings_file);
+    if (!$exists) {
+      $copied = drupal_verify_install_file(Site::getAbsolutePath(), FILE_EXIST|FILE_WRITABLE, 'dir');
+      $copied = $copied && @copy($default_settings_file, $settings_file);
       if ($copied) {
         // If the new settings file has the same owner as default.settings.php,
         // this means default.settings.php is owned by the webserver user.
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 4374ae8..f7f37fd 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\Settings;
 use Drupal\Core\Database\Database;
 use Drupal\Core\DrupalKernel;
+use Drupal\Core\Site\Site;
 
 /**
  * Requirement severity -- Informational message only.
@@ -196,7 +197,7 @@ function drupal_get_database_types() {
  */
 function drupal_rewrite_settings($settings = array(), $settings_file = NULL) {
   if (!isset($settings_file)) {
-    $settings_file = conf_path(FALSE) . '/settings.php';
+    $settings_file = Site::getPath('settings.php');
   }
   // Build list of setting names and insert the values into the global namespace.
   $variable_names = array();
@@ -460,11 +461,11 @@ function drupal_install_config_directories() {
     $config_directories_hash = Crypt::randomBytesBase64(55);
     $settings['config_directories'] = array(
       CONFIG_ACTIVE_DIRECTORY => (object) array(
-        'value' => conf_path() . '/files/config_' . $config_directories_hash . '/active',
+        'value' => Site::getPath('files/config_' . $config_directories_hash . '/active'),
         'required' => TRUE,
       ),
       CONFIG_STAGING_DIRECTORY => (object) array(
-        'value' => conf_path() . '/files/config_' . $config_directories_hash . '/staging',
+        'value' => Site::getPath('files/config_' . $config_directories_hash . '/staging'),
         'required' => TRUE,
       ),
     );
diff --git a/core/includes/update.inc b/core/includes/update.inc
index 3431886..ebf5839 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -14,6 +14,7 @@
 use Drupal\Core\Config\FileStorage;
 use Drupal\Core\Config\ConfigException;
 use Drupal\Core\DrupalKernel;
+use Drupal\Core\Site\Site;
 use Drupal\Core\Utility\Error;
 use Drupal\Component\Uuid\Uuid;
 use Drupal\Component\Utility\NestedArray;
@@ -81,7 +82,7 @@ function update_settings_file_requirements() {
   $requirements = array();
 
   // Check whether settings.php needs to be rewritten.
-  $settings_file = conf_path() . '/settings.php';
+  $settings_file = Site::getPath('settings.php');
   $writable = drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_WRITABLE);
   $requirements['settings file']['title'] = 'Settings file';
   if ($writable) {
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
index 97eab54..995f0e6 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Database\Driver\sqlite\Connection;
 use Drupal\Core\Database\DatabaseNotFoundException;
 use Drupal\Core\Database\Install\Tasks as InstallTasks;
+use Drupal\Core\Site\Site;
 
 /**
  * Specifies installation tasks for SQLite databases.
@@ -49,7 +50,7 @@ public function getFormOptions(array $database) {
     // Make the text more accurate for SQLite.
     $form['database']['#title'] = t('Database file');
     $form['database']['#description'] = t('The absolute path to the file where @drupal data will be stored. This must be writable by the web server and should exist outside of the web root.', array('@drupal' => drupal_install_profile_distribution_name()));
-    $default_database = conf_path(FALSE) . '/files/.ht.sqlite';
+    $default_database = Site::getPath('files/.ht.sqlite');
     $form['database']['#default_value'] = empty($database['database']) ? $default_database : $database['database'];
     return $form;
   }
diff --git a/core/lib/Drupal/Core/Site/Site.php b/core/lib/Drupal/Core/Site/Site.php
new file mode 100644
index 0000000..ff9f158
--- /dev/null
+++ b/core/lib/Drupal/Core/Site/Site.php
@@ -0,0 +1,341 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Site\Site.
+ */
+
+namespace Drupal\Core\Site;
+
+/**
+ * A utility class for easy access to the site path.
+ */
+class Site {
+
+  /**
+   * The absolute path to the Drupal root directory.
+   *
+   * @var string
+   */
+  private $root;
+
+  /**
+   * The relative path to the site directory.
+   *
+   * May be an empty string, in case the site directory is the root directory.
+   *
+   * @var string
+   */
+  private $path;
+
+  /**
+   * Whether the Site singleton was instantiated by the installer.
+   *
+   * @var bool
+   */
+  private $isInstaller = FALSE;
+
+  /**
+   * The original Site instance of the test runner during test execution.
+   *
+   * @see \Drupal\Core\Site\Site::setUpTest()
+   * @see \Drupal\Core\Site\Site::tearDownTest()
+   *
+   * @var \Drupal\Core\Site\Site
+   */
+  private static $original;
+
+  /**
+   * The Site singleton instance.
+   *
+   * @var \Drupal\Core\Site\Site
+   */
+  private static $instance;
+
+  /**
+   * Initializes the Site singleton.
+   *
+   * @param string $root_directory
+   *   The root directory to use for absolute paths; i.e., DRUPAL_ROOT.
+   * @param array $sites
+   *   (optional) A multi-site mapping, as defined in settings.php.
+   * @param string $custom_path
+   *   (optional) An explicit site path to set; skipping site negotiation.
+   *   This can be defined as $conf_path in the root /settings.php file.
+   *
+   * @see drupal_settings_initialize()
+   */
+  public static function init($root_directory, array $sites = NULL, $custom_path = NULL) {
+    if (isset(self::$instance)) {
+      // Only the installer environment is allowed to instantiate the Site
+      // singleton prior to drupal_settings_initialize().
+      // @see Site::initInstaller()
+      if (!self::$instance->isInstaller()) {
+        throw new \BadMethodCallException('Site path is initialized already.');
+      }
+    }
+    else {
+      new self($root_directory);
+    }
+    self::$instance->initializePath($sites, $custom_path);
+
+    // Prevent this method from being called more than once.
+    if (self::$instance->isInstaller()) {
+      self::$instance->isInstaller = FALSE;
+    }
+  }
+
+  /**
+   * Initializes the Site singleton for the early installer environment.
+   *
+   * The installer uses this function to prime the site directory path very
+   * early in the installer environment. This allows the application to be
+   * installed into a new and empty site directory, which does not contain a
+   * settings.php yet.
+   *
+   * @param string $root_directory
+   *   The root directory to use for absolute paths; i.e., DRUPAL_ROOT.
+   *
+   * @see install_begin_request()
+   */
+  public static function initInstaller($root_directory) {
+    if (isset(self::$instance)) {
+      throw new \BadMethodCallException('Site path is initialized already.');
+    }
+    new self($root_directory);
+    // Denote that we are operating in the special installer environment.
+    self::$instance->isInstaller = TRUE;
+  }
+
+  /**
+   * Constructs the Site singleton.
+   */
+  private function __construct($root_directory) {
+    if (isset(self::$instance)) {
+      throw new \BadMethodCallException('Site path is initialized already.');
+    }
+    $this->root = $root_directory;
+    self::$instance = $this;
+  }
+
+  /**
+   * Re-initializes (resets) the Site singleton for a test run.
+   *
+   * @see \Drupal\simpletest\TestBase::prepareEnvironment()
+   */
+  public static function setUpTest() {
+    if (!isset(self::$instance)) {
+      throw new \RuntimeException('No original Site to backup. Missing invocation of Site::init()?');
+    }
+    if (!drupal_valid_test_ua()) {
+      throw new \BadMethodCallException('Site is not executing a test.');
+    }
+    self::$original = clone self::$instance;
+    self::$instance = NULL;
+  }
+
+  /**
+   * Reverts the Site singleton to the original after a test run.
+   *
+   * @see \Drupal\simpletest\TestBase::restoreEnvironment()
+   */
+  public static function tearDownTest() {
+    if (!isset(self::$original)) {
+      throw new \RuntimeException('No original Site to revert to. Missing invocation of Site::setUpTest()?');
+    }
+    // Do not allow to restore original Site singleton in a test environment,
+    // unless we are testing the test environment setup and teardown itself.
+    // @see \Drupal\simpletest\Tests\BrokenSetUpTest
+    if (drupal_valid_test_ua() && !DRUPAL_TEST_IN_CHILD_SITE) {
+      throw new \BadMethodCallException('Unable to revert Site: A test is still being executed.');
+    }
+    self::$instance = clone self::$original;
+    self::$original = NULL;
+  }
+
+  /**
+   * Returns whether the Site singleton was instantiated for the installer.
+   */
+  private function isInstaller() {
+    return $this->isInstaller;
+  }
+
+  /**
+   * Initializes the site path.
+   *
+   * @param array $sites
+   *   (optional) A multi-site mapping, as defined in settings.php.
+   * @param string $custom_path
+   *   (optional) An explicit site path to set; skipping site negotiation.
+   */
+  private function initializePath(array $sites = NULL, $custom_path = NULL) {
+    // Force-override the site directory in tests.
+    if ($test_prefix = drupal_valid_test_ua()) {
+      $this->path = 'sites/simpletest/' . substr($test_prefix, 10);
+    }
+    // An explicitly defined $conf_path in /settings.php takes precedence.
+    elseif (isset($custom_path)) {
+      $this->path = $custom_path;
+    }
+    // If the multi-site functionality was enabled in /settings.php, discover
+    // the path for the current site.
+    // $sites just needs to be defined; an explicit mapping is not required.
+    elseif (isset($sites)) {
+      $this->path = $this->determinePath($sites, !$this->isInstaller());
+    }
+    // If the multi-site functionality is not enabled, the Drupal root
+    // directory is the site directory.
+    else {
+      $this->path = '';
+    }
+  }
+
+  /**
+   * Finds the appropriate configuration directory for a given host and path.
+   *
+   * Finds a matching configuration directory file by stripping the website's
+   * hostname from left to right and pathname from right to left. By default,
+   * the directory must contain a 'settings.php' file for it to match. If the
+   * parameter $require_settings is set to FALSE, then a directory without a
+   * 'settings.php' file will match as well. The first configuration
+   * file found will be used and the remaining ones will be ignored.
+   *
+   * The settings.php file can define aliases in an associative array named
+   * $sites. For example, to create a directory alias for
+   * http://www.drupal.org:8080/mysite/test whose configuration file is in
+   * sites/example.com, the array should be defined as:
+   * @code
+   * $sites = array(
+   *   '8080.www.drupal.org.mysite.test' => 'example.com',
+   * );
+   * @endcode
+   *
+   * @see default.settings.php
+   *
+   * @param array $sites
+   *   A multi-site mapping, as defined in settings.php.
+   * @param bool $require_settings
+   *   Only configuration directories with an existing settings.php file
+   *   will be recognized. Defaults to TRUE. During initial installation,
+   *   this is set to FALSE so that Drupal can detect a matching directory,
+   *   then create a new settings.php file in it.
+   *
+   * @return string
+   *   The path of the matching configuration directory. May be an empty string,
+   *   in case the site configuration directory is the root directory.
+   */
+  private function determinePath(array $sites, $require_settings) {
+    // The hostname and optional port number, e.g. "www.example.com" or
+    // "www.example.com:8080".
+    $http_host = $_SERVER['HTTP_HOST'];
+    // The part of the URL following the hostname, including the leading slash.
+    $script_name = $_SERVER['SCRIPT_NAME'] ?: $_SERVER['SCRIPT_FILENAME'];
+
+    $uri = explode('/', $script_name);
+    $server = explode('.', implode('.', array_reverse(explode(':', rtrim($http_host, '.')))));
+    for ($i = count($uri) - 1; $i > 0; $i--) {
+      for ($j = count($server); $j > 0; $j--) {
+        $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
+        // Check for an alias in $sites from settings.php.
+        if (isset($sites[$dir])) {
+          $dir = $sites[$dir];
+        }
+        if ($require_settings) {
+          if (file_exists($this->root . '/sites/' . $dir . '/settings.php')) {
+            return "sites/$dir";
+          }
+        }
+        elseif (file_exists($this->root . '/sites/' . $dir)) {
+          return "sites/$dir";
+        }
+      }
+    }
+    return '';
+  }
+
+  /**
+   * Prefixes a given filepath with the site directory, if any.
+   *
+   * Site::getPath() and this helper method only exists to ensure that a given
+   * filepath does not result in an absolute filesystem path in case of a string
+   * concatenation like the following:
+   *
+   * @code
+   * // If the sire directory path is empty (root directory), then the resulting
+   * // filesystem path would become absolute; i.e.: "/some/file"
+   * unlink($site_path . '/some/file');
+   * @endcode
+   *
+   * In case the PHP process has write access to the entire filesystem, such a
+   * file operation could succeed and potentially affect arbitrary other files
+   * and directories that happen to exist. That must not happen.
+   *
+   * @param string $filepath
+   *   The filepath to prefix.
+   *
+   * @return string
+   *   The prefixed filepath.
+   */
+  private function resolvePath($filepath) {
+    // Extra safety protection in case a script somehow manages to bypass all
+    // other protections.
+    if (!isset($this->path)) {
+      throw new \RuntimeException('Site path is not initialized yet.');
+    }
+    // A faulty call to Site::getPath() might include a leading slash (/), in
+    // which case the entire site path resolution of this function would be
+    // pointless, because the resulting path would still be absolute. Therefore,
+    // guarantee that even a bogus argument is resolved correctly.
+    $filepath = ltrim($filepath, '/');
+
+    if ($this->path !== '') {
+      if ($filepath !== '') {
+        return $this->path . '/' . $filepath;
+      }
+      return $this->path;
+    }
+    return $filepath;
+  }
+
+  /**
+   * Returns a given path as relative path to the site directory.
+   *
+   * Use this function instead of appending strings to the site path manually,
+   * because the site directory may be the root directory and thus the resulting
+   * path would be an absolute filesystem path.
+   *
+   * @param string $filepath
+   *   (optional) A relative filepath to append to the site path.
+   *
+   * @return string
+   *   The given $filepath, potentially prefixed with the site path.
+   *
+   * @see \Drupal\Core\Site\Site::getAbsolutePath()
+   */
+  public static function getPath($filepath = '') {
+    return self::$instance->resolvePath($filepath);
+  }
+
+  /**
+   * Returns a given path as absolute path in the site directory.
+   *
+   * @param string $filepath
+   *   (optional) A relative filepath to append to the site path.
+   *
+   * @return string
+   *   The given $filepath, potentially prefixed with the site path, as an
+   *   absolute filesystem path.
+   *
+   * @see \Drupal\Core\Site\Site::getPath()
+   */
+  public static function getAbsolutePath($filepath = '') {
+    $filepath = self::$instance->resolvePath($filepath);
+    if ($filepath !== '') {
+      return self::$instance->root . '/' . $filepath;
+    }
+    else {
+      return self::$instance->root;
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
index 760a1f8..a2239ff 100644
--- a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
+++ b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Core\StreamWrapper;
 
+use Drupal\Core\Site\Site;
+
 /**
  * Defines a Drupal public (public://) stream wrapper class.
  *
@@ -37,7 +39,7 @@ public function getExternalUrl() {
    *   The base path for public:// typically sites/default/files.
    */
   public static function basePath() {
-    $base_path = settings()->get('file_public_path', conf_path() . '/files');
+    $base_path = settings()->get('file_public_path', Site::getPath('files'));
     return $base_path;
   }
 
diff --git a/core/lib/Drupal/Core/SystemListing.php b/core/lib/Drupal/Core/SystemListing.php
index 0a82cd2..e9aee89 100644
--- a/core/lib/Drupal/Core/SystemListing.php
+++ b/core/lib/Drupal/Core/SystemListing.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core;
 
 use Drupal\Component\Utility\Settings;
+use Drupal\Core\Site\Site;
 
 /**
  * Returns information about system object files (modules, themes, etc.).
@@ -87,7 +88,6 @@ function scan($mask, $directory, $key = 'name') {
     if (!in_array($key, array('uri', 'filename', 'name'))) {
       $key = 'uri';
     }
-    $config = conf_path();
 
     // Search for the directory in core.
     $searchdir = array('core/' . $directory);
@@ -112,9 +112,13 @@ function scan($mask, $directory, $key = 'name') {
     if ($parent_site = Settings::getSingleton()->get('test_parent_site')) {
       $searchdir[] = $parent_site;
     }
-    if (file_exists("$config/$directory")) {
-      $searchdir[] = "$config/$directory";
+
+    if (Site::getPath() !== '') {
+      if (file_exists(Site::getPath($directory))) {
+        $searchdir[] = Site::getPath($directory);
+      }
     }
+
     // @todo Find a way to skip ./config directories (but not modules/config).
     $nomask = '/^(CVS|lib|templates|css|js)$/';
     $files = array();
diff --git a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php
index d230bc5..8617566 100644
--- a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php
+++ b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\file_test;
 
+use Drupal\Core\Site\Site;
 use Drupal\Core\StreamWrapper\LocalReadOnlyStream;
 
 /**
@@ -16,7 +17,7 @@
  */
 class DummyReadOnlyStreamWrapper extends LocalReadOnlyStream {
   function getDirectoryPath() {
-    return conf_path() . '/files';
+    return Site::getPath('files');
   }
 
   /**
diff --git a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php
index cbea40f..dd919c8 100644
--- a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php
+++ b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\file_test;
 
+use Drupal\Core\Site\Site;
 use Drupal\Core\StreamWrapper\LocalStream;
 
 /**
@@ -16,7 +17,7 @@
  */
 class DummyStreamWrapper extends LocalStream {
   function getDirectoryPath() {
-    return conf_path() . '/files';
+    return Site::getPath('files');
   }
 
   /**
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index c62c842..665873f 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Core\Language\Language;
+use Drupal\Core\Site\Site;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSelected;
 
 /**
@@ -14,7 +15,7 @@
 function locale_install() {
   // Create the interface translations directory and ensure it's writable.
   if (!$directory = \Drupal::config('locale.settings')->get('translation.path')) {
-    $directory = conf_path() . '/files/translations';
+    $directory = Site::getPath('files/translations');
     \Drupal::config('locale.settings')->set('translation.path', $directory)->save();
   }
   file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index e1bcc90..26cb330 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -18,6 +18,7 @@
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Language\Language;
+use Drupal\Core\Site\Site;
 use Drupal\Core\StreamWrapper\PublicStream;
 use Drupal\Core\Utility\Error;
 use Symfony\Component\HttpFoundation\Request;
@@ -982,7 +983,7 @@ private function prepareEnvironment() {
     }
 
     // Backup current in-memory configuration.
-    $this->originalSite = conf_path();
+    $this->originalSite = Site::getPath();
     $this->originalSettings = settings()->getAll();
     $this->originalConfig = $GLOBALS['config'];
 
@@ -998,7 +999,7 @@ private function prepareEnvironment() {
     // Save further contextual information.
     // Use the original files directory to avoid nesting it within an existing
     // simpletest directory if a test is executed within a test.
-    $this->originalFileDirectory = settings()->get('file_public_path', conf_path() . '/files');
+    $this->originalFileDirectory = settings()->get('file_public_path', Site::getPath('files'));
     $this->originalProfile = drupal_get_profile();
     $this->originalUser = isset($user) ? clone $user : NULL;
 
@@ -1091,8 +1092,11 @@ private function prepareEnvironment() {
 
     // After preparing the environment and changing the database prefix, we are
     // in a valid test environment.
+    if (!is_dir(DRUPAL_ROOT . '/' . $this->siteDirectory)) {
+      throw new \RuntimeException("Test site directory '$this->siteDirectory' does not exist.");
+    }
     drupal_valid_test_ua($this->databasePrefix);
-    conf_path(FALSE, TRUE);
+    Site::setUpTest();
 
     drupal_set_time_limit($this->timeLimit);
   }
@@ -1223,7 +1227,7 @@ private function restoreEnvironment() {
     else {
       drupal_valid_test_ua(FALSE);
     }
-    conf_path(TRUE, TRUE);
+    Site::tearDownTest();
 
     // Restore original shutdown callbacks.
     $callbacks = &drupal_register_shutdown_function();
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
index 9d93fa0..325e87b 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\ConnectionNotDefinedException;
+use Drupal\Core\Site\Site;
 
 /**
  * Base test case class for unit tests.
@@ -37,6 +38,9 @@ function __construct($test_id = NULL) {
    * setUp() method.
    */
   protected function setUp() {
+    // Initialize the test Site singleton, so that Site::getPath() works.
+    Site::init(DRUPAL_ROOT);
+
     file_prepare_directory($this->public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
     $this->settingsSet('file_public_path', $this->public_files_directory);
   }
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 9928b68..a0ea8df 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Component\Utility\Settings;
 use Drupal\Component\Utility\String;
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Database\Database;
@@ -774,7 +775,7 @@ protected function setUp() {
     // Copy and prepare an actual settings.php, so as to resemble a regular
     // installation.
     // Not using File API; a potential error must trigger a PHP warning.
-    copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php');
+    copy(DRUPAL_ROOT . '/core/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php');
 
     // All file system paths are created by System module during installation.
     // @see system_requirements()
@@ -793,23 +794,20 @@ protected function setUp() {
     );
     // Add the parent profile's search path to the child site's search paths.
     // @see drupal_system_listing()
-    $settings['conf']['simpletest.settings']['parent_profile'] = (object) array(
+    $settings['config']['simpletest.settings']['parent_profile'] = (object) array(
       'value' => $this->originalProfile,
       'required' => TRUE,
     );
+    // Write a new settings.php for the test site environment.
+    // drupal_rewrite_settings() will reload Settings and update
+    // $GLOBALS['config'] accordingly.
     $this->writeSettings($settings);
 
-    // Since Drupal is bootstrapped already, install_begin_request() will not
-    // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to
-    // reload the newly written custom settings.php manually.
-    drupal_settings_initialize();
-
     // Execute the non-interactive installer.
     require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
     install_drupal($parameters);
 
     // Import new settings.php written by the installer.
-    drupal_settings_initialize();
     foreach ($GLOBALS['config_directories'] as $type => $path) {
       $this->configDirectories[$type] = $path;
     }
@@ -821,6 +819,7 @@ protected function setUp() {
     // TestBase::restoreEnvironment() will delete the entire site directory.
     // Not using File API; a potential error must trigger a PHP warning.
     chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777);
+    chmod(DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php', 0666);
 
     $this->rebuildContainer();
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
index 26b1b76..91908fc 100644
--- a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\DrupalKernel;
 
 use Drupal\Core\DrupalKernel;
+use Drupal\Core\Site\Site;
 use Drupal\Component\PhpStorage\MTimeProtectedFastFileStorage;
 use Drupal\Component\PhpStorage\FileReadOnlyStorage;
 use Drupal\simpletest\DrupalUnitTestBase;
@@ -26,6 +27,9 @@ public static function getInfo() {
   }
 
   function setUp() {
+    // Initialize the test Site singleton, so that Site::getPath() works.
+    Site::init(DRUPAL_ROOT);
+
     // DrupalKernel relies on global $config_directories and requires those
     // directories to exist. Therefore, create the directories, but do not
     // invoke DrupalUnitTestBase::setUp(), since that would set up further
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
index d17db20..556f283 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\system\Tests\File;
 
+use Drupal\Core\Site\Site;
+
 /**
  * Directory related tests.
  */
@@ -23,7 +25,7 @@ public static function getInfo() {
    * Test local directory handling functions.
    */
   function testFileCheckLocalDirectoryHandling() {
-    $directory = conf_path() . '/files';
+    $directory = Site::getPath('files');
 
     // Check a new recursively created local directory for correct file system
     // permissions.
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php b/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php
index e02cd07..e62cf1a 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\system\Tests\File;
 
+use Drupal\Core\Site\Site;
+
 /**
  * Tests that files can not be written using ReadOnlyStreamWrapper functions.
  */
@@ -40,7 +42,7 @@ public static function getInfo() {
   function testWriteFunctions() {
     // Generate a test file
     $filename = $this->randomName();
-    $filepath = conf_path() . '/files/' . $filename;
+    $filepath = Site::getPath('files/' . $filename);
     file_put_contents($filepath, $filename);
 
     // Generate a read-only stream wrapper instance
@@ -83,7 +85,7 @@ function testWriteFunctions() {
 
     // Test the mkdir() function by attempting to create a directory.
     $dirname = $this->randomName();
-    $dir = conf_path() . '/files/' . $dirname;
+    $dir = Site::getPath('files/' . $dirname);
     $readonlydir = $this->scheme . '://' . $dirname;
     $this->assertFalse(@drupal_mkdir($readonlydir, 0775, 0), 'Unable to create directory with read-only stream wrapper.');
     // Create a temporary directory for testing purposes
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/SettingsRewriteTest.php b/core/modules/system/lib/Drupal/system/Tests/System/SettingsRewriteTest.php
index 74c080d..6096a41 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/SettingsRewriteTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/SettingsRewriteTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\System;
 
+use Drupal\Core\Site\Site;
 use Drupal\simpletest\UnitTestBase;
 
 /**
@@ -104,7 +105,7 @@ function testDrupalRewriteSettings() {
       ),
     );
     foreach ($tests as $test) {
-      $filename = settings()->get('file_public_path', conf_path() . '/files') . '/mock_settings.php';
+      $filename = settings()->get('file_public_path', Site::getPath('files')) . '/mock_settings.php';
       file_put_contents(DRUPAL_ROOT . '/' . $filename, "<?php\n" . $test['original'] . "\n");
       drupal_rewrite_settings($test['settings'], $filename);
       $this->assertEqual(file_get_contents(DRUPAL_ROOT . '/' . $filename), "<?php\n" . $test['expected'] . "\n");
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 2918e9d..80bf11a 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -9,6 +9,7 @@
 use Drupal\Core\Database\Database;
 use Drupal\Core\Language\Language;
 use Drupal\Core\StreamWrapper\PublicStream;
+use Drupal\Core\Site\Site;
 
 /**
  * Implements hook_requirements().
@@ -210,14 +211,17 @@ function system_requirements($phase) {
   // Test configuration files and directory for writability.
   if ($phase == 'runtime') {
     $conf_errors = array();
-    $conf_path = conf_path();
-    if (!drupal_verify_install_file($conf_path, FILE_NOT_WRITABLE, 'dir')) {
-      $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array('%file' => $conf_path));
+    if (!drupal_verify_install_file(Site::getAbsolutePath(), FILE_NOT_WRITABLE, 'dir')) {
+      $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array(
+        '%file' => Site::getPath(),
+      ));
     }
     foreach (array('settings.php', 'settings.local.php') as $conf_file) {
-      $full_path = $conf_path . '/' . $conf_file;
+      $full_path = Site::getAbsolutePath($conf_file);
       if (file_exists($full_path) && !drupal_verify_install_file($full_path, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE)) {
-        $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", array('%file' => $full_path));
+        $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", array(
+          '%file' => Site::getPath($conf_file),
+        ));
       }
     }
     if (!empty($conf_errors)) {
@@ -341,7 +345,7 @@ function system_requirements($phase) {
     else {
       // If we are installing Drupal, the settings.php file might not exist yet
       // in the intended site directory, so don't require it.
-      $directories[] = conf_path(FALSE) . '/files';
+      $directories[] = Site::getPath('files');
     }
     if (!empty($GLOBALS['config']['system.file']['path']['private'])) {
       $directories[] = $GLOBALS['config']['system.file']['path']['private'];
@@ -367,7 +371,7 @@ function system_requirements($phase) {
     $requirements['config directories'] = array(
       'title' => t('Configuration directories'),
       'value' => t('Not present'),
-      'description' => t('Your %file file must define the $config_directories variable as an array containing the name of a directories in which configuration files can be written.', array('%file' => conf_path() . '/settings.php')),
+      'description' => t('Your %file file must define the $config_directories variable as an array containing the name of a directories in which configuration files can be written.', array('%file' => Site::getPath('settings.php'))),
       'severity' => REQUIREMENT_ERROR,
     );
   }
diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc
index b0d0483..79995c2 100644
--- a/core/modules/update/update.manager.inc
+++ b/core/modules/update/update.manager.inc
@@ -38,6 +38,7 @@
 
 use Drupal\Core\Updater\Updater;
 use Drupal\Core\FileTransfer\Local;
+use Drupal\Core\Site\Site;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
@@ -470,7 +471,7 @@ function update_manager_update_ready_form_submit($form, &$form_state) {
     // trying to install the code, there's no need to prompt for FTP/SSH
     // credentials. Instead, we instantiate a Drupal\Core\FileTransfer\Local and
     // invoke update_authorize_run_update() directly.
-    if (fileowner($project_real_location) == fileowner(conf_path())) {
+    if (fileowner($project_real_location) == fileowner(Site::getAbsolutePath())) {
       module_load_include('inc', 'update', 'update.authorize');
       $filetransfer = new Local(DRUPAL_ROOT);
       update_authorize_run_update($filetransfer, $updates);
@@ -748,7 +749,7 @@ function update_manager_install_form_submit($form, &$form_state) {
   // trying to install the code, there's no need to prompt for FTP/SSH
   // credentials. Instead, we instantiate a Drupal\Core\FileTransfer\Local and
   // invoke update_authorize_run_install() directly.
-  if (fileowner($project_real_location) == fileowner(conf_path())) {
+  if (fileowner($project_real_location) == fileowner(Site::getAbsolutePath())) {
     module_load_include('inc', 'update', 'update.authorize');
     $filetransfer = new Local(DRUPAL_ROOT);
     call_user_func_array('update_authorize_run_install', array_merge(array($filetransfer), $arguments));
@@ -947,7 +948,7 @@ function update_manager_local_transfers_allowed() {
   // the configuration directory to determine if local transfers will be
   // allowed.
   $temporary_file = drupal_tempnam('temporary://', 'update_');
-  $local_transfers_allowed = fileowner($temporary_file) === fileowner(conf_path());
+  $local_transfers_allowed = fileowner($temporary_file) === fileowner(Site::getAbsolutePath());
 
   // Clean up. If this fails, we can ignore it (since this is just a temporary
   // file anyway).
diff --git a/sites/example.sites.php b/sites/example.sites.php
deleted file mode 100644
index 2a813dd..0000000
--- a/sites/example.sites.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-/**
- * @file
- * Configuration file for multi-site support and directory aliasing feature.
- *
- * This file is required for multi-site support and also allows you to define a
- * set of aliases that map hostnames, ports, and pathnames to configuration
- * directories in the sites directory. These aliases are loaded prior to
- * scanning for directories, and they are exempt from the normal discovery
- * rules. See default.settings.php to view how Drupal discovers the
- * configuration directory when no alias is found.
- *
- * Aliases are useful on development servers, where the domain name may not be
- * the same as the domain of the live server. Since Drupal stores file paths in
- * the database (files, system table, etc.) this will ensure the paths are
- * correct when the site is deployed to a live server.
- *
- * To activate this feature, copy and rename it such that its path plus
- * filename is 'sites/sites.php'.
- *
- * Aliases are defined in an associative array named $sites. The array is
- * written in the format: '<port>.<domain>.<path>' => 'directory'. As an
- * example, to map http://www.drupal.org:8080/mysite/test to the configuration
- * directory sites/example.com, the array should be defined as:
- * @code
- * $sites = array(
- *   '8080.www.drupal.org.mysite.test' => 'example.com',
- * );
- * @endcode
- * The URL, http://www.drupal.org:8080/mysite/test/, could be a symbolic link or
- * an Apache Alias directive that points to the Drupal root containing
- * index.php. An alias could also be created for a subdomain. See the
- * @link http://drupal.org/documentation/install online Drupal installation guide @endlink
- * for more information on setting up domains, subdomains, and subdirectories.
- *
- * The following examples look for a site configuration in sites/example.com:
- * @code
- * URL: http://dev.drupal.org
- * $sites['dev.drupal.org'] = 'example.com';
- *
- * URL: http://localhost/example
- * $sites['localhost.example'] = 'example.com';
- *
- * URL: http://localhost:8080/example
- * $sites['8080.localhost.example'] = 'example.com';
- *
- * URL: http://www.drupal.org:8080/mysite/test/
- * $sites['8080.www.drupal.org.mysite.test'] = 'example.com';
- * @endcode
- *
- * @see default.settings.php
- * @see conf_path()
- * @see http://drupal.org/documentation/install/multi-site
- */
