diff --git a/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb b/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL2dpdGxhYl9yYWlscy5yYg==..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL2dpdGxhYl9yYWlscy5yYg== 100644
--- a/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb
+++ b/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb
@@ -16,6 +16,7 @@
 
 require_relative 'nginx.rb'
 require_relative '../../gitaly/libraries/gitaly.rb'
+require_relative '../../package/libraries/settings_dsl.rb'
 
 module GitlabRails
   ALLOWED_DATABASES = %w[main ci geo].freeze
@@ -162,7 +163,7 @@
         next unless Gitlab[left.first][left.last].nil?
 
         better_value_from_gitlab_rb = Gitlab[right.first][right.last]
-        default_from_attributes = Gitlab['node']['gitlab'][left.first.tr('_', '-')][left.last]
+        default_from_attributes = Gitlab['node']['gitlab'][SettingsDSL::Utils.sanitized_key(left.first)][left.last]
         Gitlab[left.first][left.last] = better_value_from_gitlab_rb || default_from_attributes
       end
 
diff --git a/files/gitlab-cookbooks/gitlab/libraries/logging.rb b/files/gitlab-cookbooks/gitlab/libraries/logging.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL2xvZ2dpbmcucmI=..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL2xvZ2dpbmcucmI= 100644
--- a/files/gitlab-cookbooks/gitlab/libraries/logging.rb
+++ b/files/gitlab-cookbooks/gitlab/libraries/logging.rb
@@ -64,7 +64,7 @@
         puma
         storage-check
       ).each do |runit_sv|
-        Gitlab[runit_sv.tr('-', '_')]['svlogd_prefix'] ||= "#{Gitlab['node']['hostname']} #{runit_sv}: "
+        Gitlab[SettingsDSL::Utils.underscored_form(runit_sv)]['svlogd_prefix'] ||= "#{Gitlab['node']['hostname']} #{runit_sv}: "
       end
     end
   end
diff --git a/files/gitlab-cookbooks/gitlab/libraries/nginx.rb b/files/gitlab-cookbooks/gitlab/libraries/nginx.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL25naW54LnJi..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL25naW54LnJi 100644
--- a/files/gitlab-cookbooks/gitlab/libraries/nginx.rb
+++ b/files/gitlab-cookbooks/gitlab/libraries/nginx.rb
@@ -15,6 +15,8 @@
 # limitations under the License.
 #
 
+require_relative '../../package/libraries/settings_dsl.rb'
+
 module Nginx
   class << self
     def parse_variables
@@ -46,7 +48,7 @@
         # This conditional is required until all services are extracted to
         # their own cookbook. Mattermost exists directly on node while
         # others exists on node['gitlab']
-        service_name_key = right.first.tr('_', '-')
+        service_name_key = SettingsDSL::Utils.sanitized_key(right.first)
         service_attribute_key = right.last
         default_set_gitlab_port = if Gitlab['node']['gitlab'].key?(service_name_key)
                                     Gitlab['node']['gitlab'][service_name_key][service_attribute_key]
@@ -72,7 +74,7 @@
 
     def parse_proxy_headers(app, https)
       values_from_gitlab_rb = Gitlab[app]['proxy_set_headers']
-      dashed_app = app.tr('_', '-')
+      dashed_app = SettingsDSL::Utils.sanitized_key(app)
       default_from_attributes = Gitlab['node']['gitlab'][dashed_app]['proxy_set_headers'].to_hash
 
       default_from_attributes = if https
diff --git a/files/gitlab-cookbooks/gitlab/recipes/default.rb b/files/gitlab-cookbooks/gitlab/recipes/default.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvcmVjaXBlcy9kZWZhdWx0LnJi..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvcmVjaXBlcy9kZWZhdWx0LnJi 100644
--- a/files/gitlab-cookbooks/gitlab/recipes/default.rb
+++ b/files/gitlab-cookbooks/gitlab/recipes/default.rb
@@ -17,6 +17,7 @@
 #
 
 require 'openssl'
+require_relative '../../package/libraries/settings_dsl.rb'
 
 # Default location of install-dir is /opt/gitlab/. This path is set during build time.
 # DO NOT change this value unless you are building your own GitLab packages
@@ -172,7 +173,12 @@
   mattermost
   gitlab-kas
   letsencrypt
-).each do |service|
-  if node[service]["enable"]
-    include_recipe "#{service}::enable"
+).each do |cookbook|
+  # `service_name` variable represents the key used to access the node
+  # attributes corresponding to the service. Will be in underscored or
+  # hyphenated form depending on whether it has been migrated to use the
+  # underscored form yet or not.
+  service_name = SettingsDSL::Utils.sanitized_key(cookbook)
+  if node[service_name]["enable"]
+    include_recipe "#{cookbook}::enable"
   else
@@ -178,5 +184,5 @@
   else
-    include_recipe "#{service}::disable"
+    include_recipe "#{cookbook}::disable"
   end
 end
 # Configure healthcheck if we have nginx or workhorse enabled
diff --git a/files/gitlab-cookbooks/logrotate/libraries/logrotate_helper.rb b/files/gitlab-cookbooks/logrotate/libraries/logrotate_helper.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9sb2dyb3RhdGUvbGlicmFyaWVzL2xvZ3JvdGF0ZV9oZWxwZXIucmI=..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9sb2dyb3RhdGUvbGlicmFyaWVzL2xvZ3JvdGF0ZV9oZWxwZXIucmI= 100644
--- a/files/gitlab-cookbooks/logrotate/libraries/logrotate_helper.rb
+++ b/files/gitlab-cookbooks/logrotate/libraries/logrotate_helper.rb
@@ -85,9 +85,10 @@
 
     logged_services.each do |svc|
       # In `Gitlab.settings`, settings aren't hyphenated, but use underscores.
-      setting_name = svc.tr('-', '_')
+      setting_name = SettingsDSL::Utils.underscored_form(svc)
+      node_attribute_key = SettingsDSL::Utils.sanitized_key(svc)
 
       raise "Service #{svc} was specified in logrotate['services'], but is not a valid service." unless available_settings.include?(setting_name)
 
       parent = available_settings[setting_name][:parent]
       if parent
@@ -89,8 +90,8 @@
 
       raise "Service #{svc} was specified in logrotate['services'], but is not a valid service." unless available_settings.include?(setting_name)
 
       parent = available_settings[setting_name][:parent]
       if parent
-        log_dir = node[parent][svc]['log_directory']
-        options = node['gitlab']['logging'].to_hash.merge(node[parent][svc].to_hash)
+        log_dir = node[parent][node_attribute_key]['log_directory']
+        options = node['gitlab']['logging'].to_hash.merge(node[parent][node_attribute_key].to_hash)
       else
@@ -96,6 +97,6 @@
       else
-        log_dir = node[svc]['log_directory']
-        options = node['gitlab']['logging'].to_hash.merge(node[svc].to_hash)
+        log_dir = node[node_attribute_key]['log_directory']
+        options = node['gitlab']['logging'].to_hash.merge(node[node_attribute_key].to_hash)
       end
 
       services[svc] = {
diff --git a/files/gitlab-cookbooks/monitoring/libraries/prometheus.rb b/files/gitlab-cookbooks/monitoring/libraries/prometheus.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL2xpYnJhcmllcy9wcm9tZXRoZXVzLnJi..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL2xpYnJhcmllcy9wcm9tZXRoZXVzLnJi 100644
--- a/files/gitlab-cookbooks/monitoring/libraries/prometheus.rb
+++ b/files/gitlab-cookbooks/monitoring/libraries/prometheus.rb
@@ -18,6 +18,7 @@
 require_relative 'prometheus_helper.rb'
 require_relative '../../gitlab/libraries/postgresql.rb'
 require_relative '../../gitlab/libraries/redis.rb'
+require_relative '../../package/libraries/settings_dsl.rb'
 
 require 'yaml'
 require 'json'
@@ -25,7 +26,7 @@
 module Prometheus
   class << self
     def services
-      Services.find_by_group('monitoring').map { |name| name.tr('_', '-') }
+      Services.find_by_group('monitoring').map { |name| SettingsDSL::Utils.sanitized_key(name) }
     end
 
     def parse_variables
diff --git a/files/gitlab-cookbooks/package/libraries/config/roles/geo_secondary.rb b/files/gitlab-cookbooks/package/libraries/config/roles/geo_secondary.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9jb25maWcvcm9sZXMvZ2VvX3NlY29uZGFyeS5yYg==..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9jb25maWcvcm9sZXMvZ2VvX3NlY29uZGFyeS5yYg== 100644
--- a/files/gitlab-cookbooks/package/libraries/config/roles/geo_secondary.rb
+++ b/files/gitlab-cookbooks/package/libraries/config/roles/geo_secondary.rb
@@ -14,6 +14,8 @@
 # limitations under the License.
 #
 
+require_relative '../../settings_dsl.rb'
+
 module GeoSecondaryRole
   def self.load_role
     return unless Gitlab['geo_secondary_role']['enable']
@@ -41,7 +43,7 @@
       # If the service is explicitly enabled
       return true if Gitlab[svc]['enable']
       # If the service is auto-enabled, and not explicitly disabled
-      return true if Gitlab[:node]['gitlab'][svc.tr('_', '-')]['enable'] && Gitlab[svc]['enable'].nil?
+      return true if Gitlab[:node]['gitlab'][SettingsDSL::Utils.sanitized_key(svc)]['enable'] && Gitlab[svc]['enable'].nil?
     end
 
     return true if Gitlab['gitaly']['enable'] || (Gitlab[:node]['gitaly']['enable'] && Gitlab['gitaly']['enable'].nil?)
diff --git a/files/gitlab-cookbooks/package/libraries/deprecations.rb b/files/gitlab-cookbooks/package/libraries/deprecations.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9kZXByZWNhdGlvbnMucmI=..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9kZXByZWNhdGlvbnMucmI= 100644
--- a/files/gitlab-cookbooks/package/libraries/deprecations.rb
+++ b/files/gitlab-cookbooks/package/libraries/deprecations.rb
@@ -1,5 +1,6 @@
 require_relative 'object_proxy'
 require_relative 'helpers/logging_helper'
+require_relative 'settings_dsl.rb'
 
 module Gitlab
   class Deprecations
@@ -401,5 +402,5 @@
           config_keys = deprecation[:config_keys].dup
           config_keys.shift if ATTRIBUTE_BLOCKS.include?(config_keys[0])
           key = if config_keys.length == 1
-                  config_keys[0].tr("-", "_")
+                  SettingsDSL::Utils.underscored_form(config_keys[0])
                 elsif config_keys.first.eql?('roles')
@@ -405,3 +406,3 @@
                 elsif config_keys.first.eql?('roles')
-                  "#{config_keys[1].tr('-', '_')}_role"
+                  "#{SettingsDSL::Utils.underscored_form(config_keys[1])}_role"
                 else
@@ -407,5 +408,5 @@
                 else
-                  "#{config_keys[0].tr('-', '_')}['#{config_keys.drop(1).join("']['")}']"
+                  "#{SettingsDSL::Utils.underscored_form(config_keys[0])}['#{config_keys.drop(1).join("']['")}']"
                 end
 
           if type == :deprecation
diff --git a/files/gitlab-cookbooks/package/libraries/helpers/roles_helper.rb b/files/gitlab-cookbooks/package/libraries/helpers/roles_helper.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9oZWxwZXJzL3JvbGVzX2hlbHBlci5yYg==..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9oZWxwZXJzL3JvbGVzX2hlbHBlci5yYg== 100644
--- a/files/gitlab-cookbooks/package/libraries/helpers/roles_helper.rb
+++ b/files/gitlab-cookbooks/package/libraries/helpers/roles_helper.rb
@@ -15,6 +15,8 @@
 # limitations under the License.
 #
 
+require_relative '../settings_dsl.rb'
+
 module RolesHelper
   class << self
     def parse_enabled
@@ -22,7 +24,7 @@
 
       # convert hyphens to underscores to avoid user errors
       # split or space or comma (allow both to avoid user errors)
-      active        = [Gitlab['roles']].flatten.map { |role| role.tr('-', '_') }
+      active        = [Gitlab['roles']].flatten.map { |role| SettingsDSL::Utils.underscored_form(role) }
       valid_roles   = Gitlab.available_roles.keys.map { |key| "#{key}_role" }
       invalid_roles = active - valid_roles
 
diff --git a/files/gitlab-cookbooks/package/libraries/helpers/services_helper.rb b/files/gitlab-cookbooks/package/libraries/helpers/services_helper.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9oZWxwZXJzL3NlcnZpY2VzX2hlbHBlci5yYg==..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9oZWxwZXJzL3NlcnZpY2VzX2hlbHBlci5yYg== 100644
--- a/files/gitlab-cookbooks/package/libraries/helpers/services_helper.rb
+++ b/files/gitlab-cookbooks/package/libraries/helpers/services_helper.rb
@@ -15,6 +15,8 @@
 # limitations under the License.
 #
 
+require_relative '../settings_dsl.rb'
+
 module Services
   ALL_SERVICES = 'all'.freeze
   ALL_GROUPS = 'all-groups'.freeze
@@ -231,7 +233,7 @@
     # @param [String] service_name
     # @return [Array]
     def service_attribute_path(service_name)
-      service = service_name.tr('_', '-')
+      service = SettingsDSL::Utils.sanitized_key(service_name)
 
       return ['monitoring', service] if Gitlab[:node]['monitoring']&.attribute?(service)
       return [service] if Gitlab[:node].attribute?(service)
diff --git a/files/gitlab-cookbooks/package/libraries/settings_dsl.rb b/files/gitlab-cookbooks/package/libraries/settings_dsl.rb
index 30d7ba9bb03aca302a8e32dbbcaf2584886638b7_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9zZXR0aW5nc19kc2wucmI=..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9zZXR0aW5nc19kc2wucmI= 100644
--- a/files/gitlab-cookbooks/package/libraries/settings_dsl.rb
+++ b/files/gitlab-cookbooks/package/libraries/settings_dsl.rb
@@ -135,9 +135,8 @@
 
       target = value[:parent] ? results[value[:parent]] : results
 
-      rkey = key.tr('_', '-')
-      target[rkey] = Gitlab[key]
+      target[Utils.sanitized_key(key)] = Gitlab[key]
     end
 
     # Add the roles the the results
     @available_roles.each do |key, value|
@@ -140,9 +139,8 @@
     end
 
     # Add the roles the the results
     @available_roles.each do |key, value|
-      rkey = key.tr('_', '-')
-      results['roles'][rkey] = Gitlab["#{key}_role"]
+      results['roles'][Utils.sanitized_key(key)] = Gitlab["#{key}_role"]
     end
 
     results
@@ -239,4 +237,26 @@
       @handler
     end
   end
+
+  class Utils
+    class << self
+      def hyphenated_form(key)
+        key.tr('_', '-')
+      end
+
+      def underscored_form(key)
+        key.tr('-', '_')
+      end
+
+      def sanitized_key(key)
+        # Services that have been migrated to use underscored form in Chef code
+        # and no longer needs to be hyphenated.
+        skip_hyphenation = %w[]
+
+        return underscored_form(key) if skip_hyphenation.include?(underscored_form(key))
+
+        hyphenated_form(key)
+      end
+    end
+  end
 end
diff --git a/spec/chef/cookbooks/package/libraries/settings_dsl_spec.rb b/spec/chef/cookbooks/package/libraries/settings_dsl_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..304e21dbf47c3c48fcc77cc5862cde06d22db1e2_c3BlYy9jaGVmL2Nvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9zZXR0aW5nc19kc2xfc3BlYy5yYg==
--- /dev/null
+++ b/spec/chef/cookbooks/package/libraries/settings_dsl_spec.rb
@@ -0,0 +1,25 @@
+require 'chef_helper'
+
+RSpec.describe SettingsDSL::Utils do
+  subject { described_class }
+
+  describe '.hyphenated_form' do
+    it 'returns original string if no underscore exists' do
+      expect(subject.hyphenated_form('foo-bar')).to eq('foo-bar')
+    end
+
+    it 'returns string with underscores replaced by hyphens' do
+      expect(subject.hyphenated_form('foo_bar')).to eq('foo-bar')
+    end
+  end
+
+  describe '.underscored_form' do
+    it 'returns original string if no hyphen exists' do
+      expect(subject.underscored_form('foo_bar')).to eq('foo_bar')
+    end
+
+    it 'returns string with hyphens replaced by underscores' do
+      expect(subject.underscored_form('foo-bar')).to eq('foo_bar')
+    end
+  end
+end