diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 5d4424a..fca92bd 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -841,31 +841,19 @@ function drupal_installation_attempted() {
  * When this function is called during Drupal's initial installation process,
  * the name of the profile that's about to be installed is stored in the global
  * installation state. At all other times, the "install_profile" setting will be
- * available in settings.php.
+ * available in settings.php, or declared as a Distribution.
  *
  * @return string|null $profile
  *   The name of the installation profile or NULL if no installation profile is
  *   currently active. This is the case for example during the first steps of
  *   the installer or during unit tests.
+ *
+ * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
+ *   Use \Drupal::installProfile() or the install_profile container parameter
+ *   instead.
  */
 function drupal_get_profile() {
-  global $install_state;
-
-  if (drupal_installation_attempted()) {
-    // If the profile has been selected return it.
-    if (isset($install_state['parameters']['profile'])) {
-      $profile = $install_state['parameters']['profile'];
-    }
-    else {
-      $profile = NULL;
-    }
-  }
-  else {
-    // Fall back to NULL, if there is no 'install_profile' setting.
-    $profile = Settings::get('install_profile');
-  }
-
-  return $profile;
+  return \Drupal::installProfile();
 }
 
 /**
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 808520b..e8ef040 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1211,12 +1211,9 @@ function _install_select_profile(&$install_state) {
       return $profile;
     }
   }
-  // Check for a distribution profile.
-  foreach ($install_state['profiles'] as $profile) {
-    $profile_info = install_profile_info($profile->getName());
-    if (!empty($profile_info['distribution'])) {
-      return $profile->getName();
-    }
+  // Check for a distribution.
+  if ($distribution = \Drupal::service('kernel')->getDistribution()) {
+    return $distribution;
   }
 
   // Get all visible (not hidden) profiles.
@@ -2296,13 +2293,14 @@ function install_display_requirements($install_state, $requirements) {
 }
 
 /**
- * Installation task; ensures install profile is written to settings.php.
+ * Installation task; writes profile to settings.php (absent a distribution).
  *
  * @param array $install_state
  *   An array of information about the current installation state.
  */
 function install_write_profile($install_state) {
-  if (Settings::get('install_profile') !== $install_state['parameters']['profile']) {
+  $is_mismatch = \Drupal::installProfile() !== $install_state['parameters']['profile'];
+  if ($is_mismatch) {
     // Remember the profile which was used.
     $settings['settings']['install_profile'] = (object) array(
       'value' => $install_state['parameters']['profile'],
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index 7621a48..8b15cef 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -181,6 +181,16 @@ public static function root() {
   }
 
   /**
+   * Gets the active install profile.
+   *
+   * @return string|null
+   *   The name of the any active install profile or distribution.
+   */
+  public static function installProfile() {
+    return static::getContainer()->getParameter('install_profile');
+  }
+
+  /**
    * Indicates if there is a currently active request object.
    *
    * @return bool
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index 8906eba..7153ab9 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -11,7 +11,6 @@
 use Drupal\Core\Config\Entity\ConfigDependencyManager;
 use Drupal\Core\Config\Entity\ConfigEntityDependency;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Site\Settings;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 class ConfigInstaller implements ConfigInstallerInterface {
@@ -614,7 +613,7 @@ protected function drupalGetPath($type, $name) {
   protected function drupalGetProfile() {
     // Settings is safe to use because settings.php is written before any module
     // is installed.
-    return Settings::get('install_profile');
+    return \Drupal::installProfile();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
index f31976b..606b833 100644
--- a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
+++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Core\Config;
 
-use Drupal\Core\Site\Settings;
 use Drupal\Core\Extension\ExtensionDiscovery;
 
 /**
@@ -83,15 +82,14 @@ protected function getAllFolders() {
       $this->folders = array();
       $this->folders += $this->getCoreNames();
 
-      $install_profile = Settings::get('install_profile');
-      $profile = drupal_get_profile();
+      $profile = \Drupal::installProfile();
       $extensions = $this->configStorage->read('core.extension');
       // @todo Remove this scan as part of https://www.drupal.org/node/2186491
       $listing = new ExtensionDiscovery(\Drupal::root());
       if (!empty($extensions['module'])) {
         $modules = $extensions['module'];
         // Remove the install profile as this is handled later.
-        unset($modules[$install_profile]);
+        unset($modules[$profile]);
         $profile_list = $listing->scan('profile');
         if ($profile && isset($profile_list[$profile])) {
           // Prime the drupal_get_filename() static cache with the profile info
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index fd27416..65a3a20 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -18,6 +18,7 @@
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
 use Drupal\Core\DependencyInjection\YamlFileLoader;
 use Drupal\Core\Extension\ExtensionDiscovery;
+use Drupal\Core\Extension\InfoParser;
 use Drupal\Core\File\MimeType\MimeTypeGuesser;
 use Drupal\Core\Http\TrustedHostsRequestFactory;
 use Drupal\Core\Language\Language;
@@ -1079,6 +1080,7 @@ protected function compileContainer() {
     $container = $this->getContainerBuilder();
     $container->set('kernel', $this);
     $container->setParameter('container.modules', $this->getModulesParameter());
+    $container->setParameter('install_profile', $this->getInstallProfile());
 
     // Get a list of namespaces and put it onto the container.
     $namespaces = $this->getModuleNamespacesPsr4($this->getModuleFileNames());
@@ -1448,4 +1450,36 @@ protected function addServiceFiles($service_yamls) {
     }
     return FALSE;
   }
+
+  /**
+   * Gets the active install profile.
+   *
+   * @return string|null
+   *   The name of the any active install profile or distribution.
+   */
+  protected function getInstallProfile() {
+    $install_profile = Settings::get('install_profile');
+    if (empty($install_profile)) {
+      $install_profile = $this->getDistribution();
+    }
+    return $install_profile;
+
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDistribution() {
+    $listing = new ExtensionDiscovery($this->root);
+    $listing->setProfileDirectories(array());
+    $info_parser = new InfoParser();
+    foreach ($listing->scan('profile') as $profile) {
+      $info = $info_parser->parse($profile->getPathname());
+      if (!empty($info['distribution'])) {
+        return $profile->getName();
+      }
+    }
+    return NULL;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php
index 892952a..287102b 100644
--- a/core/lib/Drupal/Core/DrupalKernelInterface.php
+++ b/core/lib/Drupal/Core/DrupalKernelInterface.php
@@ -134,4 +134,15 @@ public function preHandle(Request $request);
    */
   public function loadLegacyIncludes();
 
+  /**
+   * Get the name of any discovered profile that is a distribution.
+   *
+   * If multiple profiles are distributions, then the first discovered profile
+   * will be selected. See https://www.drupal.org/node/2210443.
+   *
+   * @return string|null
+   *   The machine name of any discovered distribution.
+   */
+  public function getDistribution();
+
 }
diff --git a/core/lib/Drupal/Core/InstallProfileFactory.php b/core/lib/Drupal/Core/InstallProfileFactory.php
new file mode 100644
index 0000000..dc6b9af
--- /dev/null
+++ b/core/lib/Drupal/Core/InstallProfileFactory.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\AppRootFactory.
+ */
+
+namespace Drupal\Core;
+
+/**
+ * Gets the install profile from the kernel.
+ */
+class InstallProfileFactory {
+
+  /**
+   * The Drupal kernel.
+   *
+   * @var \Drupal\Core\DrupalKernelInterface
+   */
+  protected $drupalKernel;
+
+  /**
+   * Constructs an InstallProfileFactory instance.
+   *
+   * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel
+   *   The Drupal kernel.
+   */
+  public function __construct(DrupalKernelInterface $drupal_kernel) {
+    $this->drupalKernel = $drupal_kernel;
+  }
+
+  /**
+   * Gets the install profile.
+   *
+   * @return string
+   */
+  public function get() {
+    return $this->drupalKernel->getInstallProfile();
+  }
+
+}
+
diff --git a/core/lib/Drupal/Core/Installer/InstallerKernel.php b/core/lib/Drupal/Core/Installer/InstallerKernel.php
index cd3977c..7cf6f72 100644
--- a/core/lib/Drupal/Core/Installer/InstallerKernel.php
+++ b/core/lib/Drupal/Core/Installer/InstallerKernel.php
@@ -45,4 +45,28 @@ protected function addServiceFiles($service_yamls) {
     // In the beginning there is no settings.php and no service YAMLs.
     return parent::addServiceFiles($service_yamls ?: []);
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getInstallProfile() {
+    global $install_state;
+
+    if ($install_state && empty($install_state['installation_finished'])) {
+      // If the profile has been selected return it.
+      if (isset($install_state['parameters']['profile'])) {
+        $profile = $install_state['parameters']['profile'];
+      }
+      else {
+        $profile = NULL;
+      }
+    }
+    else {
+      $profile = parent::getInstallProfile();
+    }
+
+    return $profile;
+  }
+
+
 }
diff --git a/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php b/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php
index 27ca162..2d28302 100644
--- a/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php
+++ b/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Bootstrap;
 
 use Drupal\simpletest\KernelTestBase;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 
 /**
  * Tests that drupal_get_filename() works correctly.
@@ -17,14 +18,18 @@
 class GetFilenameUnitTest extends KernelTestBase {
 
   /**
+   * {@inheritdoc}
+   */
+  public function containerBuild(ContainerBuilder $container) {
+    parent::containerBuild($container);
+    // Use the testing install profile.
+    $container->setParameter('install_profile', 'testing');
+  }
+
+  /**
    * Tests that drupal_get_filename() works when the file is not in database.
    */
   function testDrupalGetFilename() {
-    // drupal_get_profile() is using obtaining the profile from state if the
-    // install_state global is not set.
-    global $install_state;
-    $install_state['parameters']['profile'] = 'testing';
-
     // Rebuild system.module.files state data.
     // @todo Remove as part of https://www.drupal.org/node/2186491
     drupal_static_reset('system_rebuild_module_data');
diff --git a/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php b/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php
new file mode 100644
index 0000000..f6548eb
--- /dev/null
+++ b/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php
@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Installer\DistributionProfileExistingSettingsTest.
+ */
+
+namespace Drupal\system\Tests\Installer;
+
+use Drupal\Component\Serialization\Yaml;
+use Drupal\Core\Database\Database;
+use Drupal\Core\DrupalKernel;
+use Drupal\Core\Site\Settings;
+use Drupal\simpletest\InstallerTestBase;
+use Symfony\Component\HttpFoundation\Request;
+
+
+/**
+ * Tests distribution profile support with existing settings.
+ *
+ * @group Installer
+ */
+class DistributionProfileExistingSettingsTest extends InstallerTestBase {
+
+  /**
+   * The distribution profile info.
+   *
+   * @var array
+   */
+  protected $info;
+
+  protected function setUp() {
+    $this->info = array(
+      'type' => 'profile',
+      'core' => \Drupal::CORE_COMPATIBILITY,
+      'name' => 'Distribution profile',
+      'distribution' => array(
+        'name' => 'My Distribution',
+        'install' => array(
+          'theme' => 'bartik',
+        ),
+      ),
+    );
+    // File API functions are not available yet.
+    $path = $this->siteDirectory . '/profiles/mydistro';
+    mkdir($path, 0777, TRUE);
+    file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info));
+
+    // Pre-configure hash salt.
+    // Any string is valid, so simply use the class name of this test.
+    $this->settings['settings']['hash_salt'] = (object) array(
+      'value' => __CLASS__,
+      'required' => TRUE,
+    );
+
+    // Pre-configure database credentials.
+    $connection_info = Database::getConnectionInfo();
+    unset($connection_info['default']['pdo']);
+    unset($connection_info['default']['init_commands']);
+
+    $this->settings['databases']['default'] = (object) array(
+      'value' => $connection_info,
+      'required' => TRUE,
+    );
+
+    // Use the kernel to find the site path because the site.path service should
+    // not be available at this point in the install process.
+    $site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
+    // Pre-configure config directories.
+    $this->settings['config_directories'] = array(
+      CONFIG_ACTIVE_DIRECTORY => (object) array(
+        'value' => $site_path . '/files/config_active',
+        'required' => TRUE,
+      ),
+      CONFIG_STAGING_DIRECTORY => (object) array(
+        'value' => $site_path . '/files/config_staging',
+        'required' => TRUE,
+      ),
+    );
+    mkdir($this->settings['config_directories'][CONFIG_ACTIVE_DIRECTORY]->value, 0777, TRUE);
+    mkdir($this->settings['config_directories'][CONFIG_STAGING_DIRECTORY]->value, 0777, TRUE);
+    parent::setUp();
+    $filename = $this->siteDirectory . '/settings.php';
+    // Make the settings file read-only.
+    // Not using File API; a potential error must trigger a PHP warning.
+    chmod($filename, 0444);
+  }
+
+  /**
+   * Overrides InstallerTest::setUpLanguage().
+   */
+  protected function setUpLanguage() {
+    // Verify that the distribution name appears.
+    $this->assertRaw($this->info['distribution']['name']);
+    // Verify that the requested theme is used.
+    $this->assertRaw($this->info['distribution']['install']['theme']);
+    // Verify that the "Choose profile" step does not appear.
+    $this->assertNoText('profile');
+
+    parent::setUpLanguage();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUpProfile() {
+    // This step is skipped, because there is a distribution profile.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUpSettings() {
+    // This step should not appear, since settings.php is fully configured
+    // already.
+  }
+
+  /**
+   * Confirms that the installation succeeded.
+   */
+  public function testInstalled() {
+    $this->assertUrl('user/1');
+    $this->assertResponse(200);
+    // Confirm that we are logged-in after installation.
+    $this->assertText($this->rootUser->getUsername());
+
+    // Confirm that Drupal recognizes this distribution as the current profile.
+    $this->assertEqual(\Drupal::installProfile(), 'mydistro');
+    $this->assertNull(Settings::get('install_profile'), 'The install profile has not been written to settings.php.');
+  }
+
+}
diff --git a/core/modules/system/src/Tests/Installer/DistributionProfileTest.php b/core/modules/system/src/Tests/Installer/DistributionProfileTest.php
index 367510f..ca43d09 100644
--- a/core/modules/system/src/Tests/Installer/DistributionProfileTest.php
+++ b/core/modules/system/src/Tests/Installer/DistributionProfileTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Installer;
 
 use Drupal\Component\Serialization\Yaml;
+use Drupal\Core\Site\Settings;
 use Drupal\simpletest\InstallerTestBase;
 
 /**
@@ -73,6 +74,10 @@ public function testInstalled() {
     $this->assertResponse(200);
     // Confirm that we are logged-in after installation.
     $this->assertText($this->rootUser->getUsername());
+
+    // Confirm that Drupal recognizes this distribution as the current profile.
+    $this->assertEqual(\Drupal::installProfile(), 'mydistro');
+    $this->assertEqual(Settings::get('install_profile'), 'mydistro', 'The install profile has been written to settings.php.');
   }
 
 }
diff --git a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsNoProfileTest.php b/core/modules/system/src/Tests/Installer/InstallerExistingSettingsNoProfileTest.php
index 61dd5be..f7b41fe 100644
--- a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsNoProfileTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerExistingSettingsNoProfileTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\system\Tests\Installer;
 
-use Drupal\Core\Site\Settings;
 use Drupal\simpletest\InstallerTestBase;
 use Drupal\Core\Database\Database;
 
@@ -73,7 +72,7 @@ protected function setUpSettings() {
   public function testInstaller() {
     $this->assertUrl('user/1');
     $this->assertResponse(200);
-    $this->assertEqual('testing', Settings::get('install_profile'));
+    $this->assertEqual('testing', \Drupal::installProfile());
   }
 
 }
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 9ad5cae..99ec3a9 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -258,12 +258,20 @@
 /**
  * The active installation profile.
  *
+ * This setting should not be accessed directly using the Settings object. Use
+ * \Drupal::installProfile() or inject the install_profile container parameter
+ * instead.
+ *
  * Changing this after installation is not recommended as it changes which
  * directories are scanned during extension discovery. If this is set prior to
  * installation this value will be rewritten according to the profile selected
- * by the user.
+ * by the user. If the installation is using a distribution then this does not
+ * need to be set.
  *
  * @see install_select_profile()
+ * @see \Drupal::installProfile()
+ * @see \Drupal\Core\DrupalKernel::getInstallProfile()
+ * @see \Drupal\Core\DrupalKernel::getDistribution()
  */
 # $settings['install_profile'] = '';
 
