diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644
--- a/files/gitlab-config-template/gitlab.rb.template
+++ b/files/gitlab-config-template/gitlab.rb.template
@@ -931,6 +931,8 @@
 
 ##! Service name used to register GitLab Workhorse as a Consul service
 # gitlab_workhorse['consul_service_name'] = 'workhorse'
+##! Semantic metadata used when registering GitLab Workhorse as a Consul service
+# gitlab_workhorse['consul_service_meta'] = {}
 
 ################################################################################
 ## GitLab User Settings
@@ -987,6 +989,8 @@
 
 ##! Service name used to register Puma as a Consul service
 # puma['consul_service_name'] = 'rails'
+##! Semantic metadata used when registering Puma as a Consul service
+# puma['consul_service_meta'] = {}
 
 ################################################################################
 ## GitLab Sidekiq
@@ -1029,6 +1033,8 @@
 
 ##! Service name used to register Sidekiq as a Consul service
 # sidekiq['consul_service_name'] = 'sidekiq'
+##! Semantic metadata used when registering Sidekiq as a Consul service
+# sidekiq['consul_service_meta'] = {}
 
 ################################################################################
 ## gitlab-shell
@@ -1439,6 +1445,8 @@
 
 ##! Service name used to register Nginx as a Consul service
 # nginx['consul_service_name'] = 'nginx'
+##! Semantic metadata used when registering NGINX as a Consul service
+# nginx['consul_service_meta'] = {}
 
 ################################################################################
 ## GitLab Logging
@@ -1891,6 +1899,8 @@
 
 ##! Service name used to register Prometheus as a Consul service
 # prometheus['consul_service_name'] = 'prometheus'
+##! Semantic metadata used when registering Prometheus as a Consul service
+# prometheus['consul_service_meta'] = {}
 
 ################################################################################
 ###! **Only needed if Prometheus and Rails are not on the same server.**
@@ -1943,6 +1953,8 @@
 
 ##! Service name used to register Node Exporter as a Consul service
 # node_exporter['consul_service_name'] = 'node-exporter'
+##! Semantic metadata used when registering Node Exporter as a Consul service
+# node_exporter['consul_service_meta'] = {}
 
 ################################################################################
 ## Prometheus Redis exporter
@@ -1964,6 +1976,8 @@
 
 ##! Service name used to register Redis Exporter as a Consul service
 # redis_exporter['consul_service_name'] = 'redis-exporter'
+##! Semantic metadata used when registering Redis Exporter as a Consul service
+# redis_exporter['consul_service_meta'] = {}
 
 ################################################################################
 ## Prometheus Postgres exporter
@@ -1984,6 +1998,8 @@
 
 ##! Service name used to register Postgres Exporter as a Consul service
 # postgres_exporter['consul_service_name'] = 'postgres-exporter'
+##! Semantic metadata used when registering Postgres Exporter as a Consul service
+# postgres_exporter['consul_service_meta'] = {}
 
 ################################################################################
 ## Prometheus PgBouncer exporter (EE only)
@@ -2183,6 +2199,8 @@
 
 ##! Service name used to register Gitaly as a Consul service
 # gitaly['consul_service_name'] = 'gitaly'
+##! Semantic metadata used when registering Gitaly as a Consul service
+# gitaly['consul_service_meta'] = {}
 
 ################################################################################
 ## Praefect
@@ -2263,6 +2281,8 @@
 
 ##! Service name used to register Praefect as a Consul service
 # praefect['consul_service_name'] = 'praefect'
+##! Semantic metadata used when registering Praefect as a Consul service
+# praefect['consul_service_meta'] = {}
 
 ################################################################################
 # Storage check
diff --git a/files/gitlab-cookbooks/consul/resources/consul_service.rb b/files/gitlab-cookbooks/consul/resources/consul_service.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9jb25zdWwvcmVzb3VyY2VzL2NvbnN1bF9zZXJ2aWNlLnJi..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9jb25zdWwvcmVzb3VyY2VzL2NvbnN1bF9zZXJ2aWNlLnJi 100644
--- a/files/gitlab-cookbooks/consul/resources/consul_service.rb
+++ b/files/gitlab-cookbooks/consul/resources/consul_service.rb
@@ -4,6 +4,7 @@
 property :service_name, String, name_property: true
 property :id, String, name_property: true
 property :ip_address, [String, nil], default: nil
+property :meta, [Hash, nil], default: nil
 property :port, [Integer, nil], default: nil
 property :reload_service, [TrueClass, FalseClass], default: true
 
@@ -35,6 +36,8 @@
   # Remove address if advertise_addr is set to allow service to use underlying advertise_addr
   content['service'].delete('address') if node['consul']['configuration']['advertise_addr']
 
+  content['service']['meta'] = new_resource.meta if property_is_set?(:meta)
+
   # Ensure the dir exists but leave permissions to `consul::enable`
   directory node['consul']['config_dir'] do
     recursive true
diff --git a/files/gitlab-cookbooks/gitaly/attributes/default.rb b/files/gitlab-cookbooks/gitaly/attributes/default.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRhbHkvYXR0cmlidXRlcy9kZWZhdWx0LnJi..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRhbHkvYXR0cmlidXRlcy9kZWZhdWx0LnJi 100644
--- a/files/gitlab-cookbooks/gitaly/attributes/default.rb
+++ b/files/gitlab-cookbooks/gitaly/attributes/default.rb
@@ -48,3 +48,4 @@
 default['gitaly']['pack_objects_cache_max_age'] = nil
 default['gitaly']['consul_service_name'] = 'gitaly'
 default['gitaly']['custom_hooks_dir'] = nil
+default['gitaly']['consul_service_meta'] = nil
diff --git a/files/gitlab-cookbooks/gitaly/recipes/enable.rb b/files/gitlab-cookbooks/gitaly/recipes/enable.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRhbHkvcmVjaXBlcy9lbmFibGUucmI=..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRhbHkvcmVjaXBlcy9lbmFibGUucmI= 100644
--- a/files/gitlab-cookbooks/gitaly/recipes/enable.rb
+++ b/files/gitlab-cookbooks/gitaly/recipes/enable.rb
@@ -138,6 +138,7 @@
 
 consul_service node['gitaly']['consul_service_name'] do
   id 'gitaly'
+  meta node['gitaly']['consul_service_meta']
   action Prometheus.service_discovery_action
   socket_address node['gitaly']['prometheus_listen_addr']
   reload_service false unless node['consul']['enable']
diff --git a/files/gitlab-cookbooks/gitlab/attributes/default.rb b/files/gitlab-cookbooks/gitlab/attributes/default.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvYXR0cmlidXRlcy9kZWZhdWx0LnJi..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvYXR0cmlidXRlcy9kZWZhdWx0LnJi 100644
--- a/files/gitlab-cookbooks/gitlab/attributes/default.rb
+++ b/files/gitlab-cookbooks/gitlab/attributes/default.rb
@@ -538,6 +538,7 @@
 default['gitlab']['puma']['exporter_address'] = "127.0.0.1"
 default['gitlab']['puma']['exporter_port'] = 8083
 default['gitlab']['puma']['consul_service_name'] = 'rails'
+default['gitlab']['puma']['consul_service_meta'] = nil
 
 ####
 # ActionCable
@@ -570,6 +571,7 @@
 default['gitlab']['sidekiq']['negate'] = false
 default['gitlab']['sidekiq']['queue_groups'] = ['*']
 default['gitlab']['sidekiq']['consul_service_name'] = 'sidekiq'
+default['gitlab']['sidekiq']['consul_service_meta'] = nil
 
 ###
 # gitlab-shell
@@ -640,6 +642,7 @@
 default['gitlab']['gitlab-workhorse']['image_scaler_max_procs'] = [2, node['cpu']['total'].to_i / 2].max
 default['gitlab']['gitlab-workhorse']['image_scaler_max_filesize'] = 250_000
 default['gitlab']['gitlab-workhorse']['consul_service_name'] = 'workhorse'
+default['gitlab']['gitlab-workhorse']['consul_service_meta'] = nil
 
 ####
 # mailroom
@@ -724,6 +727,7 @@
 
 # Consul
 default['gitlab']['nginx']['consul_service_name'] = 'nginx'
+default['gitlab']['nginx']['consul_service_meta'] = nil
 
 ###
 # Nginx status
diff --git a/files/gitlab-cookbooks/monitoring/attributes/default.rb b/files/gitlab-cookbooks/monitoring/attributes/default.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg==..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg== 100644
--- a/files/gitlab-cookbooks/monitoring/attributes/default.rb
+++ b/files/gitlab-cookbooks/monitoring/attributes/default.rb
@@ -25,6 +25,7 @@
 default['monitoring']['prometheus']['listen_address'] = 'localhost:9090'
 default['monitoring']['prometheus']['alertmanagers'] = nil
 default['monitoring']['prometheus']['consul_service_name'] = 'prometheus'
+default['monitoring']['prometheus']['consul_service_meta'] = nil
 
 ####
 # Prometheus Alertmanager
@@ -57,6 +58,7 @@
 }
 default['monitoring']['node-exporter']['listen_address'] = 'localhost:9100'
 default['monitoring']['node-exporter']['consul_service_name'] = 'node-exporter'
+default['monitoring']['node-exporter']['consul_service_meta'] = nil
 
 ####
 # Redis exporter
@@ -69,6 +71,7 @@
 }
 default['monitoring']['redis-exporter']['listen_address'] = 'localhost:9121'
 default['monitoring']['redis-exporter']['consul_service_name'] = 'redis-exporter'
+default['monitoring']['redis-exporter']['consul_service_meta'] = nil
 
 ####
 # Postgres exporter
@@ -84,6 +87,7 @@
 default['monitoring']['postgres-exporter']['sslmode'] = nil
 default['monitoring']['postgres-exporter']['per_table_stats'] = false
 default['monitoring']['postgres-exporter']['consul_service_name'] = 'postgres-exporter'
+default['monitoring']['postgres-exporter']['consul_service_meta'] = nil
 
 ####
 # PgBouncer exporter
diff --git a/files/gitlab-cookbooks/monitoring/recipes/node-exporter.rb b/files/gitlab-cookbooks/monitoring/recipes/node-exporter.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvbm9kZS1leHBvcnRlci5yYg==..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvbm9kZS1leHBvcnRlci5yYg== 100644
--- a/files/gitlab-cookbooks/monitoring/recipes/node-exporter.rb
+++ b/files/gitlab-cookbooks/monitoring/recipes/node-exporter.rb
@@ -68,6 +68,7 @@
 
 consul_service node['monitoring']['node-exporter']['consul_service_name'] do
   id 'node-exporter'
+  meta node['monitoring']['node-exporter']['consul_service_meta']
   action Prometheus.service_discovery_action
   socket_address node['monitoring']['node-exporter']['listen_address']
   reload_service false unless node['consul']['enable']
diff --git a/files/gitlab-cookbooks/monitoring/recipes/postgres-exporter.rb b/files/gitlab-cookbooks/monitoring/recipes/postgres-exporter.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvcG9zdGdyZXMtZXhwb3J0ZXIucmI=..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvcG9zdGdyZXMtZXhwb3J0ZXIucmI= 100644
--- a/files/gitlab-cookbooks/monitoring/recipes/postgres-exporter.rb
+++ b/files/gitlab-cookbooks/monitoring/recipes/postgres-exporter.rb
@@ -79,6 +79,7 @@
 
 consul_service node['monitoring']['postgres-exporter']['consul_service_name'] do
   id 'postgres-exporter'
+  meta node['monitoring']['postgres-exporter']['consul_service_meta']
   action Prometheus.service_discovery_action
   socket_address node['monitoring']['postgres-exporter']['listen_address']
   reload_service false unless node['consul']['enable']
diff --git a/files/gitlab-cookbooks/monitoring/recipes/prometheus.rb b/files/gitlab-cookbooks/monitoring/recipes/prometheus.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvcHJvbWV0aGV1cy5yYg==..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvcHJvbWV0aGV1cy5yYg== 100644
--- a/files/gitlab-cookbooks/monitoring/recipes/prometheus.rb
+++ b/files/gitlab-cookbooks/monitoring/recipes/prometheus.rb
@@ -97,6 +97,7 @@
 
 consul_service node['monitoring']['prometheus']['consul_service_name'] do
   id 'prometheus'
+  meta node['monitoring']['prometheus']['consul_service_meta']
   action Prometheus.service_discovery_action
   socket_address node['monitoring']['prometheus']['listen_address']
   reload_service false unless node['consul']['enable']
diff --git a/files/gitlab-cookbooks/monitoring/recipes/redis-exporter.rb b/files/gitlab-cookbooks/monitoring/recipes/redis-exporter.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvcmVkaXMtZXhwb3J0ZXIucmI=..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvcmVkaXMtZXhwb3J0ZXIucmI= 100644
--- a/files/gitlab-cookbooks/monitoring/recipes/redis-exporter.rb
+++ b/files/gitlab-cookbooks/monitoring/recipes/redis-exporter.rb
@@ -55,6 +55,7 @@
 
 consul_service node['monitoring']['redis-exporter']['consul_service_name'] do
   id 'redis-exporter'
+  meta node['monitoring']['redis-exporter']['consul_service_meta']
   action Prometheus.service_discovery_action
   socket_address node['monitoring']['redis-exporter']['listen_address']
   reload_service false unless node['consul']['enable']
diff --git a/files/gitlab-cookbooks/praefect/attributes/default.rb b/files/gitlab-cookbooks/praefect/attributes/default.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9hdHRyaWJ1dGVzL2RlZmF1bHQucmI=..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9hdHRyaWJ1dGVzL2RlZmF1bHQucmI= 100644
--- a/files/gitlab-cookbooks/praefect/attributes/default.rb
+++ b/files/gitlab-cookbooks/praefect/attributes/default.rb
@@ -41,3 +41,4 @@
 default['praefect']['certificate_path'] = nil
 default['praefect']['key_path'] = nil
 default['praefect']['consul_service_name'] = 'praefect'
+default['praefect']['consul_service_meta'] = nil
diff --git a/files/gitlab-cookbooks/praefect/recipes/enable.rb b/files/gitlab-cookbooks/praefect/recipes/enable.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9yZWNpcGVzL2VuYWJsZS5yYg==..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wcmFlZmVjdC9yZWNpcGVzL2VuYWJsZS5yYg== 100644
--- a/files/gitlab-cookbooks/praefect/recipes/enable.rb
+++ b/files/gitlab-cookbooks/praefect/recipes/enable.rb
@@ -89,6 +89,7 @@
 
 consul_service node['praefect']['consul_service_name'] do
   id 'praefect'
+  meta node['praefect']['consul_service_meta']
   action Prometheus.service_discovery_action
   socket_address node['praefect']['prometheus_listen_addr']
   reload_service false unless node['consul']['enable']
diff --git a/spec/chef/consul/resources/consul_service_spec.rb b/spec/chef/consul/resources/consul_service_spec.rb
index 094acc958e8e0d18ee8bf9a98979ed6d3a8f0ea0_c3BlYy9jaGVmL2NvbnN1bC9yZXNvdXJjZXMvY29uc3VsX3NlcnZpY2Vfc3BlYy5yYg==..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_c3BlYy9jaGVmL2NvbnN1bC9yZXNvdXJjZXMvY29uc3VsX3NlcnZpY2Vfc3BlYy5yYg== 100644
--- a/spec/chef/consul/resources/consul_service_spec.rb
+++ b/spec/chef/consul/resources/consul_service_spec.rb
@@ -37,6 +37,15 @@
           .not_to notify 'execute[reload consul]'
       end
     end
+
+    context 'with symantic metadata' do
+      let(:chef_run) { runner.converge('test_consul::consul_service_meta') }
+
+      it 'creates the Consul service file' do
+        expect(chef_run).to render_file('/var/opt/gitlab/consul/config.d/node-exporter-service.json')
+          .with_content('{"service":{"name":"node-exporter","address":"10.1.1.1","port":1234,"meta":{"some_key":"value"}}}')
+      end
+    end
   end
 
   context 'delete' do
diff --git a/spec/fixtures/cookbooks/test_consul/recipes/consul_service_meta.rb b/spec/fixtures/cookbooks/test_consul/recipes/consul_service_meta.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0240c6a02fc60797f1095ac5c5d16b6c8e53076b_c3BlYy9maXh0dXJlcy9jb29rYm9va3MvdGVzdF9jb25zdWwvcmVjaXBlcy9jb25zdWxfc2VydmljZV9tZXRhLnJi
--- /dev/null
+++ b/spec/fixtures/cookbooks/test_consul/recipes/consul_service_meta.rb
@@ -0,0 +1,9 @@
+include_recipe 'test_consul::reload_consul'
+
+meta = { some_key: "value" }
+
+consul_service 'node-exporter' do
+  ip_address '0.0.0.0'
+  port 1234
+  meta meta
+end