# mTLS Setup (/sdks/java/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.

The builder's `.tls(true)`, `.caCertFile()`, `.tlsCertFile()`, and `.tlsKeyFile()` (or the `.caCertPem()` / `.tlsCertPem()` / `.tlsKeyPem()` byte-array variants) wire in three artifacts at client construction: 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.

**Gotchas:** the certificate and key must be a matched pair signed by a CA the server trusts — a mismatch fails the handshake outright; all three inputs 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
* Java SDK installed (Maven/Gradle dependency `io.kubemq.sdk:kubemq-sdk-Java:3.1.1`)
* TLS certificates (client certificate, client key, and CA certificate)

## Code [#code]

```java title="MtlsSetupExample.java"
package io.kubemq.example.tls;

import io.kubemq.sdk.client.KubeMQClient;
import io.kubemq.sdk.common.ServerInfo;
import io.kubemq.sdk.queues.QueuesClient;

/**
 * Mutual TLS Setup Example
 *
 * Demonstrates establishing a mutual TLS (mTLS) connection to KubeMQ server
 * where both client and server authenticate each other with certificates.
 */
public class MtlsSetupExample {

    private static final String ADDRESS = "localhost:50001";
    private static final String CLIENT_ID = "java-tls-mtls-setup-client";
    private static final String CA_CERT_FILE = "/path/to/ca.pem";
    private static final String CLIENT_CERT_FILE = "/path/to/client.pem";
    private static final String CLIENT_KEY_FILE = "/path/to/client.key";

    public void connectWithMutualTLS() {
        System.out.println("=== Mutual TLS (mTLS) Connection ===\n");

        // Create a client with mTLS (client cert + key + CA cert)
        try (QueuesClient client = QueuesClient.builder()
                .address(ADDRESS)
                .clientId(CLIENT_ID)
                .tls(true)
                .caCertFile(CA_CERT_FILE)
                .tlsCertFile(CLIENT_CERT_FILE)
                .tlsKeyFile(CLIENT_KEY_FILE)
                .logLevel(KubeMQClient.Level.INFO)
                .build()) {

            // Verify mTLS connection
            ServerInfo serverInfo = client.ping();
            System.out.println("Connected with mTLS. Server: " + serverInfo);

        } catch (Exception e) {
            System.err.println("mTLS connection failed: " + e.getMessage());
        }
    }

    public void connectWithMutualTLSFromPemBytes() {
        System.out.println("=== Mutual TLS from PEM bytes ===\n");

        // Load certs from PEM bytes instead of files
        byte[] caCertPem = "-----BEGIN CERTIFICATE-----\n... CA cert ...\n-----END CERTIFICATE-----".getBytes();
        byte[] clientCertPem = "-----BEGIN CERTIFICATE-----\n... client cert ...\n-----END CERTIFICATE-----".getBytes();
        byte[] clientKeyPem = "-----BEGIN PRIVATE KEY-----\n... client key ...\n-----END PRIVATE KEY-----".getBytes();

        try (QueuesClient client = QueuesClient.builder()
                .address(ADDRESS)
                .clientId(CLIENT_ID + "-pem")
                .tls(true)
                .caCertPem(caCertPem)
                .tlsCertPem(clientCertPem)
                .tlsKeyPem(clientKeyPem)
                .build()) {

            ServerInfo serverInfo = client.ping();
            System.out.println("Connected with mTLS (PEM bytes). Server: " + serverInfo);

        } catch (Exception e) {
            System.err.println("mTLS PEM connection failed: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        MtlsSetupExample example = new MtlsSetupExample();
        example.connectWithMutualTLS();
        example.connectWithMutualTLSFromPemBytes();
    }
}
```

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

* The builder with `.tls(true)`, `.caCertFile()`, `.tlsCertFile()`, and `.tlsKeyFile()` enables mutual TLS authentication.
* The server verifies the client's certificate, and the client verifies the server's certificate, establishing bidirectional trust.
* The SDK also supports loading certificates from PEM byte arrays via `.caCertPem()`, `.tlsCertPem()`, and `.tlsKeyPem()` for environments where certificates are stored in memory or secrets managers.
* The `try-with-resources` pattern ensures the client is properly closed after use.

## Related [#related]

* [Java SDK Reference](/sdks/java/reference)
* [TLS Setup](/sdks/java/how-to/tls/tls-setup)
