Contact Us

Client Authentication in Angie with TLS Certificates

TLS is used everywhere today for secure data transfer, and almost every website runs over HTTPS. Besides encrypting traffic, TLS also lets you authenticate clients by certificate (mTLS). This article sets up that mechanism on the Angie web server.

Video version

A video version of this article is available on YouTube.

How mTLS works

With the standard HTTPS protocol, the server presents a certificate when a connection is established. The handshake negotiates connection parameters (ciphers, symmetric encryption key, protocol versions) and authenticates the server by name.

A certificate is a public key with a signature from a certificate authority (also CA — certificate authority). Each certificate comes with a private key.

The client compares the server name it is connecting to with the name in the certificate, checks the certificate's expiry date, and decides whether to trust the CA that issued it. If any of these checks fails, the connection is considered insecure and the connection process is aborted (unless ignoring these problems is explicitly allowed).

With mutual TLS (mTLS — mutual TLS authentication), the client must also present a certificate in order to gain access to resources on the server. In the simple case, it is enough for the client certificate to be signed by a CA that the server trusts. With a regular HTTPS connection the client already has a list of trusted root CAs; with mTLS, the trusted CA certificate is specified explicitly in the configuration.

So mTLS gives us a way to authenticate the client, but it requires a trusted CA and client certificates.

Preparing certificates

To create client certificates we will use the EasyRSA project, which makes it easy to set up your own certificate authority and issue certificates. Start by installing the package (the commands below use Ubuntu 24.04):

apt install easy-rsa

Next we need to create the configuration for our own CA (we will use the /etc/angie/easy-rsa directory):

make-cadir /etc/angie/easy-rsa

Then move into that directory and start the CA initialization:

cd /etc/angie/easy-rsa
./easyrsa init-pki
./easyrsa build-ca

During setup, set a strong passphrase for encrypting the private key. You can also edit the vars configuration file to tune certificate properties. The values below are examples, of course, and can be changed:

echo 'set_var EASYRSA_DN "ROOTCA"' >> vars
echo 'set_var EASYRSA_KEY_SIZE 4096' >> vars
echo 'set_var EASYRSA_REQ_COUNTRY "RU"' >> vars
echo 'set_var EASYRSA_REQ_PROVINCE "Moscow"' >> vars
echo 'set_var EASYRSA_REQ_CITY "Moscow"' >> vars
echo 'set_var EASYRSA_REQ_ORG "IT Corp"' >> vars
echo 'set_var EASYRSA_REQ_OU "IT"' >> vars
echo 'set_var EASYRSA_REQ_EMAIL "[email protected]"' >> vars

Now we can issue the server certificate and private key pair:

./easyrsa build-server-full server nopass

Copy the resulting pair into Angie's TLS configuration directory (/etc/angie/ssl/). Note that the certificate name from the previous command (server) appears in the paths to the certificate and key:

mkdir /etc/angie/ssl
cp /etc/angie/easy-rsa/pki/issued/server.crt /etc/angie/ssl
cp /etc/angie/easy-rsa/pki/private/server.key /etc/angie/ssl

That completes the server side. All that is left is to generate a certificate and key for the client:

./easyrsa build-client-full client nopass

We also generate a certificate revocation list (CRL — Certificate Revocation List):

./easyrsa gen-crl

With all the necessary certificates created, we can move on to configuring the Angie server.

Configuring mTLS in Angie

Let's set up a test server to verify that mTLS works. The configuration is close to ordinary HTTPS, but has a few extra directives:

server {
  listen 443 ssl;
  server_name server;

  ssl_certificate     /etc/angie/ssl/server.crt;
  ssl_certificate_key /etc/angie/ssl/server.key;
  ssl_client_certificate /etc/angie/easy-rsa/pki/ca.crt;
  ssl_crl /etc/angie/easy-rsa/pki/crl.pem;
  ssl_verify_client  on;

  root /usr/share/angie/html;
}

As you can see, we use the familiar ssl_certificate and ssl_certificate_key directives to point at the server certificate and key. The new mTLS directives are:

  • ssl_client_certificate — our CA certificate (for verifying client certificates);
  • ssl_crl — certificate revocation list (for revoking access).
  • ssl_verify_client — enables client certificate verification.

This configuration turns on strict client certificate verification (ssl_verify_client on). It is also possible to configure certificate checking as optional (optional), or to skip the check entirely while still requesting a certificate (optional_no_ca).

Check and reload the Angie configuration:

angie -t
systemctl reload angie

If the configuration reloads and there are no errors in /var/log/angie/error.log, you can start testing the settings.

Testing the connection

Start with a simple connection test using curl. We need to pass the path to the client certificate file and its key:

curl --head -Lks --cert /etc/angie/easy-rsa/pki/issued/client.crt \
 --key /etc/angie/easy-rsa/pki/private/client.key https://localhost

We also disable verification of the server certificate's validity (since the system does not consider it trusted). A successful request returns a server response with code 200:

HTTP/1.1 200 OK
Server: Angie/1.10.2
Date: Wed, 12 Nov 2025 12:44:41 GMT
...

To use the client certificate in a browser, a few extra steps are needed (the example uses Chrome).

First, prepare a file to import into the browser. The client certificate and key are exported to a PKCS12 file. The openssl utility handles this:

openssl pkcs12 -export \
 -in /etc/angie/easy-rsa/pki/issued/client.crt \
 -inkey /etc/angie/easy-rsa/pki/private/client.key -out client.p12

The export asks for a password — it will be needed to import the certificate into the browser. The resulting file (client.p12) must be copied to the client machine for import.

Open the certificate settings page in Chrome (chrome://settings/certificates). In the certificate management section (Manage certificates), find the personal certificates section (Your certificates) and press the import button (Import). Point it at the client.p12 file and enter the password you set during the openssl export.

When you try to connect, you will be prompted to use the client certificate (you can pick one from the list) and will get a response from the server.

Managing certificates in EasyRSA

By default, EasyRSA certificates are valid for a little over two years (825 days). To renew a certificate when needed, use the renew command with the certificate name. For our server certificate:

./easyrsa renew server

To renew the client certificate:

./easyrsa renew client

If the files were copied to other directories, remember to repeat those steps with the new certificate and key files.

To revoke a client certificate, run the revocation and CRL generation commands:

./easyrsa revoke client
./easyrsa gen-crl

To apply the list, reload the Angie configuration:

systemctl reload angie

We now know the basic operations on certificates issued with EasyRSA.

Summary

We went through the basics of how the mTLS mechanism authenticates the client and server mutually; set up our own CA with the EasyRSA system and obtained certificates for the server and client; and finally configured a server that requires certificate-based authentication. We also covered certificate management in EasyRSA.