diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template
index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644
--- a/files/gitlab-config-template/gitlab.rb.template
+++ b/files/gitlab-config-template/gitlab.rb.template
@@ -1803,5 +1803,7 @@
 # gitlab_kas['listen_address'] = 'localhost:8150'
 # gitlab_kas['listen_network'] = 'tcp'
 # gitlab_kas['listen_websocket'] = true
+# gitlab_kas['certificate_file'] = "/path/to/certificate.pem"
+# gitlab_kas['key_file'] = "/path/to/key.pem"
 # gitlab_kas['internal_api_listen_network'] = 'tcp'
 # gitlab_kas['internal_api_listen_address'] = 'localhost:8153'
@@ -1806,3 +1808,5 @@
 # gitlab_kas['internal_api_listen_network'] = 'tcp'
 # gitlab_kas['internal_api_listen_address'] = 'localhost:8153'
+# gitlab_kas['internal_api_certificate_file'] = "/path/to/certificate.pem"
+# gitlab_kas['internal_api_key_file'] = "/path/to/key.pem"
 # gitlab_kas['kubernetes_api_listen_address'] = 'localhost:8154'
@@ -1808,3 +1812,5 @@
 # gitlab_kas['kubernetes_api_listen_address'] = 'localhost:8154'
+# gitlab_kas['kubernetes_api_certificate_file'] = "/path/to/certificate.pem"
+# gitlab_kas['kubernetes_api_key_file'] = "/path/to/key.pem"
 # gitlab_kas['private_api_listen_network'] = 'tcp'
 # gitlab_kas['private_api_listen_address'] = 'localhost:8155'
@@ -1809,5 +1815,7 @@
 # gitlab_kas['private_api_listen_network'] = 'tcp'
 # gitlab_kas['private_api_listen_address'] = 'localhost:8155'
+# gitlab_kas['private_api_certificate_file'] = "/path/to/certificate.pem"
+# gitlab_kas['private_api_key_file'] = "/path/to/key.pem"
 
 ##! Metrics configuration for GitLab KAS
 # gitlab_kas['metrics_usage_reporting_period'] = 60
diff --git a/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb b/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb
index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg==..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg== 100644
--- a/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb
+++ b/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb
@@ -13,5 +13,7 @@
 default['gitlab-kas']['listen_address'] = 'localhost:8150'
 default['gitlab-kas']['listen_network'] = 'tcp'
 default['gitlab-kas']['listen_websocket'] = true
+default['gitlab-kas']['certificate_file'] = nil
+default['gitlab-kas']['key_file'] = nil
 default['gitlab-kas']['internal_api_listen_address'] = 'localhost:8153'
 default['gitlab-kas']['internal_api_listen_network'] = 'tcp'
@@ -16,3 +18,5 @@
 default['gitlab-kas']['internal_api_listen_address'] = 'localhost:8153'
 default['gitlab-kas']['internal_api_listen_network'] = 'tcp'
+default['gitlab-kas']['internal_api_certificate_file'] = nil
+default['gitlab-kas']['internal_api_key_file'] = nil
 default['gitlab-kas']['kubernetes_api_listen_address'] = 'localhost:8154'
@@ -18,4 +22,6 @@
 default['gitlab-kas']['kubernetes_api_listen_address'] = 'localhost:8154'
+default['gitlab-kas']['kubernetes_api_certificate_file'] = nil
+default['gitlab-kas']['kubernetes_api_key_file'] = nil
 default['gitlab-kas']['private_api_secret_key'] = nil
 default['gitlab-kas']['private_api_listen_address'] = 'localhost:8155'
 default['gitlab-kas']['private_api_listen_network'] = 'tcp'
@@ -19,6 +25,8 @@
 default['gitlab-kas']['private_api_secret_key'] = nil
 default['gitlab-kas']['private_api_listen_address'] = 'localhost:8155'
 default['gitlab-kas']['private_api_listen_network'] = 'tcp'
+default['gitlab-kas']['private_api_certificate_file'] = nil
+default['gitlab-kas']['private_api_key_file'] = nil
 default['gitlab-kas']['metrics_usage_reporting_period'] = 60
 default['gitlab-kas']['sentry_dsn'] = nil
 default['gitlab-kas']['sentry_environment'] = nil
diff --git a/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb b/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb
index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3JlY2lwZXMvZW5hYmxlLnJi..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3JlY2lwZXMvZW5hYmxlLnJi 100644
--- a/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb
+++ b/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb
@@ -50,6 +50,17 @@
   end
 end
 
+ruby_block 'websocket TLS termination' do
+  block do
+    message = [
+      "Enabling gitlab-kas API TLS termination and websocket tunnelling at the same time is not supported.",
+      "See <https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/217>"
+    ]
+    LoggingHelper.warning(message.join("\n\n"))
+  end
+  only_if { node['gitlab-kas']['listen_websocket'] && node['gitlab-kas']['certificate_file'] && node['gitlab-kas']['key_file'] }
+end
+
 version_file 'Create version file for Gitlab KAS' do
   version_file_path File.join(working_dir, 'VERSION')
   version_check_cmd '/opt/gitlab/embedded/bin/gitlab-kas --version'
diff --git a/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb b/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb
index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3RlbXBsYXRlcy9kZWZhdWx0L2dpdGxhYi1rYXMtY29uZmlnLnltbC5lcmI=..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3RlbXBsYXRlcy9kZWZhdWx0L2dpdGxhYi1rYXMtY29uZmlnLnltbC5lcmI= 100644
--- a/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb
+++ b/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb
@@ -3,6 +3,10 @@
     address: <%= @listen_address %>
     network: <%= @listen_network %>
     websocket: <%= @listen_websocket %>
+    <%- if @certificate_file and @key_file %>
+    certificate_file: <%= @certificate_file %>
+    key_file: <%= @key_file %>
+    <%- end %>
   configuration:
     poll_period: <%= @agent_configuration_poll_period %>s
   gitops:
@@ -12,6 +16,10 @@
   kubernetes_api:
     listen:
       address: <%= @kubernetes_api_listen_address %>
+      <%- if @kubernetes_api_certificate_file and @kubernetes_api_key_file %>
+      certificate_file: <%= @kubernetes_api_certificate_file %>
+      key_file: <%= @kubernetes_api_key_file %>
+      <%- end %>
     url_path_prefix: /
   info_cache_ttl: <%= @agent_info_cache_ttl %>s
   info_cache_error_ttl: <%= @agent_info_cache_error_ttl %>s
@@ -50,8 +58,12 @@
     network: <%= @internal_api_listen_network %>
     address: <%= @internal_api_listen_address %>
     authentication_secret_file: <%= @authentication_secret_file %>
+    <%- if @internal_api_certificate_file and @internal_api_key_file %>
+    certificate_file: <%= @internal_api_certificate_file %>
+    key_file: <%= @internal_api_key_file %>
+    <%- end %>
 private_api:
   listen:
     network: <%= @private_api_listen_network %>
     address: <%= @private_api_listen_address %>
     authentication_secret_file: <%= @private_api_authentication_secret_file %>
@@ -53,5 +65,9 @@
 private_api:
   listen:
     network: <%= @private_api_listen_network %>
     address: <%= @private_api_listen_address %>
     authentication_secret_file: <%= @private_api_authentication_secret_file %>
+    <%- if @private_api_certificate_file and @private_api_key_file %>
+    certificate_file: <%= @private_api_certificate_file %>
+    key_file: <%= @private_api_key_file %>
+    <%- end %>
diff --git a/spec/chef/recipes/gitlab-kas_spec.rb b/spec/chef/recipes/gitlab-kas_spec.rb
index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_c3BlYy9jaGVmL3JlY2lwZXMvZ2l0bGFiLWthc19zcGVjLnJi..a7ded2feeef93afeed156110e822f9cbf45293e6_c3BlYy9jaGVmL3JlY2lwZXMvZ2l0bGFiLWthc19zcGVjLnJi 100644
--- a/spec/chef/recipes/gitlab-kas_spec.rb
+++ b/spec/chef/recipes/gitlab-kas_spec.rb
@@ -403,6 +403,96 @@
     end
   end
 
+  describe 'TLS listen config' do
+    context 'when all certificates and keys are defined' do
+      before do
+        stub_gitlab_rb(
+          external_url: 'https://gitlab.example.com',
+          gitlab_kas: {
+            enable: true,
+            listen_websocket: false,
+            certificate_file: '/path/to/cert.pem',
+            key_file: '/path/to/key.pem',
+            internal_api_certificate_file: '/path/to/internal-api-cert.pem',
+            internal_api_key_file: '/path/to/internal-api-key.pem',
+            kubernetes_api_certificate_file: '/path/to/kubernetes-api-cert.pem',
+            kubernetes_api_key_file: '/path/to/kubernetes-api-key.pem',
+            private_api_certificate_file: '/path/to/private-api-cert.pem',
+            private_api_key_file: '/path/to/private-api-key.pem'
+          }
+        )
+      end
+
+      it 'correctly renders the KAS config file' do
+        expect(gitlab_kas_config_yml).to(
+          include(
+            agent: hash_including(
+              listen: hash_including(
+                certificate_file: '/path/to/cert.pem',
+                key_file: '/path/to/key.pem'
+              ),
+              kubernetes_api: hash_including(
+                listen: hash_including(
+                  certificate_file: '/path/to/kubernetes-api-cert.pem',
+                  key_file: '/path/to/kubernetes-api-key.pem'
+                )
+              )
+            ),
+            api: {
+              listen: hash_including(
+                certificate_file: '/path/to/internal-api-cert.pem',
+                key_file: '/path/to/internal-api-key.pem'
+              ),
+            },
+            private_api: {
+              listen: hash_including(
+                certificate_file: '/path/to/private-api-cert.pem',
+                key_file: '/path/to/private-api-key.pem'
+              )
+            }
+          )
+        )
+      end
+    end
+
+    context 'when certificate/key bundles are not correctly defined' do
+      before do
+        stub_gitlab_rb(
+          external_url: 'https://gitlab.example.com',
+          gitlab_kas: {
+            enable: true,
+            certificate_file: '/path/to/file.pem',
+            internal_api_certificate_file: '/path/to/file.pem',
+            kubernetes_api_key_file: '/path/to/file.pem',
+            private_api_key_file: '/path/to/file.pem'
+          }
+        )
+      end
+
+      it 'renders no certificate or key configuration' do
+        expect(gitlab_kas_config_yml).not_to(include('/path/to/file.pem'))
+      end
+    end
+
+    context 'when the certificate/key bundle is defined and websocket tunneling is enabled' do
+      before do
+        stub_gitlab_rb(
+          external_url: 'https://gitlab.example.com',
+          gitlab_kas: {
+            enable: true,
+            listen_websocket: true,
+            certificate_file: '/path/to/cert.pem',
+            key_file: '/path/to/key.pem',
+          }
+        )
+      end
+
+      it 'logs a warning' do
+        expect(chef_run).to run_ruby_block('websocket TLS termination')
+      end
+    end
+  end
+
   def chef_run_load_yaml_template(chef_run, path)
     template = chef_run.template(path)
     file_content = ChefSpec::Renderer.new(chef_run, template).content