diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index d9977fb6b84d27c09f8565dd286263d2243ac6c6..a155778e83cbab12a11d68172edd3439bb943ba0 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1638,7 +1638,6 @@ function install_profile_themes(&$install_state) {
  *   An array of information about the current installation state.
  */
 function install_install_profile(&$install_state) {
-  \Drupal::service('module_installer')->install([$install_state['parameters']['profile']], FALSE);
   // Install all available optional config. During installation the module order
   // is determined by dependencies. If there are no dependencies between modules
   // then the order in which they are installed is dependent on random factors
@@ -1648,6 +1647,8 @@ function install_install_profile(&$install_state) {
   // any disparities that this creates.
   \Drupal::service('config.installer')->installOptionalConfig();
 
+  \Drupal::service('module_installer')->install([$install_state['parameters']['profile']], FALSE);
+
   // Ensure that the install profile's theme is used.
   // @see _drupal_maintenance_theme()
   \Drupal::theme()->resetActiveTheme();
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index cfee5199556ccf50b1e6fdcc7753341fdd5515f9..e123e397bae8c5ca46bc37c39c8dbf60bbaf16d0 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -140,9 +140,11 @@ public function installDefaultConfig($type, $name) {
     }
 
     // During a drupal installation optional configuration is installed at the
-    // end of the installation process.
+    // end of the installation process. Once the install profile is installed
+    // optional configuration should be installed as usual.
     // @see install_install_profile()
-    if (!$this->isSyncing() && !InstallerKernel::installationAttempted()) {
+    $profile_installed = in_array($this->drupalGetProfile(), $this->getEnabledExtensions(), TRUE);
+    if (!$this->isSyncing() && (!InstallerKernel::installationAttempted() || $profile_installed)) {
       $optional_install_path = $extension_path . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
       if (is_dir($optional_install_path)) {
         // Install any optional config the module provides.
diff --git a/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php b/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php
index 80a6861b330529d5aa2c52398bad2e3a2bd48a05..7b0accb15003ebd9d6946200ac81263a82625531 100644
--- a/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php
@@ -91,6 +91,10 @@ public function testInstallProfileConfigOverwrite() {
     $tour = Tour::load('language-add');
     $this->assertCount(3, $tour->getTips(), 'Optional configuration that is not overridden is not affected.');
 
+    // Ensure the optional configuration is installed. Note that the overridden
+    // language tour has a dependency on this tour so it has to exist.
+    $this->assertInstanceOf(Tour::class, Tour::load('testing_config_overrides_module'));
+
     // Ensure that optional configuration from a profile is created if
     // dependencies are met.
     $this->assertEquals('Config override test', Tour::load('testing_config_overrides')->label());
diff --git a/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install b/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install
index 95640955d9990e0c418bc68e6ae0b7f39fb5bd1b..db02670cd236cc3d5a5066f997285d988158e1b7 100644
--- a/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install
+++ b/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install
@@ -8,10 +8,12 @@
 use Drupal\demo_umami_content\InstallHelper;
 
 /**
- * Implements hook_install().
+ * Implements hook_module_preinstall().
  */
-function demo_umami_content_install($is_syncing) {
-  if (!$is_syncing) {
+function demo_umami_content_module_preinstall($module) {
+  if ($module === 'demo_umami_content' && !\Drupal::service('config.installer')->isSyncing()) {
+    // Run before importing config so blocks are created with the correct
+    // dependencies.
     \Drupal::classResolver(InstallHelper::class)->importContent();
   }
 }
diff --git a/core/profiles/testing_config_overrides/config/install/tour.tour.language.yml b/core/profiles/testing_config_overrides/config/install/tour.tour.language.yml
index 6f90240763415219850febbf2d104f9fda70d266..0d83ee83f606b46e579a25de87145f4322af110f 100644
--- a/core/profiles/testing_config_overrides/config/install/tour.tour.language.yml
+++ b/core/profiles/testing_config_overrides/config/install/tour.tour.language.yml
@@ -1,4 +1,12 @@
 id: language
+# The enforced dependency ensures that profile configuration in config/install
+# can depend on optional configuration of modules and themes it installs.
+dependencies:
+  enforced:
+    config:
+      - tour.tour.testing_config_overrides_module
+  module:
+    - language
 module: language
 label: Language
 langcode: en
diff --git a/core/profiles/testing_config_overrides/config/optional/tour.tour.testing_config_overrides.yml b/core/profiles/testing_config_overrides/config/optional/tour.tour.testing_config_overrides.yml
index f0ef399bcfd84b6471fc1c7c55bd8769ac066d3f..f36b14593acaeb63779f8b4d7b3119fecd09347d 100644
--- a/core/profiles/testing_config_overrides/config/optional/tour.tour.testing_config_overrides.yml
+++ b/core/profiles/testing_config_overrides/config/optional/tour.tour.testing_config_overrides.yml
@@ -1,5 +1,13 @@
 id: testing_config_overrides
 module: testing_config_overrides
+# This depends on configuration in the install's config/install directory so we
+# can test that this configuration is installed.
+dependencies:
+  enforced:
+    config:
+      - tour.tour.language
+  module:
+    - testing_config_overrides
 label: Config override test
 langcode: en
 routes:
diff --git a/core/profiles/testing_config_overrides/modules/testing_config_overrides_module/config/optional/tour.tour.testing_config_overrides_module.yml b/core/profiles/testing_config_overrides/modules/testing_config_overrides_module/config/optional/tour.tour.testing_config_overrides_module.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a6f7e7a70e54ff90fc071e780e10e2de1f3d123d
--- /dev/null
+++ b/core/profiles/testing_config_overrides/modules/testing_config_overrides_module/config/optional/tour.tour.testing_config_overrides_module.yml
@@ -0,0 +1,13 @@
+id: testing_config_overrides_module
+module: testing_config_overrides_module
+label: Config override test
+langcode: en
+routes:
+  - route_name: system.admin
+tips:
+  overview:
+    id: block-seven-content
+    plugin: text
+    label: Test
+    body: '<p>This is a test.</p>'
+    weight: 1
diff --git a/core/profiles/testing_config_overrides/modules/testing_config_overrides_module/testing_config_overrides_module.info.yml b/core/profiles/testing_config_overrides/modules/testing_config_overrides_module/testing_config_overrides_module.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7c0f1b4e2b45be6e8b89d904291db3bc0b2b10c8
--- /dev/null
+++ b/core/profiles/testing_config_overrides/modules/testing_config_overrides_module/testing_config_overrides_module.info.yml
@@ -0,0 +1,4 @@
+name: 'Testing config dependencies and optional configuration'
+type: module
+package: Testing
+version: VERSION
diff --git a/core/profiles/testing_config_overrides/testing_config_overrides.info.yml b/core/profiles/testing_config_overrides/testing_config_overrides.info.yml
index 6b6b55d34e6300813dd9f4ca76a1473c9ef36cf2..3ef6ee5fffec179380b2b86060676d31a60e151d 100644
--- a/core/profiles/testing_config_overrides/testing_config_overrides.info.yml
+++ b/core/profiles/testing_config_overrides/testing_config_overrides.info.yml
@@ -9,4 +9,5 @@ hidden: true
 install:
   - action
   - language
+  - testing_config_overrides_module
   - tour