# How to Configure TLS Mutual Authentication for Secure Communication Between Dragonboat Nodes

> Secure Dragonboat nodes with TLS mutual authentication. Enable mTLS and provide CA Cert Key file paths to encrypt Raft traffic and authenticate nodes.

- Repository: [lni/dragonboat](https://github.com/lni/dragonboat)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Enable mutual TLS in Dragonboat by setting `NodeHostConfig.MutualTLS` to `true` and providing the `CAFile`, `CertFile`, and `KeyFile` paths, which automatically encrypts all Raft traffic and authenticates nodes using the shared Certificate Authority.**

Dragonboat is a high-performance Raft consensus library for Go that protects node-to-node communication through built-in **mutual TLS (mTLS)** support. When you configure TLS mutual authentication for secure communication between Dragonboat nodes, the transport layer automatically encrypts all Raft messages and snapshot streams while verifying that each peer presents a valid certificate signed by a shared Certificate Authority.

## Understanding Dragonboat's Mutual TLS Architecture

Dragonboat implements mTLS at the transport layer, ensuring that both incoming and outgoing connections are authenticated and encrypted without requiring changes to your application logic.

### How the Transport Layer Handles Encryption

In [`internal/transport/tcp.go`](https://github.com/lni/dragonboat/blob/main/internal/transport/tcp.go), the TCP transport checks the `NodeHostConfig.MutualTLS` flag during initialization. When enabled, the transport sets an internal `encrypted` flag that triggers TLS wrapping for all connections.

The listener creation in `tcp.Start` calls `NodeHostConfig.GetServerTLSConfig()` to obtain a `tls.Config` configured with the node's certificate and the shared CA. For outbound connections, `tcp.getConnection` invokes `GetClientTLSConfig(target)`, which builds a client-side TLS configuration that verifies the remote server's certificate against the same CA and sets the `ServerName` field for hostname verification.

### Certificate Validation Flow

Each Dragonboat node requires three files: the CA certificate (`CAFile`), the node's own certificate (`CertFile`), and its private key (`KeyFile`). During the TLS handshake:

1. The server presents its certificate to connecting clients.
2. The client verifies the server certificate against the `CAFile`.
3. In mutual TLS mode, the client also presents its certificate.
4. The server verifies the client certificate against the same `CAFile`.

This bidirectional verification ensures that only nodes with certificates signed by the shared CA can join the Raft cluster.

## Prerequisites for TLS Configuration

Before configuring Dragonboat nodes, you must generate the required certificates. Each node needs a unique certificate/key pair, and all nodes must share the same CA certificate.

### Generating Certificates and CA

Use OpenSSL or a similar tool to create the certificate infrastructure:

```bash

# Generate CA private key and certificate

openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.pem \
  -subj "/CN=Dragonboat-CA"

# Generate node certificate (repeat for each node)

openssl genrsa -out node1.key 4096
openssl req -new -key node1.key -out node1.csr \
  -subj "/CN=dragonboat-node-1"
openssl x509 -req -days 365 -in node1.csr -CA ca.pem -CAkey ca.key \
  -CAcreateserial -out node1.crt

```

Distribute `ca.pem` to all nodes. Each node receives its own `nodeN.crt` and `nodeN.key` files.

## Configuring NodeHostConfig for Mutual TLS

The `NodeHostConfig` struct in [`config/config.go`](https://github.com/lni/dragonboat/blob/main/config/config.go) defines the fields required to enable TLS mutual authentication. Set `MutualTLS` to `true` and provide the paths to your certificate files.

```go
import "github.com/lni/dragonboat/v4/config"

nhConfig := config.NodeHostConfig{
    // Network address for Raft communication
    RaftAddress: "10.0.0.1:63001",
    
    // Enable mutual TLS
    MutualTLS: true,
    
    // Certificate paths - must be accessible to the process
    CAFile:   "/etc/dragonboat/certs/ca.pem",      // Shared CA
    CertFile: "/etc/dragonboat/certs/node1.crt",  // This node's cert
    KeyFile:  "/etc/dragonboat/certs/node1.key",  // This node's private key
    
    // Optional: configure other NodeHost settings
    MaxSendQueueSize: 1024 * 1024,
}

```

The `CAFile` must contain the certificate of the authority that signed all node certificates. The `CertFile` and `KeyFile` contain this specific node's identity.

## Starting a NodeHost with TLS Enabled

Once configured, pass the `NodeHostConfig` to `dragonboat.NewNodeHost`. The transport layer automatically initializes TLS listeners and clients based on the configuration.

```go
import (
    "github.com/lni/dragonboat/v4"
    "github.com/lni/dragonboat/v4/config"
    "github.com/lni/dragonboat/v4/raftio"
)

func main() {
    nhConfig := config.NodeHostConfig{
        RaftAddress: "10.0.0.1:63001",
        MutualTLS:   true,
        CAFile:      "/etc/dragonboat/certs/ca.pem",
        CertFile:    "/etc/dragonboat/certs/node1.crt",
        KeyFile:     "/etc/dragonboat/certs/node1.key",
    }
    
    // Create the NodeHost - TLS is automatically enabled
    nh, err := dragonboat.NewNodeHost(nhConfig, raftio.NewInMemLogDB, nil)
    if err != nil {
        panic(err)
    }
    defer nh.Close()
    
    // Proceed with StartReplica or other operations
    // All Raft traffic will now use mutual TLS
}

```

When `MutualTLS` is true, [`internal/transport/tcp.go`](https://github.com/lni/dragonboat/blob/main/internal/transport/tcp.go) invokes `GetServerTLSConfig` to create the TLS listener and `GetClientTLSConfig` for every outbound connection to peers.

## Verifying TLS Communication

The Dragonboat repository includes tests in [`internal/transport/transport_test.go`](https://github.com/lni/dragonboat/blob/main/internal/transport/transport_test.go) that verify mutual TLS functionality. These tests demonstrate that when `MutualTLS` is enabled, the transport correctly encrypts messages and validates certificates.

To verify your own deployment:

1. Check that nodes can form a cluster and elect a leader.
2. Monitor network traffic to confirm encryption (e.g., using `tcpdump` or Wireshark - traffic should be opaque).
3. Verify that nodes reject connections from clients presenting certificates signed by a different CA.

If a node attempts to connect with an invalid certificate, the TLS handshake will fail in `tcp.getConnection` before any Raft messages are exchanged, preventing unauthorized nodes from joining the cluster.

## Summary

- **Enable mTLS** by setting `NodeHostConfig.MutualTLS` to `true` and providing `CAFile`, `CertFile`, and `KeyFile` paths.
- **Certificate requirements** include a shared CA certificate distributed to all nodes and unique certificate/key pairs for each node.
- **Automatic encryption** occurs in [`internal/transport/tcp.go`](https://github.com/lni/dragonboat/blob/main/internal/transport/tcp.go), which uses `GetServerTLSConfig` for listeners and `GetClientTLSConfig` for outbound connections.
- **No application changes** are required beyond configuration; the transport layer handles all TLS handshakes and certificate validation transparently.

## Frequently Asked Questions

### What files are required to enable mutual TLS in Dragonboat?

You need three files: a `CAFile` containing the Certificate Authority certificate that signed all node certificates, a `CertFile` containing the specific node's certificate, and a `KeyFile` containing the node's private key. All nodes must use the same CA file, but each node requires its own unique certificate and key pair.

### Does enabling MutualTLS affect application-level Raft code?

No. When you configure `NodeHostConfig.MutualTLS`, the encryption and authentication happen entirely within the transport layer in [`internal/transport/tcp.go`](https://github.com/lni/dragonboat/blob/main/internal/transport/tcp.go). Your state machine implementation, Raft configuration, and business logic remain unchanged. The `NewNodeHost` function automatically initializes TLS listeners and clients based on the configuration.

### How does Dragonboat verify peer certificates during cluster membership changes?

During cluster membership changes or regular heartbeat exchanges, when node A connects to node B, the transport layer in `tcp.getConnection` creates a TLS client using `GetClientTLSConfig`. This configuration requires the server (node B) to present a certificate signed by the shared CA. Conversely, node B's listener, created with `GetServerTLSConfig`, requires client certificates signed by the same CA. If verification fails, the connection is rejected before any Raft protocol messages are transmitted.

### Can I use different CAs for different nodes in the same cluster?

No. Dragonboat's mutual TLS implementation requires a shared Certificate Authority across all nodes in the cluster. The `CAFile` specified in `NodeHostConfig` is used to verify both incoming and outgoing connections. If nodes use different CAs, TLS handshakes will fail because nodes cannot verify each other's certificate chains against their local CA file.