TLS certificates

When Kalix services are exposed to the internet using routes, all requests are served using Transport Layer Security (TLS). By default Kalix will automatically provision a server certificate for you using Let’s Encrypt.

Using TLS ensures that a client can trust that the server they are connecting to is the server that they intended to connect to, and ensures that the connection is encrypted and can’t be tampered with. However, the default configuration doesn’t offer the server any guarantees about the identity of the client. By default, anyone on the internet can connect to your exposed services.

Kalix offers the ability to require clients to supply a valid certificate, as well as the ability to use a custom server provisioned certificate, rather than a certificate automatically provisioned by Let’s Encrypt.

Client certificates

Kalix’s client certificate support, also known as Mutual TLS (mTLS) support, allows you to configure routes to require a client certificate. The supplied certificates will be validated using a trusted Certificate Authority that you supply.

Client certificates allow you to control who can connect to your services, by requiring all clients to present a certificate when they connect. This is a very course grained level of authentication, and is ideal for situations where you only want your service to be accessible to other services that you control.

To enable this, you will need a Certificate Authority (CA) that is capable of issuing client certificates to the clients that you want to consume your Kalix services. Kalix will trust any client certificates issued by that CA, so it’s important to only issue certificates to people or services that you trust.

Many organisations will already have a CA that they can use for this, perhaps using products like HashiCorp Vault or Kubernetes cert-manager. If you already have a way of issuing client certificates from a CA, then to enable this feature, you just need that CA’s certificate, and you can skip the next step.

Creating your own CA

If you don’t have a mechanism for issuing client certificates with a CA, this guide will walk you through the process. We will use the smallstep CLI, a tool that makes it very easy.

First you will need to install the CLI using the instructions linked above.

Then we’ll create a CA certificate and key:

step certificate create --profile root-ca "My Root CA" \
  my-root-ca.crt my-root-ca.key --insecure --no-password

Now that we have the CA, we’ll also create a client certificate. We don’t actually need this to configure the client certificate support in Kalix. Only the CA certificate is needed for that. The client certificate will be used by our client when we try to connect to the service:

step certificate create "My Client" my-client.crt my-client.key \
  --ca my-root-ca.crt --ca-key my-root-ca.key --insecure --no-password

Configuring the CA secret

Now that we have a CA certificate, we can configure it as a secret in Kalix. The type of secret we’re creating is called a TLS CA secret:

kalix secret create tls-ca my-root-ca --cert ./my-root-ca.crt

Configuring a route to use the secret

We now need to configure a route to use a secret. Routes can be created by following the instructions in exposing services to the internet. If you haven’t yet created your route, then using the kalix route create command, you can pass the flag --client-ca-secret my-root-ca when you create it. Otherwise, you can update it:

kalix route update my-route --client-ca-secret my-root-ca

Testing that the service is secured

Your service should now be secured. You can test that it’s secured using curl. Let’s say the URL that your service is exposed on is Try issuing a simple curl request on it:

$ curl -I
curl: (56) OpenSSL SSL_read: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required, errno 0

You can see that curl is reporting that a certificate is required to connect to this service. Now if you have a client certificate issued by the CA handy, like the one created above using smallstep, you can try the same request with the client certificate:

$ curl -I --key my-client.key --cert my-client.crt
HTTP/2 404
content-length: 0
date: Wed, 10 Nov 2021 05:00:59 GMT
server: envoy
x-envoy-upstream-service-time: 19

Unless you have defined HTTP transcoding rules for the root path, your service is expected to respond with 404, as shown above. This verifies that the client certificate was accepted and the service is secured.

Custom server certificates

There may be multiple reasons why you don’t want to use the TLS certificates automatically provisioned by Let’s Encrypt:

  • The domain you want to provision the certificates at has a Certification Authority Authorization (CAA) policy configured in DNS, which does not permit Let’s Encrypt to provision certificates for hostnames at it’s domain, and you don’t want to or can’t change this policy.

  • You want to use certificates that are not publicly trusted, but rather are explicitly configured in your client and server.

Configuring a TLS secret

To configure a custom server TLS secret, you will need the key and certificate for the servers hostname in unencrypted PEM format. Once that has been provisioned, create it by running:

kalix secret create tls my-tls-cert --key ./my-key.pem --cert ./my-cert.pem

Configuring a route to use the secret

Now that you’ve created the secret, you can configure the route to use that certificate to serve requests, by running:

kalix route update my-route --server-certificate-secret my-tls-cert