How to Set Up Mutual TLS Between Services
Stand up a private CA, issue server and client certificates, and configure a server to require and verify client certificates so service-to-service calls use mutual TLS. Covers verification and rotation.
What and why
Mutual TLS (mTLS) authenticates both ends of a connection: the client verifies the server certificate as usual, and the server also requires and verifies the client certificate. It is a foundation of zero-trust service-to-service communication, ensuring only trusted workloads can talk to each other.
Prerequisites
- Two services communicating over TLS.
- OpenSSL (or
cfssl/step) installed. - Basic understanding of certificates and keys.
Steps
1. Create a private CA
openssl genrsa -out ca.key 4096
openssl req -x509 -new -key ca.key -days 3650 -out ca.crt -subj '/CN=Internal CA'
This CA signs all internal certificates; both services must trust ca.crt.
2. Issue a server certificate
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj '/CN=orders.internal'
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -out server.crt
Include a Subject Alternative Name matching the service DNS name.
3. Issue a client certificate
Repeat the process with CN=billing.internal to produce client.key and client.crt for the calling service.
4. Require client certificates on the server
With Nginx as the TLS terminator:
server {
listen 443 ssl;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_client_certificate ca.crt;
ssl_verify_client on;
}
ssl_verify_client on rejects connections without a valid client certificate signed by the CA.
5. Present the client certificate
The calling service supplies its certificate on outbound calls:
curl --cacert ca.crt --cert client.crt --key client.key https://orders.internal/api
6. Verify and rotate
Connections without a valid client certificate should be refused. Plan rotation: certificates are short-lived in zero-trust setups, so automate issuance. A service mesh like Istio or a secrets engine like Vault can issue and rotate workload certificates automatically.
Verification
- A request with a valid client certificate succeeds.
- A request without a client certificate is rejected.
- A certificate signed by an untrusted CA is rejected.
Next Steps
Automate certificate lifecycle with a mesh (Istio/Linkerd) or Vault PKI so workloads get short-lived certificates and rotation without manual steps, and enforce mTLS mesh-wide with a strict policy.
Prerequisites
- Two services that communicate over TLS
- OpenSSL installed
- Basic TLS knowledge
Steps
- 1Create a private CA
- 2Issue a server certificate
- 3Issue a client certificate
- 4Require client certificates on the server
- 5Present the client certificate
- 6Verify and rotate