# Connect with TLS & mTLS (/learn/guides/connect-with-tls)



<Callout type="info">
  Securing connections applies across every messaging pattern. See the [Messaging Patterns Fundamentals](/learn/concepts) for the conceptual model these guides build on.
</Callout>

## Prerequisites [#prerequisites]

* KubeMQ server configured with TLS certificates
* CA certificate file (for TLS and mTLS)
* Client certificate and key files (for mTLS only)

<Callout type="info">
  Server-side TLS configuration is managed in the KubeMQ deployment.
</Callout>

## TLS Connection [#tls-connection]

Server-side TLS encrypts all traffic between the client and KubeMQ. The client verifies the server's identity using a CA certificate, preventing man-in-the-middle attacks.

### Configure TLS [#configure-tls]

<Tabs groupId="language" items="['Go', 'Python', 'Node.js', 'Java', 'C#', 'Kotlin', 'C++', 'Rust', 'Ruby', 'Elixir']">
  <Tab value="Go">
    ```go title="tls_connect.go"
    package main

    import (
        "context"
        "fmt"
        "log"
        "time"

        "github.com/kubemq-io/kubemq-go/v2"
    )

    func main() {
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()

        client, err := kubemq.NewClient(ctx,
            kubemq.WithAddress("kubemq.example.com", 50000),
            kubemq.WithClientId("secure-client"),
            kubemq.WithTLS("path/to/ca-cert.pem"),
        )
        if err != nil {
            log.Fatalf("TLS connection failed: %v", err)
        }
        defer client.Close()

        info, err := client.Ping(ctx)
        if err != nil {
            log.Fatalf("Ping failed: %v", err)
        }
        fmt.Printf("TLS connected: host=%s version=%s\n", info.Host, info.Version)
    }
    ```
  </Tab>

  <Tab value="Python">
    ```python title="tls_connect.py"
    from kubemq import TLSConfig
    from kubemq.pubsub import Client as PubSubClient

    tls_config = TLSConfig(
        enabled=True,
        ca_file="/path/to/ca.pem",
    )

    with PubSubClient(
        address="kubemq.example.com:50000",
        client_id="secure-client",
        tls=tls_config,
    ) as client:
        info = client.ping()
        print(f"TLS connected: host={info.host}")
    ```
  </Tab>

  <Tab value="Node.js">
    ```typescript title="tls_connect.ts"
    import { KubeMQClient, ConnectionError } from "kubemq-js";

    try {
      const client = await KubeMQClient.create({
        address: "kubemq.example.com:50000",
        clientId: "secure-client",
        tls: {
          enabled: true,
          caCert: "/path/to/ca-cert.pem",
        },
      });

      console.log("TLS connected:", client.state);
      await client.close();
    } catch (err) {
      if (err instanceof ConnectionError) {
        console.error("TLS connection failed:", err.message);
      }
    }
    ```
  </Tab>

  <Tab value="Java">
    ```java title="TlsConnect.java"
    QueuesClient client = QueuesClient.builder()
        .address("kubemq.example.com:50000")
        .clientId("secure-client")
        .tls(true)
        .caCertFile("/path/to/ca.pem")
        .build();

    ServerInfo info = client.ping();
    System.out.println("TLS connected: " + info);
    client.close();
    ```
  </Tab>

  <Tab value="C#">
    ```csharp title="TlsConnect.cs"
    await using var client = new KubeMQClient(new KubeMQClientOptions
    {
        Address = "kubemq.example.com:50000",
        ClientId = "secure-client",
        Tls = new TlsOptions
        {
            Enabled = true,
            CaFile = "/path/to/ca.pem",
        },
    });
    await client.ConnectAsync();

    var info = await client.PingAsync();
    Console.WriteLine($"TLS connected: {info}");
    ```
  </Tab>

  <Tab value="Kotlin">
    ```kotlin title="TlsConnect.kt"
    val client = KubeMQClient.queues {
        address = "kubemq.example.com:50000"
        clientId = "secure-client"
        tls {
            caCertFile = "/path/to/ca.pem"
        }
    }

    client.use {
        val info = it.ping()
        println("TLS connected: host=${info.host}")
    }
    ```
  </Tab>

  <Tab value="C++">
    ```cpp title="tls_connect.cpp"
    #include <kubemq/client.h>
    #include <iostream>

    kubemq::ClientOptions opts;
    opts.address = "kubemq.example.com:50000";
    opts.client_id = "secure-client";
    opts.set_tls_config(kubemq::TlsConfig::FromCertFile("/path/to/ca-cert.pem"));

    kubemq::PubSubClient client(opts);
    auto info = client.ping();
    std::cout << "TLS connected: " << info.host << std::endl;
    ```
  </Tab>

  <Tab value="Rust">
    ```rust title="tls_connect.rs"
    use kubemq::prelude::*;
    use kubemq::TlsConfig;

    #[tokio::main]
    async fn main() -> kubemq::Result<()> {
        let tls = TlsConfig {
            ca_cert_file: Some("/path/to/ca.pem".to_string()),
            ..Default::default()
        };

        let client = KubemqClient::builder()
            .host("kubemq.example.com")
            .port(50000)
            .tls_config(tls)
            .build()
            .await?;

        let info = client.ping().await?;
        println!("TLS connected. Server version: {}", info.version);

        client.close().await?;
        Ok(())
    }
    ```
  </Tab>

  <Tab value="Ruby">
    ```ruby title="tls_connect.rb"
    require 'kubemq'

    tls = KubeMQ::TLSConfig.new(enabled: true, ca_file: '/path/to/ca.pem')

    client = KubeMQ::PubSubClient.new(
      address: 'kubemq.example.com:50000',
      client_id: 'secure-client',
      tls: tls
    )

    info = client.ping
    puts "TLS connected: host=#{info.host}, version=#{info.version}"
    client.close
    ```
  </Tab>

  <Tab value="Elixir">
    ```elixir title="tls_connect.exs"
    {:ok, client} =
      KubeMQ.Client.start_link(
        address: "kubemq.example.com:50000",
        client_id: "secure-client",
        tls: [cacertfile: "/path/to/ca.pem"]
      )

    {:ok, info} = KubeMQ.Client.ping(client)
    IO.puts("TLS connected: version=#{info.version}")

    KubeMQ.Client.close(client)
    ```
  </Tab>
</Tabs>

### Verify Connection [#verify-connection]

After establishing a TLS connection, call `Ping` (or equivalent) to confirm the secure channel is working. A successful ping confirms both network connectivity and certificate validation.

## Mutual TLS (mTLS) [#mutual-tls-mtls]

mTLS extends standard TLS by requiring both the client and server to present certificates. The server verifies the client's identity, and the client verifies the server — establishing bidirectional trust.

### Configure mTLS [#configure-mtls]

<Tabs groupId="language" items="['Go', 'Python', 'Node.js', 'Java', 'C#', 'Kotlin', 'C++', 'Rust', 'Ruby', 'Elixir']">
  <Tab value="Go">
    ```go title="mtls_connect.go"
    client, err := kubemq.NewClient(ctx,
        kubemq.WithAddress("kubemq.example.com", 50000),
        kubemq.WithClientId("mtls-client"),
        kubemq.WithMTLS(
            "path/to/client-cert.pem",
            "path/to/client-key.pem",
            "path/to/ca-cert.pem",
        ),
    )
    if err != nil {
        log.Fatalf("mTLS connection failed: %v", err)
    }
    defer client.Close()

    info, err := client.Ping(ctx)
    if err != nil {
        log.Fatalf("Ping failed: %v", err)
    }
    fmt.Printf("mTLS connected: host=%s\n", info.Host)
    ```
  </Tab>

  <Tab value="Python">
    ```python title="mtls_connect.py"
    from kubemq import TLSConfig
    from kubemq.pubsub import Client as PubSubClient

    tls_config = TLSConfig(
        enabled=True,
        cert_file="/path/to/client-cert.pem",
        key_file="/path/to/client-key.pem",
        ca_file="/path/to/ca.pem",
    )

    with PubSubClient(
        address="kubemq.example.com:50000",
        client_id="mtls-client",
        tls=tls_config,
    ) as client:
        info = client.ping()
        print(f"mTLS connected: host={info.host}")
    ```
  </Tab>

  <Tab value="Node.js">
    ```typescript title="mtls_connect.ts"
    const client = await KubeMQClient.create({
      address: "kubemq.example.com:50000",
      clientId: "mtls-client",
      tls: {
        enabled: true,
        caCert: "/path/to/ca-cert.pem",
        clientCert: "/path/to/client-cert.pem",
        clientKey: "/path/to/client-key.pem",
      },
    });

    console.log("mTLS connected:", client.state);
    await client.close();
    ```
  </Tab>

  <Tab value="Java">
    ```java title="MtlsConnect.java"
    QueuesClient client = QueuesClient.builder()
        .address("kubemq.example.com:50000")
        .clientId("mtls-client")
        .tls(true)
        .caCertFile("/path/to/ca.pem")
        .tlsCertFile("/path/to/client-cert.pem")
        .tlsKeyFile("/path/to/client-key.pem")
        .build();

    ServerInfo info = client.ping();
    System.out.println("mTLS connected: " + info);
    client.close();
    ```
  </Tab>

  <Tab value="C#">
    ```csharp title="MtlsConnect.cs"
    await using var client = new KubeMQClient(new KubeMQClientOptions
    {
        Address = "kubemq.example.com:50000",
        ClientId = "mtls-client",
        Tls = new TlsOptions
        {
            Enabled = true,
            CaFile = "/path/to/ca.pem",
            CertFile = "/path/to/client-cert.pem",
            KeyFile = "/path/to/client-key.pem",
        },
    });
    await client.ConnectAsync();

    var info = await client.PingAsync();
    Console.WriteLine($"mTLS connected: {info}");
    ```
  </Tab>

  <Tab value="Kotlin">
    ```kotlin title="MtlsConnect.kt"
    val client = KubeMQClient.queues {
        address = "kubemq.example.com:50000"
        clientId = "mtls-client"
        tls {
            caCertFile = "/path/to/ca.pem"
            certFile = "/path/to/client-cert.pem"
            keyFile = "/path/to/client-key.pem"
        }
    }

    client.use {
        val info = it.ping()
        println("mTLS connected: host=${info.host}")
    }
    ```
  </Tab>

  <Tab value="C++">
    ```cpp title="mtls_connect.cpp"
    kubemq::ClientOptions opts;
    opts.address = "kubemq.example.com:50000";
    opts.client_id = "mtls-client";
    opts.set_tls_config(kubemq::TlsConfig::FromMutualTls(
        "/path/to/client-cert.pem",
        "/path/to/client-key.pem",
        "/path/to/ca-cert.pem"
    ));

    kubemq::PubSubClient client(opts);
    auto info = client.ping();
    std::cout << "mTLS connected: " << info.host << std::endl;
    ```
  </Tab>

  <Tab value="Rust">
    ```rust title="mtls_connect.rs"
    use kubemq::prelude::*;
    use kubemq::TlsConfig;

    #[tokio::main]
    async fn main() -> kubemq::Result<()> {
        let tls = TlsConfig {
            ca_cert_file: Some("/path/to/ca.pem".to_string()),
            cert_file: Some("/path/to/client-cert.pem".to_string()),
            key_file: Some("/path/to/client-key.pem".to_string()),
            ..Default::default()
        };

        let client = KubemqClient::builder()
            .host("kubemq.example.com")
            .port(50000)
            .tls_config(tls)
            .build()
            .await?;

        let info = client.ping().await?;
        println!("mTLS connected. Server version: {}", info.version);

        client.close().await?;
        Ok(())
    }
    ```
  </Tab>

  <Tab value="Ruby">
    ```ruby title="mtls_connect.rb"
    require 'kubemq'

    tls = KubeMQ::TLSConfig.new(
      enabled: true,
      cert_file: '/path/to/client-cert.pem',
      key_file: '/path/to/client-key.pem',
      ca_file: '/path/to/ca.pem'
    )

    client = KubeMQ::PubSubClient.new(
      address: 'kubemq.example.com:50000',
      client_id: 'mtls-client',
      tls: tls
    )

    info = client.ping
    puts "mTLS connected: host=#{info.host}, version=#{info.version}"
    client.close
    ```
  </Tab>

  <Tab value="Elixir">
    ```elixir title="mtls_connect.exs"
    {:ok, client} =
      KubeMQ.Client.start_link(
        address: "kubemq.example.com:50000",
        client_id: "mtls-client",
        tls: [
          cacertfile: "/path/to/ca.pem",
          certfile: "/path/to/client-cert.pem",
          keyfile: "/path/to/client-key.pem",
          verify: :verify_peer
        ]
      )

    {:ok, info} = KubeMQ.Client.ping(client)
    IO.puts("mTLS connected: version=#{info.version}")

    KubeMQ.Client.close(client)
    ```
  </Tab>
</Tabs>

### When to Use mTLS [#when-to-use-mtls]

| Scenario                   | TLS        | mTLS        |
| -------------------------- | ---------- | ----------- |
| Encrypt traffic in transit | Yes        | Yes         |
| Verify server identity     | Yes        | Yes         |
| Verify client identity     | No         | Yes         |
| Zero-trust network         | —          | Recommended |
| Multi-tenant deployment    | —          | Recommended |
| Internal trusted network   | Sufficient | Optional    |

## Pattern-Specific Notes [#pattern-specific-notes]

<Callout type="info">
  TLS and mTLS configuration is **identical for Events, Events Store, Queues, and RPC**. The secure connection is established once at client creation and applies to all operations performed through that client. You do not need separate TLS configuration per pattern.
</Callout>

## Troubleshooting [#troubleshooting]

<Accordions>
  <Accordion title="Certificate chain validation failed">
    Verify the CA certificate matches the server's certificate issuer:

    ```bash
    openssl verify -CAfile ca-cert.pem server-cert.pem
    ```

    Common causes: expired certificates, wrong CA file, or intermediate CA missing from the chain.
  </Accordion>

  <Accordion title="Client certificate rejected (mTLS)">
    Verify the client certificate and key are a matching pair:

    ```bash
    openssl x509 -noout -modulus -in client-cert.pem | openssl md5
    openssl rsa  -noout -modulus -in client-key.pem  | openssl md5
    ```

    Both commands should output the same MD5 hash. If they differ, the cert and key do not match.
  </Accordion>

  <Accordion title="Connection timeout with TLS">
    TLS typically uses a different port than plaintext. Confirm the server port in your deployment configuration. The default TLS port varies by deployment method.
  </Accordion>
</Accordions>

## Next Steps [#next-steps]

<Cards>
  <Card title="Error Handling" href="/learn/guides/error-handling" description="Handle connection errors and implement retry logic." />

  <Card title="Production Checklist" href="/learn/guides/production-checklist" description="Review all security and reliability settings." />
</Cards>
