diff --git a/Gemfile b/Gemfile
index c5462b6218a88753422b6e10aa1a697662d8db7e_R2VtZmlsZQ==..75e2cef04837b969ae959833d3568f1ab80eb3e9_R2VtZmlsZQ== 100644
--- a/Gemfile
+++ b/Gemfile
@@ -41,7 +41,6 @@
 gem 'yard'
 gem 'toml-rb'
 gem 'retriable'
-gem "tomlib", "~> 0.5.0"
 
 group :packagecloud, optional: true do
   gem 'package_cloud'
diff --git a/Gemfile.lock b/Gemfile.lock
index c5462b6218a88753422b6e10aa1a697662d8db7e_R2VtZmlsZS5sb2Nr..75e2cef04837b969ae959833d3568f1ab80eb3e9_R2VtZmlsZS5sb2Nr 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -479,7 +479,6 @@
     thread_safe (0.3.6)
     toml-rb (2.2.0)
       citrus (~> 3.0, > 3.0)
-    tomlib (0.5.0)
     tomlrb (1.3.0)
     train-core (3.9.2)
       addressable (~> 2.5)
@@ -585,7 +584,6 @@
   simplecov-cobertura
   thor (~> 1.2)
   toml-rb
-  tomlib (~> 0.5.0)
   yard
 
 BUNDLED WITH
diff --git a/config/patches/tomlib/license/add-license-file.patch b/config/patches/tomlib/license/add-license-file.patch
deleted file mode 100644
index c5462b6218a88753422b6e10aa1a697662d8db7e_Y29uZmlnL3BhdGNoZXMvdG9tbGliL2xpY2Vuc2UvYWRkLWxpY2Vuc2UtZmlsZS5wYXRjaA==..0000000000000000000000000000000000000000
--- a/config/patches/tomlib/license/add-license-file.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-diff --git a/LICENSE.txt b/LICENSE.txt
-new file mode 100644
-index 000000000..82cf5177b
---- /dev/null
-+++ b/LICENSE.txt
-@@ -0,0 +1,21 @@
-+The MIT License (MIT)
-+
-+Copyright (c) 2022 Kamil Giszczak
-+
-+Permission is hereby granted, free of charge, to any person obtaining a copy
-+of this software and associated documentation files (the "Software"), to deal
-+in the Software without restriction, including without limitation the rights
-+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+copies of the Software, and to permit persons to whom the Software is
-+furnished to do so, subject to the following conditions:
-+
-+The above copyright notice and this permission notice shall be included in
-+all copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+THE SOFTWARE.
diff --git a/config/software/gitaly.rb b/config/software/gitaly.rb
index c5462b6218a88753422b6e10aa1a697662d8db7e_Y29uZmlnL3NvZnR3YXJlL2dpdGFseS5yYg==..75e2cef04837b969ae959833d3568f1ab80eb3e9_Y29uZmlnL3NvZnR3YXJlL2dpdGFseS5yYg== 100644
--- a/config/software/gitaly.rb
+++ b/config/software/gitaly.rb
@@ -30,7 +30,6 @@
 dependency 'ruby'
 dependency 'bundler'
 dependency 'libicu'
-dependency 'tomlib'
 
 # Technically, gitaly depends on git also. But because of how omnibus arranges
 # components to be built, this causes git to be built early in the process. But
diff --git a/config/software/tomlib.rb b/config/software/tomlib.rb
deleted file mode 100644
index c5462b6218a88753422b6e10aa1a697662d8db7e_Y29uZmlnL3NvZnR3YXJlL3RvbWxpYi5yYg==..0000000000000000000000000000000000000000
--- a/config/software/tomlib.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright 2016-2023 GitLab Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-name 'tomlib'
-
-# The version here should be in agreement with /Gemfile.lock so that our rspec
-# testing stays consistent with the package contents.
-default_version '0.5.0'
-
-license 'MIT'
-license_file 'LICENSE.txt'
-
-skip_transitive_dependency_licensing true
-
-dependency 'ruby'
-
-build do
-  patch source: "license/add-license-file.patch"
-  env = with_standard_compiler_flags(with_embedded_path)
-
-  gem 'install tomlib' \
-      " --version '#{version}'", env: env
-end
diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template
index c5462b6218a88753422b6e10aa1a697662d8db7e_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..75e2cef04837b969ae959833d3568f1ab80eb3e9_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644
--- a/files/gitlab-config-template/gitlab.rb.template
+++ b/files/gitlab-config-template/gitlab.rb.template
@@ -2448,6 +2448,7 @@
 # }
 # praefect['wrapper_path'] = "/opt/gitlab/embedded/bin/gitaly-wrapper"
 # praefect['failover_enabled'] = true
+# praefect['failover_timeout'] = "10s"
 # praefect['auth_token'] = ""
 # praefect['auth_transitioning'] = false
 # praefect['listen_addr'] = "localhost:2305"
diff --git a/files/gitlab-cookbooks/praefect/attributes/default.rb b/files/gitlab-cookbooks/praefect/attributes/default.rb
index c5462b6218a88753422b6e10aa1a697662d8db7e_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9hdHRyaWJ1dGVzL2RlZmF1bHQucmI=..75e2cef04837b969ae959833d3568f1ab80eb3e9_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9hdHRyaWJ1dGVzL2RlZmF1bHQucmI= 100644
--- a/files/gitlab-cookbooks/praefect/attributes/default.rb
+++ b/files/gitlab-cookbooks/praefect/attributes/default.rb
@@ -1,6 +1,11 @@
 default['praefect']['enable'] = false
+default['praefect']['failover_enabled'] = true
+default['praefect']['failover_timeout'] = nil
+default['praefect']['failover_election_strategy'] = nil
+default['praefect']['auth_token'] = nil
+default['praefect']['auth_transitioning'] = false
 default['praefect']['dir'] = "/var/opt/gitlab/praefect"
 default['praefect']['log_directory'] = "/var/log/gitlab/praefect"
 default['praefect']['env_directory'] = "/opt/gitlab/etc/praefect/env"
 # default['praefect']['env'] is set in ../recipes/enable.rb
 default['praefect']['wrapper_path'] = "/opt/gitlab/embedded/bin/gitaly-wrapper"
@@ -2,6 +7,14 @@
 default['praefect']['dir'] = "/var/opt/gitlab/praefect"
 default['praefect']['log_directory'] = "/var/log/gitlab/praefect"
 default['praefect']['env_directory'] = "/opt/gitlab/etc/praefect/env"
 # default['praefect']['env'] is set in ../recipes/enable.rb
 default['praefect']['wrapper_path'] = "/opt/gitlab/embedded/bin/gitaly-wrapper"
+default['praefect']['listen_addr'] = "localhost:2305"
+default['praefect']['prometheus_grpc_latency_buckets'] = nil
+default['praefect']['prometheus_listen_addr'] = "localhost:9652"
+default['praefect']['logging_level'] = nil
+default['praefect']['logging_format'] = 'json'
+default['praefect']['sentry_dsn'] = nil
+default['praefect']['sentry_environment'] = nil
+default['praefect']['virtual_storages'] = {}
 default['praefect']['auto_migrate'] = true
@@ -7,3 +20,25 @@
 default['praefect']['auto_migrate'] = true
+default['praefect']['database_host'] = nil
+default['praefect']['database_port'] = nil
+default['praefect']['database_user'] = nil
+default['praefect']['database_password'] = nil
+default['praefect']['database_dbname'] = nil
+default['praefect']['database_sslmode'] = nil
+default['praefect']['database_sslcert'] = nil
+default['praefect']['database_sslkey'] = nil
+default['praefect']['database_sslrootcert'] = nil
+default['praefect']['database_direct_host'] = nil
+default['praefect']['database_direct_port'] = nil
+default['praefect']['database_direct_user'] = nil
+default['praefect']['database_direct_password'] = nil
+default['praefect']['database_direct_dbname'] = nil
+default['praefect']['database_direct_sslmode'] = nil
+default['praefect']['database_direct_sslcert'] = nil
+default['praefect']['database_direct_sslkey'] = nil
+default['praefect']['database_direct_sslrootcert'] = nil
+default['praefect']['separate_database_metrics'] = true
+default['praefect']['tls_listen_addr'] = nil
+default['praefect']['certificate_path'] = nil
+default['praefect']['key_path'] = nil
 default['praefect']['consul_service_name'] = 'praefect'
 default['praefect']['consul_service_meta'] = nil
@@ -8,16 +43,5 @@
 default['praefect']['consul_service_name'] = 'praefect'
 default['praefect']['consul_service_meta'] = nil
-default['praefect']['configuration'] = {
-  listen_addr: 'localhost:2305',
-  prometheus_listen_addr: 'localhost:9652',
-  logging: {
-    format: 'json',
-  },
-  prometheus_exclude_database_from_default_metrics: true,
-  auth: {
-    transitioning: false
-  },
-  failover: {
-    enabled: true
-  }
-}
+default['praefect']['background_verification_verification_interval'] = nil
+default['praefect']['background_verification_delete_invalid_records'] = nil
+default['praefect']['graceful_stop_timeout'] = nil
diff --git a/files/gitlab-cookbooks/praefect/libraries/praefect.rb b/files/gitlab-cookbooks/praefect/libraries/praefect.rb
index c5462b6218a88753422b6e10aa1a697662d8db7e_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9saWJyYXJpZXMvcHJhZWZlY3QucmI=..75e2cef04837b969ae959833d3568f1ab80eb3e9_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9saWJyYXJpZXMvcHJhZWZlY3QucmI= 100644
--- a/files/gitlab-cookbooks/praefect/libraries/praefect.rb
+++ b/files/gitlab-cookbooks/praefect/libraries/praefect.rb
@@ -1,6 +1,4 @@
-require 'tomlib'
-
 module Praefect
   class << self
     def parse_variables
       parse_virtual_storages
@@ -3,154 +1,7 @@
 module Praefect
   class << self
     def parse_variables
       parse_virtual_storages
-
-      remap_legacy_values
-    end
-
-    # remap_legacy_values moves configuration values from their legacy locations to where they are
-    # in Praefect's own configuration. All of the configuration was previously grouped under Gitlab['praefect']
-    # but now Praefect's own config is under Gitlab['praefect']['configuration']. This then allows us to
-    # simply encode the map as TOML to get the resulting Praefect configuration file without having to manually
-    # template every key. As existing configuration files may can still have the configuration in its old place,
-    # this method provides backwards compatibility by moving the old values to their new locations. This can
-    # compatibility wrapper can be removed in 16.0
-    def remap_legacy_values
-      Gitlab['praefect']['configuration'] = {} unless Gitlab['praefect']['configuration']
-
-      remap_recursive(
-        {
-          listen_addr: 'listen_addr',
-          socket_path: 'socket_path',
-          prometheus_listen_addr: 'prometheus_listen_addr',
-          tls_listen_addr: 'tls_listen_addr',
-          prometheus_exclude_database_from_default_metrics: 'separate_database_metrics',
-          auth: {
-            token: 'auth_token',
-            transitioning: 'auth_transitioning',
-          },
-          logging: {
-            format: 'logging_format',
-            level: 'logging_level',
-          },
-          failover: {
-            enabled: 'failover_enabled',
-          },
-          background_verification: {
-            delete_invalid_records: 'background_verification_delete_invalid_records',
-            verification_interval: 'background_verification_verification_interval',
-          },
-          reconciliation: {
-            scheduling_interval: 'reconciliation_scheduling_interval',
-            histogram_buckets: 'reconciliation_histogram_buckets',
-          },
-          tls: {
-            certificate_path: 'certificate_path',
-            key_path: 'key_path',
-          },
-          database: {
-            host: 'database_host',
-            port: 'database_port',
-            user: 'database_user',
-            password: 'database_password',
-            dbname: 'database_dbname',
-            sslmode: 'database_sslmode',
-            sslcert: 'database_sslcert',
-            sslkey: 'database_sslkey',
-            sslrootcert: 'database_sslrootcert',
-            session_pooled: {
-              host: 'database_direct_host',
-              port: 'database_direct_port',
-              user: 'database_direct_user',
-              password: 'database_direct_password',
-              dbname: 'database_direct_dbname',
-              sslmode: 'database_direct_sslmode',
-              sslcert: 'database_direct_sslcert',
-              sslkey: 'database_direct_sslkey',
-              sslrootcert: 'database_direct_sslrootcert',
-            }
-          },
-          sentry: {
-            sentry_dsn: 'sentry_dsn',
-            sentry_environment: 'sentry_environment',
-          },
-          prometheus: {
-            grpc_latency_buckets: 'prometheus_grpc_latency_buckets',
-          },
-          graceful_stop_timeout: 'graceful_stop_timeout',
-          virtual_storage: lambda {
-            return [] unless Gitlab['praefect']['virtual_storages']
-            raise "Legacy configuration key 'virtual_storages' can't be set when its new key 'configuration.virtual_storage' is set." if Gitlab['praefect']['configuration'].key?('virtual_storage')
-
-            Gitlab['praefect']['virtual_storages'].map do |name, details|
-              virtual_storage = {
-                name: name,
-                node: details['nodes'].map do |name, details|
-                  {
-                    storage: name,
-                    address: details['address'],
-                    token: details['token'],
-                  }
-                end
-              }
-
-              virtual_storage['default_replication_factor'] = details['default_replication_factor'] if details['default_replication_factor']
-              virtual_storage
-            end
-          }
-        },
-        Gitlab['praefect']['configuration'],
-        ['configuration']
-      )
-    end
-
-    # remap_recursive goes over the mappings to remap the configuration from the old format into the new
-    # format:
-    #   - Hash values indicate a subsection in the destination configuration. Hashes are recursed into to
-    #     build the expected configuration structure.
-    #   - Proc values are mapping functions that return the new value when executed.
-    #   - String values indicate an old configuration key that should be copied into the new configuration
-    #     under the new key.
-    #
-    # new_parent contains the parent key path on each level of recursion.
-    def remap_recursive(mappings, new_configuration, new_parent)
-      mappings.each do |new_key, mapping|
-        # If this is a hash, recurse the tree to create the correct structure.
-        if mapping.is_a?(Hash)
-          new_value = remap_recursive(
-            mappings[new_key],
-            # If there is already a section in the new configuration under the key, use that. If not,
-            # initialize and empty hash for the section.
-            Gitlab['praefect'].dig(*[new_parent, new_key].flatten) || {},
-            [new_parent, new_key].flatten
-          )
-
-          new_configuration[new_key] = new_value unless new_value.empty?
-          next
-        end
-
-        # If this is a Proc, it's a mapping function that returns the value for the
-        # new key.
-        if mapping.is_a?(Proc)
-          new_value = mapping.call
-          new_configuration[new_key] = new_value unless new_value.empty?
-          next
-        end
-
-        # If the mapping is not a hash nor a lambda, then it is a String. The value gets copied from the
-        # mapping to the new_key as is.
-        #
-        # If there is no old key, then there's nothing to map. Proceed to the next key.
-        next unless Gitlab['praefect'].key?(mapping)
-
-        # Raise an error if both the old key and the new key are present in the configuration as it would be
-        # ambigious which key is ued in the final configuration.
-        raise "Legacy configuration key '#{mapping}' can't be set when its new key '#{[new_parent, new_key].flatten.join('.')}' is set." if new_configuration.key?(new_key)
-
-        new_configuration[new_key] = Gitlab['praefect'][mapping]
-      end
-
-      new_configuration
     end
 
     def parse_virtual_storages
diff --git a/files/gitlab-cookbooks/praefect/recipes/enable.rb b/files/gitlab-cookbooks/praefect/recipes/enable.rb
index c5462b6218a88753422b6e10aa1a697662d8db7e_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9yZWNpcGVzL2VuYWJsZS5yYg==..75e2cef04837b969ae959833d3568f1ab80eb3e9_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9yZWNpcGVzL2VuYWJsZS5yYg== 100644
--- a/files/gitlab-cookbooks/praefect/recipes/enable.rb
+++ b/files/gitlab-cookbooks/praefect/recipes/enable.rb
@@ -21,7 +21,7 @@
 log_directory = node['praefect']['log_directory']
 env_directory = node['praefect']['env_directory']
 wrapper_path = node['praefect']['wrapper_path']
-json_logging = node['praefect']['configuration']['logging']['format'].eql?('json')
+json_logging = node['praefect']['logging_format'].eql?('json')
 config_path = File.join(working_dir, "config.toml")
 
 directory working_dir do
@@ -50,9 +50,11 @@
   notifies :restart, "runit_service[praefect]" if omnibus_helper.should_notify?('praefect')
 end
 
+gitlab_url, gitlab_relative_path = WebServerHelper.internal_api_url(node)
+
 template "Create praefect config.toml" do
   path config_path
   source "praefect-config.toml.erb"
   owner "root"
   group account_helper.gitlab_group
   mode "0640"
@@ -53,10 +55,14 @@
 template "Create praefect config.toml" do
   path config_path
   source "praefect-config.toml.erb"
   owner "root"
   group account_helper.gitlab_group
   mode "0640"
-  variables node['praefect']
+  variables node['praefect'].to_hash.merge(
+    { gitlab_shell: node['gitlab']['gitlab-shell'].to_hash,
+      gitlab_url: gitlab_url,
+      gitlab_relative_path: gitlab_relative_path }
+  )
   notifies :hup, "runit_service[praefect]"
 end
 
@@ -91,7 +97,7 @@
   id 'praefect'
   meta node['praefect']['consul_service_meta']
   action Prometheus.service_discovery_action
-  socket_address node['praefect']['configuration']['prometheus_listen_addr']
+  socket_address node['praefect']['prometheus_listen_addr']
   reload_service false unless Services.enabled?('consul')
 end
 
diff --git a/files/gitlab-cookbooks/praefect/templates/default/praefect-config.toml.erb b/files/gitlab-cookbooks/praefect/templates/default/praefect-config.toml.erb
index c5462b6218a88753422b6e10aa1a697662d8db7e_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC90ZW1wbGF0ZXMvZGVmYXVsdC9wcmFlZmVjdC1jb25maWcudG9tbC5lcmI=..75e2cef04837b969ae959833d3568f1ab80eb3e9_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC90ZW1wbGF0ZXMvZGVmYXVsdC9wcmFlZmVjdC1jb25maWcudG9tbC5lcmI= 100644
--- a/files/gitlab-cookbooks/praefect/templates/default/praefect-config.toml.erb
+++ b/files/gitlab-cookbooks/praefect/templates/default/praefect-config.toml.erb
@@ -4,4 +4,149 @@
 # and run:
 # sudo gitlab-ctl reconfigure
 
-<%= Tomlib.dump(@configuration) %>
+<% if @listen_addr %>
+# TCP address to listen on
+listen_addr = '<%= @listen_addr %>'
+<% end %>
+
+<% if @socket_path %>
+# # Praefect can listen on a socket when placed on the same machine as all clients
+socket_path = '<%= @socket_path %>'
+<% end %>
+
+<% if @prometheus_listen_addr %>
+# Optional: export metrics via Prometheus
+prometheus_listen_addr = '<%= @prometheus_listen_addr %>'
+<% end %>
+
+<% unless @separate_database_metrics.nil? %>
+# Optional: when set to true, metrics that query the database will no longer be
+# available on the /metrics endpoint but will be available on the /db_metrics endpoint
+prometheus_exclude_database_from_default_metrics = <%= @separate_database_metrics %>
+<% end %>
+
+<% if @graceful_stop_timeout %>
+# Optional: The amount of time a graceful shutdown has before forcible interruption. For example "3m", "1m30s".
+graceful_stop_timeout = '<%= @graceful_stop_timeout %>'
+<% end %>
+
+<% if @tls_listen_addr %>
+# Optional: listen on a secure TCP socket
+tls_listen_addr = '<%= @tls_listen_addr %>'
+[tls]
+certificate_path = '<%= @certificate_path %>'
+key_path = '<%= @key_path %>'
+<% end %>
+
+[reconciliation]
+<%= "scheduling_interval = '#{@reconciliation_scheduling_interval}'" if @reconciliation_scheduling_interval %>
+<%= "histogram_buckets = #{@reconciliation_histogram_buckets}" if @reconciliation_histogram_buckets %>
+
+[failover]
+<% unless @failover_enabled.nil? %>
+enabled = <%= @failover_enabled %>
+<% unless @failover_timeout.nil? %>
+timeout = '<%= @failover_timeout %>'
+<% end %>
+<% end %>
+
+[sentry]
+<% if @sentry_dsn %>
+# Optional: emit errors to Sentry
+sentry_dsn = '<%= @sentry_dsn %>'
+<% end %>
+<% if @sentry_environment %>
+sentry_environment = '<%= @sentry_environment %>'
+<% end %>
+
+[auth]
+token = '<%= @auth_token %>'
+transitioning = <%= @auth_transitioning %>
+
+[logging]
+<% if @logging_level %>
+level = '<%= @logging_level %>'
+<% end %>
+<% if @logging_format %>
+format = '<%= @logging_format %>'
+<% end %>
+
+[background_verification]
+<% if @background_verification_verification_interval %>
+verification_interval = '<%= @background_verification_verification_interval %>'
+<% end %>
+<% if @background_verification_delete_invalid_records %>
+delete_invalid_records = <%= @background_verification_delete_invalid_records %>
+<% end %>
+
+<% @virtual_storages.each do |name, config| %>
+[[virtual_storage]]
+name = '<%= name %>'
+<% if config['default_replication_factor'] %>
+default_replication_factor = <%= config['default_replication_factor'] %>
+<% end %>
+<% config['nodes'].each do |storage, node|  %>
+[[virtual_storage.node]]
+storage = '<%= storage %>'
+address = '<%= node['address'] %>'
+token = '<%= node['token'] %>'
+<% end %>
+<% end %>
+
+[database]
+<%= "host = '#{@database_host}'" if @database_host %>
+<%= "port = #{@database_port}" if @database_port %>
+<%= "user = '#{@database_user}'" if @database_user %>
+<%= "password = '#{@database_password}'" if @database_password %>
+<%= "dbname = '#{@database_dbname}'" if @database_dbname %>
+<%= "sslmode = '#{@database_sslmode}'" if @database_sslmode %>
+<%= "sslcert = '#{@database_sslcert}'" if @database_sslcert %>
+<%= "sslkey = '#{@database_sslkey}'" if @database_sslkey %>
+<%= "sslrootcert = '#{@database_sslrootcert}'" if @database_sslrootcert %>
+
+[database.session_pooled]
+<% direct_host = @database_direct_host %>
+<% direct_port = @database_direct_port %>
+<%= "host = '#{direct_host}'" if direct_host %>
+<%= "port = #{direct_port}" if direct_port %>
+<%= "user = '#{@database_direct_user}'" if @database_direct_user %>
+<%= "password = '#{@database_direct_password}'" if @database_direct_password %>
+<%= "dbname = '#{@database_direct_dbname}'" if @database_direct_dbname %>
+<%= "sslmode = '#{@database_direct_sslmode}'" if @database_direct_sslmode %>
+<%= "sslcert = '#{@database_direct_sslcert}'" if @database_direct_sslcert %>
+<%= "sslkey = '#{@database_direct_sslkey}'" if @database_direct_sslkey %>
+<%= "sslrootcert = '#{@database_direct_sslrootcert}'" if @database_direct_sslrootcert %>
+
+<% if @prometheus_grpc_latency_buckets %>
+# # You can optionally configure Gitaly to record histogram latencies on GRPC method calls
+[prometheus]
+grpc_latency_buckets = <%= @prometheus_grpc_latency_buckets %>
+<% end %>
+
+[gitlab]
+<% if @gitlab_url %>
+url = '<%= @gitlab_url %>'
+<% end %>
+<% if @gitlab_relative_path %>
+relative_url_root = '<%= @gitlab_relative_path %>'
+<% end %>
+
+<% if @gitlab_shell['http_settings'] %>
+<% http_settings = @gitlab_shell['http_settings'] %>
+[gitlab.http-settings]
+<% if http_settings['read_timeout'] %>
+read_timeout = <%= http_settings['read_timeout'] %>
+<% end %>
+<% if http_settings['user'] %>
+user = '<%= http_settings['user'] %>'
+<% end %>
+<% if http_settings['password'] %>
+password = '<%= http_settings['password'] %>'
+<% end %>
+<% if http_settings['ca_file'] %>
+ca_file = '<%= http_settings['ca_file'] %>'
+<% end %>
+<% if http_settings['ca_path'] %>
+ca_path = '<%= http_settings['ca_path'] %>'
+<% end %>
+<% end %>
diff --git a/spec/chef/cookbooks/praefect/recipes/praefect_spec.rb b/spec/chef/cookbooks/praefect/recipes/praefect_spec.rb
index c5462b6218a88753422b6e10aa1a697662d8db7e_c3BlYy9jaGVmL2Nvb2tib29rcy9wcmFlZmVjdC9yZWNpcGVzL3ByYWVmZWN0X3NwZWMucmI=..75e2cef04837b969ae959833d3568f1ab80eb3e9_c3BlYy9jaGVmL2Nvb2tib29rcy9wcmFlZmVjdC9yZWNpcGVzL3ByYWVmZWN0X3NwZWMucmI= 100644
--- a/spec/chef/cookbooks/praefect/recipes/praefect_spec.rb
+++ b/spec/chef/cookbooks/praefect/recipes/praefect_spec.rb
@@ -2,7 +2,7 @@
 RSpec.describe 'praefect' do
   let(:chef_run) { ChefSpec::SoloRunner.new(step_into: %w(runit_service env_dir)).converge('gitlab::default') }
   let(:prometheus_grpc_latency_buckets) do
-    [0.001, 0.005, 0.025, 0.1, 0.5, 1.0, 10.0, 30.0, 60.0, 300.0, 1500.0]
+    '[0.001, 0.005, 0.025, 0.1, 0.5, 1.0, 10.0, 30.0, 60.0, 300.0, 1500.0]'
   end
 
   before do
@@ -40,8 +40,8 @@
 
     it 'renders the config.toml' do
       rendered = {
-        'auth' => { 'transitioning' => false },
+        'auth' => { 'token' => '', 'transitioning' => false },
         'listen_addr' => 'localhost:2305',
         'logging' => { 'format' => 'json' },
         'prometheus_listen_addr' => 'localhost:9652',
         'prometheus_exclude_database_from_default_metrics' => true,
@@ -44,5 +44,11 @@
         'listen_addr' => 'localhost:2305',
         'logging' => { 'format' => 'json' },
         'prometheus_listen_addr' => 'localhost:9652',
         'prometheus_exclude_database_from_default_metrics' => true,
+        'sentry' => {},
+        'database' => {
+          'session_pooled' => {},
+        },
+        'reconciliation' => {},
+        'background_verification' => {},
         'failover' => { 'enabled' => true },
@@ -48,4 +54,5 @@
         'failover' => { 'enabled' => true },
+        'gitlab' => { 'relative_url_root' => '', 'url' => 'http+unix://%2Fvar%2Fopt%2Fgitlab%2Fgitlab-workhorse%2Fsockets%2Fsocket' }
       }
 
       expect(chef_run).to render_file(config_path).with_content { |content|
@@ -70,183 +77,6 @@
         .with_content('exec chpst -e /opt/gitlab/etc/praefect/env')
     end
 
-    context 'with defaults overridden with custom configuration' do
-      before do
-        stub_gitlab_rb(
-          {
-            praefect: {
-              enable: true,
-              configuration: {
-                listen_addr: 'custom_listen_addr:5432',
-                prometheus_listen_addr: 'custom_prometheus_listen_addr:5432',
-                logging: {
-                  format: 'custom_format',
-                  has_no_default: 'should get output'
-                },
-                prometheus_exclude_database_from_default_metrics: false,
-                auth: {
-                  transitioning: true
-                },
-                failover: {
-                  enabled: false
-                },
-                virtual_storage: [
-                  {
-                    name: 'default',
-                    node: [
-                      {
-                        storage: 'praefect1',
-                        address: 'tcp://node2.internal',
-                        token: 'praefect2-token'
-                      },
-                      {
-                        storage: 'praefect2',
-                        address: 'tcp://node2.internal',
-                        token: 'praefect2-token'
-                      }
-                    ]
-                  },
-                  {
-                    name: 'virtual-storage-2',
-                    node: [
-                      {
-                        storage: 'praefect3',
-                        address: 'tcp://node3.internal',
-                        token: 'praefect3-token'
-                      },
-                      {
-                        storage: 'praefect4',
-                        address: 'tcp://node4.internal',
-                        token: 'praefect4-token'
-                      }
-                    ]
-                  }
-                ]
-              }
-            }
-          }
-        )
-      end
-
-      it 'renders config.toml' do
-        expect(chef_run).to render_file(config_path).with_content { |content|
-          expect(Tomlrb.parse(content)).to eq(
-            {
-              'auth' => {
-                'transitioning' => true
-              },
-              'failover' => {
-                'enabled' => false
-              },
-              'listen_addr' => 'custom_listen_addr:5432',
-              'logging' => {
-                'format' => 'custom_format',
-                'has_no_default' => 'should get output'
-              },
-              'prometheus_exclude_database_from_default_metrics' => false,
-              'prometheus_listen_addr' => 'custom_prometheus_listen_addr:5432',
-              'virtual_storage' => [
-                {
-                  'name' => 'default',
-                  'node' => [
-                    {
-                      'storage' => 'praefect1',
-                      'address' => 'tcp://node2.internal',
-                      'token' => 'praefect2-token'
-                    },
-                    {
-                      'storage' => 'praefect2',
-                      'address' => 'tcp://node2.internal',
-                      'token' => 'praefect2-token'
-                    }
-                  ]
-                },
-                {
-                  'name' => 'virtual-storage-2',
-                  'node' => [
-                    {
-                      'storage' => 'praefect3',
-                      'address' => 'tcp://node3.internal',
-                      'token' => 'praefect3-token'
-                    },
-                    {
-                      'storage' => 'praefect4',
-                      'address' => 'tcp://node4.internal',
-                      'token' => 'praefect4-token'
-                    }
-                  ]
-                }
-              ]
-            }
-          )
-        }
-      end
-    end
-
-    context 'with old key and its new key set' do
-      before do
-        stub_gitlab_rb(
-          {
-            praefect: {
-              enable: true,
-              database_direct_host: 'database_direct_host_legacy',
-              configuration: {
-                database: {
-                  session_pooled: {
-                    host: 'database_direct_host_new'
-                  }
-                }
-              }
-            }
-          }
-        )
-      end
-
-      it 'raises an error' do
-        expect { chef_run }.to raise_error("Legacy configuration key 'database_direct_host' can't be set when its new key 'configuration.database.session_pooled.host' is set.")
-      end
-    end
-
-    context 'with old virtual_storages and new virtual_storage set' do
-      before do
-        stub_gitlab_rb(
-          {
-            praefect: {
-              enable: true,
-              virtual_storages: {
-                default: {
-                  nodes: {
-                    praefect1: {
-                      address: 'tcp://node1.internal',
-                      token: "praefect1-token"
-                    }
-                  }
-                }
-              },
-              configuration: {
-                virtual_storage: [
-                  {
-                    name: 'default',
-                    node: [
-                      {
-                        storage: 'praefect2',
-                        address: 'tcp://node2.internal',
-                        token: 'praefect2-token'
-                      }
-                    ]
-                  }
-                ]
-              }
-            }
-          }
-        )
-      end
-
-      it 'raises an error' do
-        expect { chef_run }.to raise_error("Legacy configuration key 'virtual_storages' can't be set when its new key 'configuration.virtual_storage' is set.")
-      end
-    end
-
     context 'with custom settings' do
       let(:dir) { nil }
       let(:socket_path) { '/var/opt/gitlab/praefect/praefect.socket' }
@@ -277,6 +107,7 @@
         }
       end
       let(:failover_enabled) { true }
+      let(:failover_timeout) { "30s" }
       let(:database_host) { 'pg.external' }
       let(:database_port) { 2234 }
       let(:database_user) { 'praefect-pg' }
@@ -289,7 +120,8 @@
       let(:database_direct_host) { 'pg.internal' }
       let(:database_direct_port) { 1234 }
       let(:reconciliation_scheduling_interval) { '1m' }
-      let(:reconciliation_histogram_buckets) { [1.0, 2.0] }
+      let(:reconciliation_histogram_buckets) { '[1.0, 2.0]' }
+      let(:gitlab_url) { 'http://localhost:3000' }
       let(:user) { 'user123' }
       let(:password) { 'password321' }
       let(:ca_file) { '/path/to/ca_file' }
@@ -316,6 +148,7 @@
                          logging_level: log_level,
                          logging_format: log_format,
                          failover_enabled: failover_enabled,
+                         failover_timeout: failover_timeout,
                          virtual_storages: virtual_storages,
                          database_host: database_host,
                          database_port: database_port,
@@ -333,12 +166,17 @@
                          background_verification_verification_interval: '168h',
                          background_verification_delete_invalid_records: true,
                          graceful_stop_timeout: graceful_stop_timeout,
-                         # Sanity check that the configuration values get templated out as TOML.
-                         configuration: {
-                           string_value: 'value',
-                           subsection: {
-                             array_value: [1, 2]
-                           },
+                       },
+                       gitlab_rails: {
+                         internal_api_url: gitlab_url
+                       },
+                       gitlab_shell: {
+                         http_settings: {
+                           read_timeout: read_timeout,
+                           user: user,
+                           password: password,
+                           ca_file: ca_file,
+                           ca_path: ca_path
                          }
                        }
                       )
@@ -369,6 +207,7 @@
               },
               'failover' => {
                 'enabled' => true,
+                'timeout' => "30s"
               },
               'logging' => {
                 'format' => 'text',
@@ -393,10 +232,6 @@
               'prometheus_listen_addr' => 'localhost:1234',
               'prometheus_exclude_database_from_default_metrics' => false,
               'socket_path' => '/var/opt/gitlab/praefect/praefect.socket',
-              'string_value' => 'value',
-              'subsection' => {
-                'array_value' => [1, 2]
-              },
               'tls' => {
                 'certificate_path' => '/path/to/cert.pem',
                 'key_path' => '/path/to/key.pem'
@@ -430,6 +265,17 @@
                   ]
                 }
               ],
+              'gitlab' => {
+                'url' => 'http://localhost:3000',
+                'relative_url_root' => '',
+                'http-settings' => {
+                  'read_timeout' => 123,
+                  'user' => 'user123',
+                  'password' => 'password321',
+                  'ca_file' => '/path/to/ca_file',
+                  'ca_path' => '/path/to/ca_path'
+                }
+              },
               'graceful_stop_timeout' => graceful_stop_timeout
             }
           )