# mTLS Setup (/sdks/ruby/how-to/tls/mtls-setup)



## Overview [#overview]

Standard TLS only proves the server's identity — the server itself accepts any client that knows the address and client ID. &#x2A;*Mutual TLS (mTLS)** closes that gap: the client also presents a certificate, so the server verifies who is connecting before accepting the connection. That matters on zero-trust networks and in regulated environments where "reaches the port" isn't an acceptable authorization model — the certificate becomes the credential.

`KubeMQ::TLSConfig.new` with `cert_file`, `key_file`, and `ca_file` wires in three artifacts before creating the client: the CA certificate (to verify the server, same as one-way TLS) plus the client's own certificate and private key (for the server to verify in return). Verification happens during the handshake, before any messaging traffic flows — a failed handshake surfaces as a `KubeMQ::Error`.

**Gotchas:** `cert_file` and `key_file` must be provided as a matched pair — the SDK raises `ConfigurationError` if only one is set; all three files must be valid, unexpired PEM, and expiry breaks connections with no warning; and the CA that signed the *client* cert isn't necessarily the CA that verifies the *server* — mixing them up causes "works with TLS, fails with mTLS" confusion.

## Prerequisites [#prerequisites]

* KubeMQ server running with mTLS enabled
* Ruby SDK installed (`gem install kubemq`)
* Client certificate, private key, and CA certificate files

## Code [#code]

```ruby title="main.rb"
require 'kubemq'

address = ENV.fetch('KUBEMQ_ADDRESS', 'localhost:50000')
cert_file = ENV.fetch('KUBEMQ_CERT_FILE', '/path/to/client.pem')
key_file = ENV.fetch('KUBEMQ_KEY_FILE', '/path/to/client-key.pem')
ca_file = ENV.fetch('KUBEMQ_CA_FILE', '/path/to/ca.pem')

begin
  tls = KubeMQ::TLSConfig.new(
    enabled: true,
    cert_file: cert_file,
    key_file: key_file,
    ca_file: ca_file
  )
  client = KubeMQ::PubSubClient.new(
    address: address,
    client_id: 'mtls-example',
    tls: tls
  )
  puts "Connected with mTLS to #{address}"

  info = client.ping
  puts "Ping OK: host=#{info.host}, version=#{info.version}"
rescue KubeMQ::Error => e
  puts "KubeMQ error: #{e.message}"
ensure
  client&.close
  puts 'Connection closed'
end
```

## How It Works [#how-it-works]

* mTLS requires `cert_file` (client certificate), `key_file` (client private key), and `ca_file` (CA certificate).
* Both the client and server verify each other's certificates — stronger security than TLS alone.
* `cert_file` and `key_file` must be provided as a pair; the SDK raises `ConfigurationError` if only one is set.
* Review timeouts, channel names, and client IDs before running against shared environments.

## Related [#related]

* [Ruby SDK Reference](/sdks/ruby/reference)
* [TLS Setup](/sdks/ruby/how-to/tls/tls-setup)
* [Token Authentication](/sdks/ruby/how-to/connection/token-auth)
