etcd’s TLS authentication is fundamentally about ensuring that only authorized clients can talk to your etcd cluster, and that the clients are certain they’re talking to the real etcd.

Let’s see it in action. Imagine you have an etcd cluster running, and you want to connect to it using etcdctl. Without TLS, it’s just etcdctl --endpoints http://localhost:2379 member list. But with TLS, the command becomes significantly more involved, and for good reason.

Here’s a typical setup for a secure connection. We’ll need a Certificate Authority (CA) to sign all our certificates, server certificates for each etcd node, and client certificates for anyone or anything that needs to talk to etcd.

First, the CA. This is the root of trust.

# Generate CA private key
openssl genrsa -out ca.key 2048

# Generate CA certificate
openssl req -x509 -new -nodes -key ca.key -sha256 -days 1825 -out ca.crt -subj "/CN=etcd-ca"

This ca.crt is what all your etcd servers and clients will trust.

Next, the server certificates. Each etcd server needs its own certificate.

# Generate server private key
openssl genrsa -out server.key 2048

# Generate server certificate signing request (CSR)
openssl req -new -key server.key -out server.csr -subj "/CN=etcd-server.example.com" -config openssl.cnf

The openssl.cnf would contain subject alternative names (SANs) to include IP addresses and hostnames the server might be reached at. Crucially, it needs to include the IP addresses and DNS names that clients will use to connect to this etcd node.

# openssl.cnf example snippet
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
C = US
ST = California
L = San Francisco
O = MyCompany
OU = IT
CN = etcd-server.example.com

[v3_req]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = etcd-server.example.com
IP.1 = 192.168.1.10
IP.2 = 10.0.0.5

Then, sign the server CSR with your CA.

# Sign the server CSR with the CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 -extensions v3_req -extfile openssl.cnf

You’d do this for each etcd server, typically with a unique CN and relevant SANs for that server.

Now, for client certificates. These are for etcdctl or other applications.

# Generate client private key
openssl genrsa -out client.key 2048

# Generate client CSR
openssl req -new -key client.key -out client.csr -subj "/CN=etcd-client" -config openssl.cnf

Again, openssl.cnf is important, but for client certs, extendedKeyUsage should be clientAuth.

Sign the client CSR:

# Sign the client CSR with the CA
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256 -extensions v3_req -extfile openssl.cnf

Finally, configure etcd to use these certificates. In your etcd configuration file (e.g., /etc/etcd/etcd.conf.yml or passed as flags), you’d set:

# etcd.conf.yml snippet
client-transport-security:
  cert-file: /etc/etcd/ssl/server.crt
  key-file: /etc/etcd/ssl/server.key
  trusted-ca-file: /etc/etcd/ssl/ca.crt
  auto-tls: false # Important: Set to false if you're manually configuring TLS

peer-transport-security:
  cert-file: /etc/etcd/ssl/server.crt # Often the same as client certs for simplicity
  key-file: /etc/etcd/ssl/server.key
  trusted-ca-file: /etc/etcd/ssl/ca.crt
  auto-tls: false

And when you run etcdctl, you’d use these flags:

ETCDCTL_API=3 etcdctl \
  --endpoints https://etcd-server.example.com:2379 \
  --cacert /path/to/ca.crt \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  member list

Here, cacert tells etcdctl which CA to trust for verifying the server’s identity. cert and key are the client’s own credentials, used by the etcd server to authenticate the client. The endpoints must use https.

The core problem this solves is man-in-the-middle attacks and unauthorized access. Without TLS, anyone on the network could intercept traffic or impersonate an etcd server or client. By requiring certificates signed by a trusted CA, etcd ensures both the server and the client are who they claim to be, and that the communication channel is encrypted. The subjectAltName is critical because it’s what the server certificate is actually validated against; CN alone is often insufficient.

The one thing most people don’t realize is that etcd has two distinct TLS configurations: client-transport-security for client-to-server communication (what etcdctl uses) and peer-transport-security for server-to-server communication within the cluster. While they often use the same certificates, they are independently configurable and serve different purposes. A misconfigured peer-transport-security can lead to cluster instability and nodes failing to join or communicate, even if client access works fine.

Once client-to-server TLS is correctly configured, the next hurdle is often ensuring that your client applications (like Kubernetes API servers or other microservices) are also configured with the correct client certificates and CA to communicate with the etcd cluster.

Want structured learning?

Take the full Etcd course →