For most web applications, HTTPS is now close to mandatory. Angie handles HTTPS traffic efficiently while keeping security high. HTTP/2 and HTTP/3 require an encrypted connection. As usual, though, the configuration carries plenty of detail, which this article works through step by step.
Video version
A video version of this article is available on YouTube.
HTTPS fundamentals
HTTPS is essentially HTTP running on top of a traffic encryption protocol — TLS. Historically, encryption was handled by versions of SSL (Secure Sockets Layer); after version 3.0 it was renamed to TLS (Transport Layer Security).
Only two TLS versions are currently recommended for use: 1.2 and 1.3. QUIC (the transport behind HTTP/3) uses its own analogue of TLS 1.3. Protocol compatibility and capabilities are covered below.
For our purposes, it helps to separate two stages of HTTPS operation:
- connection establishment;
- the request/response data exchange.
The first stage is heavy on the CPU because it relies on asymmetric encryption. The main goal is to cut its cost by applying modern cryptography and long-lived caching of established sessions. The outcome of the first stage is a shared encryption key on both the server and the client, used in the second stage. Setting up a TLS connection adds latency, which newer protocol versions and other optimizations can reduce. The extra latency ranges from 1 RTT (Round Trip Time) to 3 RTT. On reconnection, early data is theoretically possible — in practice, a 0-RTT handshake.
The second stage is the bulk of client–server interaction, where the actual data is transferred. It uses symmetric encryption, which handles large volumes of data efficiently. The cipher here has to be both strong and fast.
TLS rests on a public key infrastructure (PKI — Public Key Infrastructure). Every client ships with a set of preinstalled public keys (certificates) from trusted certificate authorities (CA — Certificate Authority). A server needs its own certificate (and its private key) issued by one of those CAs. The certificate vouches that the server's owner proved control of the domain name, which is the basis for issuing it.
From here on, the certificate is assumed to be already issued. A distinctive feature of Angie is its ACME module, which fully handles automatic certificate issuance and renewal. There is also a set of utilities for working with the free certificate authority Let's Encrypt (and others): Certbot, Acme.sh, Acmebot, and so on.
Before configuring TLS itself, look at how Angie interacts with SSL libraries.
OpenSSL versions
Angie's TLS capabilities depend heavily on the version of the SSL library in use. If you install the standard Angie package from the official repositories, it is most likely built with dynamic linking against the system OpenSSL library. To use other OpenSSL versions or forks (LibreSSL, BoringSSL, etc.), Angie has to be built with the ‑with‑openssl parameter.
The list below maps TLS features to the OpenSSL versions that support them:
- TLS 1.3 — OpenSSL => 1.1.1;
- ALPN (required for HTTP/2) — OpenSSL => 1.0.2;
- QUIC support — BoringSSL, OpenSSL => 3.5 (compatibility mode for older versions).
To check which SSL library Angie uses, run:
angie -V
The output shows the library and its version:
Angie version: Angie/1.9.0
nginx version: nginx/1.27.4
built on Fri, 11 Apr 2025 08:00:48 GMT
built with OpenSSL 3.0.2 15 Mar 2022
The library version tells you which TLS features are available. With that, it is time to move to practical TLS configuration in Angie.
General TLS settings
TLS configuration can be split into two parts: general settings and the site configuration. Although most settings can be applied per site, it usually makes sense to put all the general directives in the http context and leave only certificates, keys, and site-specific settings in the site config. Mozilla's online configurator is a good starting point for HTTPS setup, but do not copy directives from it into production blindly.
The first thing to set is the protocol versions the server will support. The list is defined by the ssl_protocols directive; the default value is:
ssl_protocols TLSv1.2 TLSv1.3;
This value suits most applications, but for readability and explicitness the directive can be added at the http block level. TLS versions determine compatibility with clients (browsers, CLI tools, other library-based clients). A rough list of minimum versions with TLS 1.2 support: Firefox 27, Android 4.4.2, Chrome 31, Edge, IE 11 (Windows 7), Java 8u31, the OpenSSL 1.0.1 library, Opera 20, Safari 9. Detailed TLS protocol support is available on Caniuse.
The second important setting: cipher suites. Their choice determines connection security, compatibility, and what can be negotiated. A cipher suite includes several components:
- Key exchange — key exchange algorithms (DH and its variants);
- Authentication — authentication options (certificate);
- Cipher (bulk data encryption) — the main (symmetric) traffic encryption;
- Message Authentication Code (MAC) — message integrity algorithms (hash functions).
By default the following cipher suite setting is used:
ssl_ciphers HIGH:!aNULL:!MD5;
This setting uses the encryption library's macro for strong algorithms in both the asymmetric and the symmetric phase of the connection. Both certificate types are also supported: RSA and ECDSA.
These suites contain no known-unsafe combinations, so the server's cipher order does not need to take priority; client preferences can be taken into account more flexibly (keep the default: ssl_prefer_server_ciphers off). With broader cipher suites, it is recommended to enable the server's cipher order over the client's (ssl_prefer_server_ciphers on).
For TLS 1.3, keep in mind that the cipher options are fixed; with OpenSSL they can only be controlled through the ssl_conf_command directive. For example:
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256;
The next setting: TLS session caching, which speeds up client reconnections. Angie supports two options: a server-side session cache (ssl_session_cache) and session tickets (ssl_session_tickets), which are stored on the client side.
For the server-side session cache, set the memory zone size, type (shared or dedicated), and name. The session lifetime also needs to be raised to improve the odds of a cache hit.
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 28h;
ssl_session_tickets on;
The specified 10 MB is enough to store roughly 40,000 sessions. A shared cache is common to all worker processes, which maximizes cache hits. Session cache efficiency can be monitored through the API or in Angie Console Light (the "Server zones" section — the ratio of "reuses" to "handshakes").
The TLS buffer size can also be tuned (ssl_buffer_size). The default (16k) matches minimal overhead, but if the goal is to minimize the time it takes to receive and decrypt the first bytes of the response, the buffer can be made smaller (the setting is available in the http and server contexts).
One more setting for cutting latency on repeat connections enables Early Data in TLS 1.3.
ssl_early_data on;
With this extension, the client can send application data right away during connection establishment (0-RTT handshake). Using this method can be risky, though — requests may be subject to a replay attack.
By default, Angie processes HTTPS with the SSL library specified at build time, that is, in user space. There is, however, a way to attach a special kernel module and hand traffic encryption to it. kTLS support appeared in Linux 4.13, but a version of 5.2 or newer is recommended. The main advantage of this approach is the ability to use the sendfile mechanism (SSL_sendfile) for HTTPS sites. sendfile is useful for transferring static files or cached elements.
A performance comparison on kernel 6.8 and OpenSSL 3.0.2 shows kTLS with sendfile about 20% ahead of the normal mode when using AES-256-GCM. The test issued requests for a 1 GB file using TLS 1.3. Do not use kTLS with HTTP/2, though — because of the protocol's behavior, enabling kTLS degrades performance by about 40–50%.
Site configuration
To set up an HTTPS site it is enough to specify the socket, the certificate, and the key. Support for the HTTP/2 and HTTP/3 protocols can be enabled additionally.
Angie supports configuring RSA and ECDSA certificates at the same time. These days, RSA certificates should be used only for compatibility. Practically all clients support ECDSA (the exceptions are Android <= 5.0, IE 11 Win7–8.1, Safari < 9), so it can be used as the only option. RSA certificates have even broader client support, but put a much heavier load on the server on connection. When both types are specified, modern clients will use ECDSA, which is exactly what is needed.
The configuration will look roughly like this:
server {
listen 443 ssl;
http2 on;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/certs/1.ru.rsa.pem;
ssl_certificate_key /etc/ssl/private/1.ru.rsa.key;
ssl_certificate /etc/ssl/certs/1.ru.ecdsa.pem;
ssl_certificate_key /etc/ssl/private/1.ru.ecdsa.key;
add_header Strict-Transport-Security "max-age=63072000" always;
}
Here the site gets HTTPS with HTTP/2 support, and two pairs of directives are specified for the certificate (ssl_certificate) and the key (ssl_certificate_key). If you assemble the certificate chain file yourself, it is important to keep the order of certificates in the file: from leaf to general. That is, the file first holds the certificate for the domain, then an intermediate CA certificate, then a higher-level CA certificate, and so on. Root-level certificates do not need to be specified — they are already on the client device.
The site also has the HSTS header (HTTP Strict Transport Security) set, which instructs browsers to use only HTTPS when accessing this site. Careful: the header has a long lifetime and is cached hard on the browser side, so it should only be set if you are completely sure that HTTP access will not be needed again.
To support the HTTP/3 protocol, an additional socket and the http3 directive are required. For example:
server {
listen 443 ssl;
listen 443 quic reuseport;
http2 on;
http3 on;
server_name example.com www.example.com;
add_header Alt-Svc 'h3=":443"; ma=86400';
add_header Strict-Transport-Security max-age=31536000;
}
In the example above, notice that the listen directive for the quic protocol (the transport for HTTP/3) has the reuseport parameter. This parameter can be specified only once for each socket; it is used to distribute packets between worker processes and, in this case, is required for HTTP/3 operation. In addition, the Alt-Svc header is added, which lets the browser know that the server supports HTTP/3 on UDP port 443. After that, the browser will try to create a QUIC connection and switch to HTTP/3 (and it will also remember h3 support for a day: ma=86400). Therefore, in a regular session with the server, the first requests will be sent over HTTP/2 and only subsequent ones will use HTTP/3. There is also a second method of switching to HTTP/3 — with HTTPS-type DNS records, which are discussed below. The Alt-Svc header is not required for all resources, so it can be enabled only when serving dynamic documents (for example, in location /).
The ssl_certificate and ssl_certificate_key directives support variables. When using variables, it makes sense to use the ssl_certificate_cache directive, which allows caching certificates specified this way. Example configuration:
server {
ssl_certificate $ssl_server_name.crt;
ssl_certificate_key $ssl_server_name.key;
ssl_certificate_cache max=1000 inactive=20s valid=1m;
}
A logical step after successfully configuring HTTPS is an unconditional redirect of all requests from HTTP to HTTPS; the simplest way is a separate server block:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
With such a configuration, all requests to HTTP will be redirected to a fixed domain with the request address and GET parameters preserved.
After making changes to the configuration, do not forget to run:
angie -t
To test the connection you can use the standard curl utility, and for details engage the openssl client:
openssl s_client -servername test.ru -connect test.ru:443
This command will create a connection with the SNI (Server Name Indication) extension, that is, as close as possible to a real browser. The output shows the certificate properties and the negotiated TLS parameters.
To view the properties of a certificate on disk you can also use openssl:
openssl x509 -text -noout -in unk.crt
Of course, you can use the browser's developer tools to view the properties of the TLS connection. It is also useful to use online tests (for example, SSLlabs), which allow testing the server's compatibility by emulating various clients, and also point out potential problems in the configuration (vulnerabilities, weak ciphers, problems with the certificate chain, and so on).
HTTPS records in DNS
In addition to server configuration, DNS can be used for fine-tuning HTTPS. Special HTTPS-type records were designed for these tasks: they contain information about supported protocols and addresses within the domain. For example, support for the HTTP/3 protocol can be declared through such a record in DNS:
example.com 3600 IN HTTPS 1 . alpn=”h3,h2”
Summary
This article covered the main issues of TLS configuration in the Angie web server. Certificate issuance remained out of scope; it deserves a separate look, given the ACME module in Angie. Hopefully this article was useful.