The TLS registry is a Quarkus extension centralizing the TLS configuration for the application. It allows to define the TLS configuration in a single place and to reference it from multiple places in the application.

The TLS extension should be automatically added to your project as soon as you use a compatible extension. For example, if your application uses Quarkus REST, gRPC or reactive routes, the TLS registry is automatically added to your project.

1. Using TLS registry

To configure a TLS connection, and more specifically the key stores and trust stores, you use the quarkus.tls.* properties.

Configuration directly under quarkus.tls is the default configuration that will be used by all the TLS connections in the application. However, you can also have specific configurations for specific connections by using the quarkus.tls.<name>.* properties.

1.1. Configure the HTTP server to use https://

To configure the HTTP server to use HTTPS, you can use the following configuration:

quarkus.tls.key-store.pem.0.cert=server.crt
quarkus.tls.key-store.pem.0.key=server.key
quarkus.http.insecure-requests=disabled # Reject HTTP requests

So you a p12 (PKCS12) key store, use the following configuration:

quarkus.tls.key-store.p12.path=server-keystore.p12
quarkus.tls.key-store.p12.password=secret
quarkus.http.insecure-requests=disabled # Reject HTTP requests

Instead of the default configuration, you can use a named configuration:

quarkus.tls.https.key-store.p12.path=server-keystore.p12
quarkus.tls.https.key-store.p12.password=secret
quarkus.http.insecure-requests=disabled
quarkus.http.tls-configuration-name=https

1.2. Configure a client to use https://

As an example to illustrate client configuration, we will use a gRPC client:

quarkus.tls.trust-store.jks.path=grpc-client-truststore.jks
quarkus.tls.trust-store.jks.password=password

quarkus.grpc.clients.hello.plain-text=false
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true

1.3. Configuring mTLS

To configure mTLS, you need to configure both the server and the client. Both will receive a key store and a trust store:

  • the server key store contains the server certificate and private key

  • the client key store contains the client certificate and private key

  • the server trust store contains the client certificate (to authenticate the client)

  • the client trust store contains the server certificate (to authenticate the server)

quarkus.tls.my-server.key-store.p12.path=target/certs/grpc-keystore.p12
quarkus.tls.my-server.key-store.p12.password=password
quarkus.tls.my-server.trust-store.p12.path=target/certs/grpc-server-truststore.p12
quarkus.tls.my-server.trust-store.p12.password=password

quarkus.tls.my-client.trust-store.p12.path=target/certs/grpc-client-truststore.p12
quarkus.tls.my-client.trust-store.p12.password=password
quarkus.tls.my-client.key-store.p12.path=target/certs/grpc-client-keystore.p12
quarkus.tls.my-client.key-store.p12.password=password

quarkus.grpc.clients.hello.plain-text=false
quarkus.grpc.clients.hello.tls-configuration-name=my-client
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true

quarkus.http.ssl.client-auth=REQUIRED # Enable mTLS
quarkus.http.insecure-requests=disabled
quarkus.http.tls-configuration-name=my-server
quarkus.grpc.server.use-separate-server=false
quarkus.grpc.server.plain-text=false

2. Referencing a TLS configuration

Once you have configured a named configuration using quarkus.tls.<name>, you need to reference it. This is done using the tls-configuration-name property:

quarkus.tls.https.key-store.p12.path=server-keystore.p12
quarkus.tls.https.key-store.p12.password=secret

quarkus.http.insecure-requests=disabled
quarkus.http.tls-configuration-name=https # Reference the named configuration

3. Configuring TLS

Configuring TLS is mainly about key stores and trust stores. The configuration depends on the format (pem, p12, jks…​). There are other important properties too. This section details the various properties you can use to configure TLS.

3.1. Key stores

Key stores are used to store the private key and the certificate. They are mainly used on the server-side, but can also be used on the client-side when mTLS is used.

3.1.1. PEM key stores

PEM key stores are composed of a list of pair of two files: the certificate and the private key. The certificate file is a .crt or .pem file, and the private key file is often a .key file.

To configure a PEM key store, use the following properties:

quarkus.tls.key-store.pem.a.cert=server.crt
quarkus.tls.key-store.pem.a.key=server.key
quarkus.tls.key-store.pem.b.cert=my-second-cert.crt
quarkus.tls.key-store.pem.b.key=my-second-key.key

In general, you will only need one pair of certificate and private key. The certificate may contain multiple certificates (a chain), but there should be one private key.

When multiple pairs are configured, the selection is done using SNI (Server Name Indication). The client will send the server name it wants to connect to, and the server will select the appropriate pair of certificate and private key. Make sure SNI is enabled on both the client and server to use this feature.

When configuring multiple key/cert pairs, the order is following the lexicographical order of the name (a and b in the previous snippet). So, the first pair is the one with the lowest lexicographical order. You can define the order by using the quarkus.tls.key-store.pem.order property, for example: quarkus.tls.key-store.pem.order=b,c,a. This is important when using SNI, as the first pair is the default one.

3.1.2. PKCS12 key stores

PKCS12 key stores are a single file containing the certificate and the private key. To configure a PKCS12 key store, use the following properties:

quarkus.tls.key-store.p12.path=server-keystore.p12
quarkus.tls.key-store.p12.password=secret

.p12 files are password-protected, so you need to provide the password to open the key store. Also, they can include more than one certificate and private key. In this case, you can:

  • either provide the alias of the certificate and private key you want to use

  • or use SNI to select the appropriate certificate and private key (all keys must use the same password)

To configure the alias, use the following properties:

quarkus.tls.key-store.p12.path=server-keystore.p12
quarkus.tls.key-store.p12.password=secret
quarkus.tls.key-store.p12.alias=my-alias
quarkus.tls.key-store.p12.alias-password=my-alias-password

3.1.3. JKS key stores

JKS key stores are a single file containing the certificate and the private key. Note that the JKS format should be avoided as it is less secure than PKCS12. To configure a JKS key store, use the following properties:

quarkus.tls.key-store.jks.path=server-keystore.jks
quarkus.tls.key-store.jks.password=secret

.jks files are password-protected, so you need to provide the password to open the key store. Also, they can include more than one certificate and private key. In this case, you can:

  • either provide the alias of the certificate and private key you want to use

  • or use SNI to select the appropriate certificate and private key (all keys must use the same password)

To configure the alias, use the following properties:

quarkus.tls.key-store.jks.path=server-keystore.jks
quarkus.tls.key-store.jks.password=secret
quarkus.tls.key-store.jks.alias=my-alias
quarkus.tls.key-store.jks.alias-password=my-alias-password

3.1.4. SNI

Server Name Indication (SNI) is a TLS extension that allows a client to specify the hostname it is attempting to connect to during the TLS handshake. It enables a server to present different TLS certificates for multiple domains on a single IP address, facilitating secure communication for virtual hosting scenarios.

To enable SNI, use the following property:

quarkus.tls.key-store.sni=true # Disabled by default

With this setting enabled, the client indicate the server name during the TLS handshake, allowing the server to select the right certificate:

  • When configuring the keystore with PEM files, multiple CRT/Key must be given.

  • When configuring the keystore with a JKS or a P12 file, it selects one alias based on the SNI hostname. In this case, all the keystore password and alias password must be the same. Do not set the alias property in this case.

3.1.5. Credential providers

Instead of passing the key store password and alias password in the configuration, you can use a credential provider.

A credential provider offers a way to retrieve the key store password and alias password. Note that the credential provider is only used if the password / alias password are not set in the configuration.

To configure a credential provider, use the following properties:

# The name of the credential bucket in the credentials provider
quarkus.tls.key-store.credentials-provider.name=my-credentials

# The name of the bean providing the credential provider (optional, using the default credential provider if not set)
quarkus.tls.key-store.credentials-provider.bean-name=my-credentials-provider

# The key used to retrieve the key store password, `password` by default
quarkus.tls.key-store.credentials-provider.password-key=password

# The key used to retrieve the alias password, `alias-password` by default
quarkus.tls.key-store.credentials-provider.alias-password-key=alias-password
The credential provider can only be used with PKCS12 and JKS key stores.

3.2. Trust stores

Trust stores are used to store the certificates of the trusted parties. They are generally used on the client-side, and on the server-side when mTLS is used.

3.2.1. PEM trust stores

PEM trust stores are composed of a list of .crt or .pem files. Each of them contains a certificate.

To configure a PEM trust store, use the following properties:

quarkus.tls.trust-store.pem.certs=ca.crt,ca2.pem

3.2.2. PKCS12 trust stores

PKCS12 trust stores are a single file containing the certificates. When multiple certificates are included, you can use the alias to select the appropriate certificate.

To configure a PKCS12 trust store, use the following properties:

quarkus.tls.trust-store.p12.path=client-truststore.p12
quarkus.tls.trust-store.p12.password=password
quarkus.tls.trust-store.p12.alias=my-alias

.p12 files are password-protected, so you need to provide the password to open the trust store. However, unlike for key stores, the alias does not require a password (because it’s the public certificate and not a private key).

3.2.3. JKS trust stores

JKS trust stores are a single file containing the certificates. When multiple certificates are included, you can use the alias to select the appropriate certificate. Note that the JKS format should be avoided as it is less secure than PKCS12.

To configure a JKS trust store, use the following properties:

quarkus.tls.trust-store.jks.path=client-truststore.jks
quarkus.tls.trust-store.jks.password=password
quarkus.tls.trust-store.jks.alias=my-alias

.jks files are password-protected, so you need to provide the password to open the trust store. However, unlike for key stores, the alias does not require a password (because it’s the public certificate and not a private key).

3.2.4. Credential providers

Instead of passing the trust store password in the configuration, you can use a credential provider.

A credential provider offers a way to retrieve passwords and other credentials. Note that the credential provider is only used if the password is not set in the configuration.

To configure a credential provider, use the following properties:

# The name of the credential bucket in the credentials provider
quarkus.tls.trust-store.credentials-provider.name=my-credentials

# The name of the bean providing the credential provider (optional, using the default credential provider if not set)
quarkus.tls.trust-store.credentials-provider.bean-name=my-credentials-provider

# The key used to retrieve the trust store password, `password` by default
quarkus.tls.trust-store.credentials-provider.password-key=password
The credential provider can only be used with PKCS12 and JKS trust stores.

3.3. Other properties

While key stores and trust stores are the most important properties, there are other properties you can use to configure TLS.

while the following examples use the default configuration, you can use the named configuration by prefixing the properties with the name of the configuration.

3.3.1. Cipher suites

The cipher suites are the list of ciphers that can be used during the TLS handshake. You can configure the ordered list of enabled cipher suites. If not configured, a reasonable default is selected from the built-in ciphers. However, when configured, it takes precedence over the default suite defined by the SSL engine in use.

To configure the cipher suites, use the following property:

quarkus.tls.cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384

3.3.2. TLS protocol versions

The TLS protocol versions are the list of protocols that can be used during the TLS handshake. You can configure the ordered list of enabled TLS protocols. If not configured , it defaults to TLSv1.3, TLSv1.2.

Are supported: TLSv1, TLSv1.1, TLSv1.2, TLSv1.3.

To only enable TLSv1.3, configure the following property:

quarkus.tls.protocols=TLSv1.3

3.3.3. Handshake timeout

When a TLS connection is established, the handshake phase is the first step. During this phase, the client and server exchange information to establish the connection, typically the cipher suite, the TLS protocol version, the certification validation and so on.

To configure the timeout for the handshake phase, use the following property:

quarkus.tls.handshake-timeout=10S # Default.

3.3.4. ALPN

Application-Layer Protocol Negotiation (ALPN) is a TLS extension that allows the client and server during the TLS handshake to negotiate which protocol they will use for communication. ALPN enables more efficient communication by allowing the client to indicate its preferred application protocol to the server before the TLS connection is established.

This helps in scenarios such as HTTP/2 where multiple protocols may be available, allowing for faster protocol selection.

ALPN is enabled by default. To disable it, use the following property:

quarkus.tls.alpn=false

3.3.5. Certificate Revocation List (CRL)

A Certificate Revocation List (CRL) is a list of certificates that have been revoked by the issuing Certificate Authority (CA) before their scheduled expiration date. When a certificate is compromised, no longer needed, or deemed invalid for any reason, the CA adds it to the CRL to inform relying parties not to trust the certificate anymore.

You can configure the CRL with the list of certificate files you do not trust anymore. Two formats are allowed: DER and PKCS#7 (also known as P7B).

  • When using the DER format, you must pass DER-encoded CRLs.

  • When using the PKCS#7 format, you must pass PKCS#7 SignedData object, with the only significant field being crls.

To configure the CRL, use the following property:

quarkus.tls.certificate-revocation-list=ca.crl, ca2.crl

3.3.6. Trusting all certificates and hostname verification

These two properties should not be used in production.

You can configure your TLS connection to trust all certificates and to disable the hostname verification. These are two different steps:

  • trusting all certificates ignores the certificate validation, so all certificates are trusted. It is useful for testing with self-signed certificates, but should not be used in production.

  • hostname verification is the process of verifying the server’s identity. It is useful to prevent man-in-the-middle attacks. It often defaults to HTTPS or LDAPS.

To trust all certificates, use the following property:

quarkus.tls.trust-all=true

To disable the hostname verification, use the following property:

quarkus.tls.hostname-verification-algorithm=NONE

3.4. Configuration reference

The following table lists the supported properties:

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

quarkus.tls.lets-encrypt.enabled

Set to true to enable let’s encrypt support.

Environment variable: QUARKUS_TLS_LETS_ENCRYPT_ENABLED

boolean

false

quarkus.tls.key-store.pem.order

The order of the key/cert files, based on the names in the keyCerts map.

By default, Quarkus sorts the key using a lexicographical order. This property allows you to specify the order of the key/cert files.

Environment variable: QUARKUS_TLS_KEY_STORE_PEM_ORDER

list of string

quarkus.tls.key-store.p12.path

Path to the key store file (P12 / PFX format).

Environment variable: QUARKUS_TLS_KEY_STORE_P12_PATH

path

required

quarkus.tls.key-store.p12.password

Password of the key store. When not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS_KEY_STORE_P12_PASSWORD

string

quarkus.tls.key-store.p12.alias

Alias of the private key and certificate in the key store.

Environment variable: QUARKUS_TLS_KEY_STORE_P12_ALIAS

string

quarkus.tls.key-store.p12.alias-password

Password of the alias in the key store. If not set, the password will be retrieved from the credential provider.

Environment variable: QUARKUS_TLS_KEY_STORE_P12_ALIAS_PASSWORD

string

quarkus.tls.key-store.p12.provider

Provider of the key store.

Environment variable: QUARKUS_TLS_KEY_STORE_P12_PROVIDER

string

quarkus.tls.key-store.jks.path

Path to the keystore file (JKS format).

Environment variable: QUARKUS_TLS_KEY_STORE_JKS_PATH

path

required

quarkus.tls.key-store.jks.password

Password of the key store. When not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS_KEY_STORE_JKS_PASSWORD

string

quarkus.tls.key-store.jks.alias

Alias of the private key and certificate in the key store.

Environment variable: QUARKUS_TLS_KEY_STORE_JKS_ALIAS

string

quarkus.tls.key-store.jks.alias-password

Password of the alias in the key store. When not set, the password may be retrieved from the credential provider.

Environment variable: QUARKUS_TLS_KEY_STORE_JKS_ALIAS_PASSWORD

string

quarkus.tls.key-store.jks.provider

Provider of the key store.

Environment variable: QUARKUS_TLS_KEY_STORE_JKS_PROVIDER

string

quarkus.tls.key-store.sni

Enables Server Name Indication (SNI).

Server Name Indication (SNI) is a TLS extension that allows a client to specify the hostname it is attempting to connect to during the TLS handshake. This enables a server to present different SSL certificates for multiple domains on a single IP address, facilitating secure communication for virtual hosting scenarios.

With this setting enabled, the client indicate the server name during the TLS handshake, allowing the server to select the right certificate.

When configuring the keystore with PEM files, multiple CRT/Key must be given. When configuring the keystore with a JKS or a P12 file, it selects one alias based on the SNI hostname. In this case, all the keystore password and alias password must be the same (configured with the password and alias-password properties. Do not set the alias property.

Environment variable: QUARKUS_TLS_KEY_STORE_SNI

boolean

false

quarkus.tls.key-store.credentials-provider.name

The name of the "credential" bucket (map key → passwords) to retrieve from the io.quarkus.credentials.CredentialsProvider. If not set, the credential provider will not be used.

A credential provider offers a way to retrieve the key store password as well as alias password. Note that the credential provider is only used if the passwords are not set in the configuration.

Environment variable: QUARKUS_TLS_KEY_STORE_CREDENTIALS_PROVIDER_NAME

string

quarkus.tls.key-store.credentials-provider.bean-name

The name of the bean providing the credential provider.

The name is used to select the credential provider to use. The credential provider must be exposed as a CDI bean and with the @Named annotation set to the configured name to be selected.

If not set, the default credential provider is used.

Environment variable: QUARKUS_TLS_KEY_STORE_CREDENTIALS_PROVIDER_BEAN_NAME

string

quarkus.tls.key-store.credentials-provider.password-key

The key used to retrieve the key store password.

If the selected credential provider does not support the key, the password is not retrieved. Otherwise, the retrieved value is used to open the key store.

Environment variable: QUARKUS_TLS_KEY_STORE_CREDENTIALS_PROVIDER_PASSWORD_KEY

string

password

quarkus.tls.key-store.credentials-provider.alias-password-key

The key used to retrieve the key store alias password.

If the selected credential provider does not contain the key, the alias password is not retrieved. Otherwise, the retrieved value is used to access the alias private key from the key store.

Environment variable: QUARKUS_TLS_KEY_STORE_CREDENTIALS_PROVIDER_ALIAS_PASSWORD_KEY

string

alias-password

quarkus.tls.trust-store.pem.certs

List of the trusted cert paths (Pem format).

Environment variable: QUARKUS_TLS_TRUST_STORE_PEM_CERTS

list of path

quarkus.tls.trust-store.p12.path

Path to the trust store file (P12 / PFX format).

Environment variable: QUARKUS_TLS_TRUST_STORE_P12_PATH

path

required

quarkus.tls.trust-store.p12.password

Password of the trust store. If not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS_TRUST_STORE_P12_PASSWORD

string

quarkus.tls.trust-store.p12.alias

Alias of the trust store.

Environment variable: QUARKUS_TLS_TRUST_STORE_P12_ALIAS

string

quarkus.tls.trust-store.p12.provider

Provider of the trust store.

Environment variable: QUARKUS_TLS_TRUST_STORE_P12_PROVIDER

string

quarkus.tls.trust-store.jks.path

Path to the trust store file (JKS format).

Environment variable: QUARKUS_TLS_TRUST_STORE_JKS_PATH

path

required

quarkus.tls.trust-store.jks.password

Password of the trust store. If not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS_TRUST_STORE_JKS_PASSWORD

string

quarkus.tls.trust-store.jks.alias

Alias of the key in the trust store.

Environment variable: QUARKUS_TLS_TRUST_STORE_JKS_ALIAS

string

quarkus.tls.trust-store.jks.provider

Provider of the trust store.

Environment variable: QUARKUS_TLS_TRUST_STORE_JKS_PROVIDER

string

quarkus.tls.trust-store.credentials-provider.name

The name of the "credential" bucket (map key → passwords) to retrieve from the io.quarkus.credentials.CredentialsProvider. If not set, the credential provider will not be used.

A credential provider offers a way to retrieve the key store password as well as alias password. Note that the credential provider is only used if the passwords are not set in the configuration.

Environment variable: QUARKUS_TLS_TRUST_STORE_CREDENTIALS_PROVIDER_NAME

string

quarkus.tls.trust-store.credentials-provider.bean-name

The name of the bean providing the credential provider.

The name is used to select the credential provider to use. The credential provider must be exposed as a CDI bean and with the @Named annotation set to the configured name to be selected.

If not set, the default credential provider is used.

Environment variable: QUARKUS_TLS_TRUST_STORE_CREDENTIALS_PROVIDER_BEAN_NAME

string

quarkus.tls.trust-store.credentials-provider.password-key

The key used to retrieve the trust store password.

If the selected credential provider does not contain the configured key, the password is not retrieved. Otherwise, the retrieved value is used to open the trust store.

Environment variable: QUARKUS_TLS_TRUST_STORE_CREDENTIALS_PROVIDER_PASSWORD_KEY

string

password

quarkus.tls.cipher-suites

Sets the ordered list of enabled cipher suites. If none is given, a reasonable default is selected from the built-in ciphers.

When suites are set, it takes precedence over the default suite defined by the SSLEngineOptions in use.

Environment variable: QUARKUS_TLS_CIPHER_SUITES

list of string

quarkus.tls.protocols

Sets the ordered list of enabled TLS protocols.

If not set, it defaults to "TLSv1.3, TLSv1.2". The following list of protocols are supported: TLSv1, TLSv1.1, TLSv1.2, TLSv1.3. To only enable TLSv1.3, set the value to to "TLSv1.3".

Note that setting an empty list, and enabling TLS is invalid. You must at least have one protocol.

Also, setting this replaces the default list of protocols.

Environment variable: QUARKUS_TLS_PROTOCOLS

list of string

TLSv1.3,TLSv1.2

quarkus.tls.handshake-timeout

The timeout for the TLS handshake phase.

If not set, it defaults to 10 seconds.

Environment variable: QUARKUS_TLS_HANDSHAKE_TIMEOUT

Duration

10S

quarkus.tls.alpn

Enables the Application-Layer Protocol Negotiation (ALPN).

Application-Layer Protocol Negotiation is a TLS extension that allows the client and server during the TLS handshake to negotiate which protocol they will use for communication. ALPN enables more efficient communication by allowing the client to indicate its preferred application protocol to the server before the TLS connection is established. This helps in scenarios such as HTTP/2 where multiple protocols may be available, allowing for faster protocol selection.

Environment variable: QUARKUS_TLS_ALPN

boolean

true

quarkus.tls.certificate-revocation-list

Sets the list of revoked certificates (paths to files).

A Certificate Revocation List (CRL) is a list of digital certificates that have been revoked by the issuing Certificate Authority (CA) before their scheduled expiration date. When a certificate is compromised, no longer needed, or deemed invalid for any reason, the CA adds it to the CRL to inform relying parties not to trust the certificate anymore.

Two formats are allowed: DER and PKCS#7 (also known as P7B). When using the DER format, you must pass DER-encoded CRLs. When using the PKCS#7 format, you must pass PKCS#7 SignedData object, with the only significant field being crls.

Environment variable: QUARKUS_TLS_CERTIFICATE_REVOCATION_LIST

list of path

quarkus.tls.trust-all

If set to true, the server trusts all certificates.

This is useful for testing, but should not be used in production.

Environment variable: QUARKUS_TLS_TRUST_ALL

boolean

false

quarkus.tls.hostname-verification-algorithm

The hostname verification algorithm to use in case the server’s identity should be checked. Should be HTTPS (default), LDAPS or an NONE.

If set to NONE, it does not verify the hostname.

If not set, the configured extension decides the default algorithm to use. For example, for HTTP, it will be "HTTPS". For TCP, it can depend on the protocol. Nevertheless, it is recommended to set it to "HTTPS" or "LDAPS".

Environment variable: QUARKUS_TLS_HOSTNAME_VERIFICATION_ALGORITHM

string

quarkus.tls.reload-period

When configured, the server will reload the certificates (from the file system for example) and fires a CertificateUpdatedEvent if the reload is successful

This property configures the period to reload the certificates. IF not set, the certificates won’t be reloaded automatically. However, the application can still trigger the reload manually using the io.quarkus.tls.TlsConfiguration#reload() method, and then fire the CertificateUpdatedEvent manually.

The fired event is used to notify the application that the certificates have been updated, and thus proceed with the actual switch of certificates.

Environment variable: QUARKUS_TLS_RELOAD_PERIOD

Duration

quarkus.tls.key-store.pem."key-certs".key

The path to the key file (in PEM format).

Environment variable: QUARKUS_TLS_KEY_STORE_PEM__KEY_CERTS__KEY

path

required

quarkus.tls.key-store.pem."key-certs".cert

The path to the certificate file (in PEM format).

Environment variable: QUARKUS_TLS_KEY_STORE_PEM__KEY_CERTS__CERT

path

required

quarkus.tls."tls-bucket-name".key-store.pem."key-certs".key

The path to the key file (in PEM format).

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_PEM__KEY_CERTS__KEY

path

required

quarkus.tls."tls-bucket-name".key-store.pem."key-certs".cert

The path to the certificate file (in PEM format).

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_PEM__KEY_CERTS__CERT

path

required

quarkus.tls."tls-bucket-name".key-store.pem.order

The order of the key/cert files, based on the names in the keyCerts map.

By default, Quarkus sorts the key using a lexicographical order. This property allows you to specify the order of the key/cert files.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_PEM_ORDER

list of string

quarkus.tls."tls-bucket-name".key-store.p12.path

Path to the key store file (P12 / PFX format).

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_P12_PATH

path

required

quarkus.tls."tls-bucket-name".key-store.p12.password

Password of the key store. When not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_P12_PASSWORD

string

quarkus.tls."tls-bucket-name".key-store.p12.alias

Alias of the private key and certificate in the key store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_P12_ALIAS

string

quarkus.tls."tls-bucket-name".key-store.p12.alias-password

Password of the alias in the key store. If not set, the password will be retrieved from the credential provider.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_P12_ALIAS_PASSWORD

string

quarkus.tls."tls-bucket-name".key-store.p12.provider

Provider of the key store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_P12_PROVIDER

string

quarkus.tls."tls-bucket-name".key-store.jks.path

Path to the keystore file (JKS format).

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_JKS_PATH

path

required

quarkus.tls."tls-bucket-name".key-store.jks.password

Password of the key store. When not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_JKS_PASSWORD

string

quarkus.tls."tls-bucket-name".key-store.jks.alias

Alias of the private key and certificate in the key store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_JKS_ALIAS

string

quarkus.tls."tls-bucket-name".key-store.jks.alias-password

Password of the alias in the key store. When not set, the password may be retrieved from the credential provider.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_JKS_ALIAS_PASSWORD

string

quarkus.tls."tls-bucket-name".key-store.jks.provider

Provider of the key store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_JKS_PROVIDER

string

quarkus.tls."tls-bucket-name".key-store.sni

Enables Server Name Indication (SNI).

Server Name Indication (SNI) is a TLS extension that allows a client to specify the hostname it is attempting to connect to during the TLS handshake. This enables a server to present different SSL certificates for multiple domains on a single IP address, facilitating secure communication for virtual hosting scenarios.

With this setting enabled, the client indicate the server name during the TLS handshake, allowing the server to select the right certificate.

When configuring the keystore with PEM files, multiple CRT/Key must be given. When configuring the keystore with a JKS or a P12 file, it selects one alias based on the SNI hostname. In this case, all the keystore password and alias password must be the same (configured with the password and alias-password properties. Do not set the alias property.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_SNI

boolean

false

quarkus.tls."tls-bucket-name".key-store.credentials-provider.name

The name of the "credential" bucket (map key → passwords) to retrieve from the io.quarkus.credentials.CredentialsProvider. If not set, the credential provider will not be used.

A credential provider offers a way to retrieve the key store password as well as alias password. Note that the credential provider is only used if the passwords are not set in the configuration.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_CREDENTIALS_PROVIDER_NAME

string

quarkus.tls."tls-bucket-name".key-store.credentials-provider.bean-name

The name of the bean providing the credential provider.

The name is used to select the credential provider to use. The credential provider must be exposed as a CDI bean and with the @Named annotation set to the configured name to be selected.

If not set, the default credential provider is used.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_CREDENTIALS_PROVIDER_BEAN_NAME

string

quarkus.tls."tls-bucket-name".key-store.credentials-provider.password-key

The key used to retrieve the key store password.

If the selected credential provider does not support the key, the password is not retrieved. Otherwise, the retrieved value is used to open the key store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_CREDENTIALS_PROVIDER_PASSWORD_KEY

string

password

quarkus.tls."tls-bucket-name".key-store.credentials-provider.alias-password-key

The key used to retrieve the key store alias password.

If the selected credential provider does not contain the key, the alias password is not retrieved. Otherwise, the retrieved value is used to access the alias private key from the key store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__KEY_STORE_CREDENTIALS_PROVIDER_ALIAS_PASSWORD_KEY

string

alias-password

quarkus.tls."tls-bucket-name".trust-store.pem.certs

List of the trusted cert paths (Pem format).

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_PEM_CERTS

list of path

quarkus.tls."tls-bucket-name".trust-store.p12.path

Path to the trust store file (P12 / PFX format).

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_P12_PATH

path

required

quarkus.tls."tls-bucket-name".trust-store.p12.password

Password of the trust store. If not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_P12_PASSWORD

string

quarkus.tls."tls-bucket-name".trust-store.p12.alias

Alias of the trust store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_P12_ALIAS

string

quarkus.tls."tls-bucket-name".trust-store.p12.provider

Provider of the trust store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_P12_PROVIDER

string

quarkus.tls."tls-bucket-name".trust-store.jks.path

Path to the trust store file (JKS format).

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_JKS_PATH

path

required

quarkus.tls."tls-bucket-name".trust-store.jks.password

Password of the trust store. If not set, the password must be retrieved from the credential provider.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_JKS_PASSWORD

string

quarkus.tls."tls-bucket-name".trust-store.jks.alias

Alias of the key in the trust store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_JKS_ALIAS

string

quarkus.tls."tls-bucket-name".trust-store.jks.provider

Provider of the trust store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_JKS_PROVIDER

string

quarkus.tls."tls-bucket-name".trust-store.credentials-provider.name

The name of the "credential" bucket (map key → passwords) to retrieve from the io.quarkus.credentials.CredentialsProvider. If not set, the credential provider will not be used.

A credential provider offers a way to retrieve the key store password as well as alias password. Note that the credential provider is only used if the passwords are not set in the configuration.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_CREDENTIALS_PROVIDER_NAME

string

quarkus.tls."tls-bucket-name".trust-store.credentials-provider.bean-name

The name of the bean providing the credential provider.

The name is used to select the credential provider to use. The credential provider must be exposed as a CDI bean and with the @Named annotation set to the configured name to be selected.

If not set, the default credential provider is used.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_CREDENTIALS_PROVIDER_BEAN_NAME

string

quarkus.tls."tls-bucket-name".trust-store.credentials-provider.password-key

The key used to retrieve the trust store password.

If the selected credential provider does not contain the configured key, the password is not retrieved. Otherwise, the retrieved value is used to open the trust store.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_STORE_CREDENTIALS_PROVIDER_PASSWORD_KEY

string

password

quarkus.tls."tls-bucket-name".cipher-suites

Sets the ordered list of enabled cipher suites. If none is given, a reasonable default is selected from the built-in ciphers.

When suites are set, it takes precedence over the default suite defined by the SSLEngineOptions in use.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__CIPHER_SUITES

list of string

quarkus.tls."tls-bucket-name".protocols

Sets the ordered list of enabled TLS protocols.

If not set, it defaults to "TLSv1.3, TLSv1.2". The following list of protocols are supported: TLSv1, TLSv1.1, TLSv1.2, TLSv1.3. To only enable TLSv1.3, set the value to to "TLSv1.3".

Note that setting an empty list, and enabling TLS is invalid. You must at least have one protocol.

Also, setting this replaces the default list of protocols.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__PROTOCOLS

list of string

TLSv1.3,TLSv1.2

quarkus.tls."tls-bucket-name".handshake-timeout

The timeout for the TLS handshake phase.

If not set, it defaults to 10 seconds.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__HANDSHAKE_TIMEOUT

Duration

10S

quarkus.tls."tls-bucket-name".alpn

Enables the Application-Layer Protocol Negotiation (ALPN).

Application-Layer Protocol Negotiation is a TLS extension that allows the client and server during the TLS handshake to negotiate which protocol they will use for communication. ALPN enables more efficient communication by allowing the client to indicate its preferred application protocol to the server before the TLS connection is established. This helps in scenarios such as HTTP/2 where multiple protocols may be available, allowing for faster protocol selection.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__ALPN

boolean

true

quarkus.tls."tls-bucket-name".certificate-revocation-list

Sets the list of revoked certificates (paths to files).

A Certificate Revocation List (CRL) is a list of digital certificates that have been revoked by the issuing Certificate Authority (CA) before their scheduled expiration date. When a certificate is compromised, no longer needed, or deemed invalid for any reason, the CA adds it to the CRL to inform relying parties not to trust the certificate anymore.

Two formats are allowed: DER and PKCS#7 (also known as P7B). When using the DER format, you must pass DER-encoded CRLs. When using the PKCS#7 format, you must pass PKCS#7 SignedData object, with the only significant field being crls.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__CERTIFICATE_REVOCATION_LIST

list of path

quarkus.tls."tls-bucket-name".trust-all

If set to true, the server trusts all certificates.

This is useful for testing, but should not be used in production.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__TRUST_ALL

boolean

false

quarkus.tls."tls-bucket-name".hostname-verification-algorithm

The hostname verification algorithm to use in case the server’s identity should be checked. Should be HTTPS (default), LDAPS or an NONE.

If set to NONE, it does not verify the hostname.

If not set, the configured extension decides the default algorithm to use. For example, for HTTP, it will be "HTTPS". For TCP, it can depend on the protocol. Nevertheless, it is recommended to set it to "HTTPS" or "LDAPS".

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__HOSTNAME_VERIFICATION_ALGORITHM

string

quarkus.tls."tls-bucket-name".reload-period

When configured, the server will reload the certificates (from the file system for example) and fires a CertificateUpdatedEvent if the reload is successful

This property configures the period to reload the certificates. IF not set, the certificates won’t be reloaded automatically. However, the application can still trigger the reload manually using the io.quarkus.tls.TlsConfiguration#reload() method, and then fire the CertificateUpdatedEvent manually.

The fired event is used to notify the application that the certificates have been updated, and thus proceed with the actual switch of certificates.

Environment variable: QUARKUS_TLS__TLS_BUCKET_NAME__RELOAD_PERIOD

Duration

About the Duration format

To write duration values, use the standard java.time.Duration format. See the Duration#parse() Java API documentation for more information.

You can also use a simplified format, starting with a number:

  • If the value is only a number, it represents time in seconds.\n

  • If the value is a number followed by ms, it represents time in milliseconds.\n

In other cases, the simplified format is translated to the java.time.Duration format for parsing:

  • If the value is a number followed by h, m, or s, it is prefixed with PT.

  • If the value is a number followed by d, it is prefixed with P.

4. The registry API

While extensions will automatically use the TLS registry, you can also use the registry API to access the TLS configuration programmatically.

To access the TLS configuration, inject the TlsConfigurationRegistry bean and gets the TLS configuration by name (or the default one):

 @Inject
 TlsConfigurationRegistry certificates;
// ...
TlsConfiguration def = certificates.getDefault().orElseThrow();
TlsConfiguration named = certificates.get("name").orElseThrow();
//...

The TlsConfiguration object contains the key stores, trust stores, cipher suites, protocols, and other properties. It also provides a way to create an SSLContext from the configuration.

As Vert.x is omnipresent in Quarkus, you can also use the TlsConfiguration object to configure the Vert.x client or server such as KeyCertOptions, TrustOptions, and so on.

5. Registering a certificate from an extension

This section is only for extension developers. An extension can register a certificate in the TLS registry. This is useful when an extension needs to provide a certificate to the application or provides a different format.

To achieve this, the extension processor must produce a TlsCertificateBuildItem. A TlsCertificateBuildItem is composed of a name and a CertificateSupplier.

TlsCertificateBuildItem item = new TlsCertificateBuildItem("named",
    new MyCertificateSupplier());

The certificate supplier is a runtime object that is generally retrieved using a recorder method. Here is an example of a certificate supplier:

public class MyCertificateSupplier implements Supplier<TlsConfiguration> {

        @Override
        public TlsConfiguration get() {
            try {
                KeyStore ks = KeyStore.getInstance("PKCS12");
                ks.load(getClass().getResourceAsStream("target/certs/test-registration-keystore.p12"),
                        "password".toCharArray());
                KeyStore ts = KeyStore.getInstance("PKCS12");
                ts.load(getClass().getResourceAsStream("target/certs/test-registration-truststore.p12"),
                        "password".toCharArray());
                return new BaseTlsConfiguration() {
                    @Override
                    public KeyStore getKeyStore() {
                        return ks;
                    }

                    @Override
                    public KeyStore getTrustStore() {
                        return ts;
                    }
                };
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

6. Startup checks

When the application starts, the TLS registry performs some checks to ensure the configuration is correct:

  • the key stores and trust stores are accessible

  • the aliases are available and accessible in the key stores and trust stores

  • the certificates are valid

  • the cipher suites and protocols are valid

  • the CRLs are valid

If any of these checks fail, the application will fail to start.

7. Reloading certificates

The TlsConfiguration obtained from the TLSConfigurationRegistry includes a mechanism for reloading certificates. The reload method refreshes the key stores and trust stores, typically by reloading them from the file system.

The reload operation is not automatic and must be triggered manually. Additionally, the TlsConfiguration implementation must support reloading (which is the case for the configured certificate).

The reload method returns a boolean indicating whether the reload was successful. A value of true means the reload operation was successful, not necessarily that there were updates to the certificates.

After a TlsConfiguration has been reloaded, servers and clients using this configuration may need to perform specific actions to apply the new certificates. The recommended approach is to fire a CDI event (CertificateReloadedEvent) that servers and clients can listen to and make the necessary changes:

@Inject
TlsConfigurationRegistry registry;

public void reload() {
    TlsConfiguration config = registry.get("name").orElseThrow();
    if (config.reload()) {
        event.fire(new CertificateReloadedEvent("name", config));
    }
}

// In the server or client code
public void onReload(@Observes CertificateReloadedEvent event) {
    if ("name".equals(event.getName())) {
        server.updateSSLOptions(event.tlsConfiguration().getSSLOptions());
        // Or update the SSLContext.
    }
}

These APIs provide a way to implement custom certificate reloading.

7.1. Periodic reloading

The TLS registry does include a built-in mechanism for periodically checking the file system for changes and reloading the certificates. You can configure periodic reloading of certificates using properties. The reload-period property specifies the interval at which certificates are reloaded, and it will emit a CertificateReloadedEvent.

quarkus.tls.reload-period=1h
quarkus.tls.key-store.pem.0.cert=tls.crt
quarkus.tls.key-store.pem.0.key=tls.key

For each named configuration, you can set a specific reload period:

quarkus.tls.http.reload-period=30min
quarkus.tls.http.key-store.pem.0.cert=tls.crt
quarkus.tls.http.key-store.pem.0.key=tls.key

Remember that the impacted server and client may need to listen to the CertificateReloadedEvent to apply the new certificates. This is automatically done for the Quarkus HTTP server (including the management interface if enabled).

8. Using Kubernetes secrets or cert-manager

When running in Kubernetes, you can use Kubernetes secrets to store the key stores and trust stores.

8.1. Using Kubernetes secrets

To use Kubernetes secrets, you need to create a secret with the key stores and trust stores. Let’s take the following secret as an example:

apiVersion: v1
data:
  tls.crt: ...
  tls.key: ...
kind: Secret
metadata:
  name: my-certs
type: kubernetes.io/tls

The easiest way to uses these certificates is to mount the secret as a volume in the pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: demo
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/managed-by: quarkus
  name: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: demo
      app.kubernetes.io/version: 1.0.0-SNAPSHOT
  template:
    metadata:
      labels:
        app.kubernetes.io/managed-by: quarkus
        app.kubernetes.io/name: demo
        app.kubernetes.io/version: 1.0.0-SNAPSHOT
    spec:
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: ...
          imagePullPolicy: IfNotPresent
          name: demo
          ports:
            - containerPort: 8443 # Configure the port to be HTTPS
              name: http
              protocol: TCP
          volumeMounts:
            - mountPath: /certs
              name: my-volume
      volumes:
        - name: my-volume
          secret:
            defaultMode: 0666 # Set the permissions, otherwise the pod may not be able to read the files
            optional: false
            secretName: my-certs # Reference the secret

Then, you can configure the TLS registry to use the certificates:

# ...
# TLS Registry configuration
%prod.quarkus.tls.http.key-store.pem.0.cert=/certs/tls.crt
%prod.quarkus.tls.http.key-store.pem.0.key=/certs/tls.key

# HTTP server configuration:
%prod.quarkus.http.tls-configuration-name=http
%prod.quarkus.http.insecure-requests=disabled

You can combine this with the periodic reloading to automatically reload the certificates when they change.

8.2. Using cert-manager

When running in Kubernetes, you can use cert-manager to automatically generate and renew certificates. Cert-manager will produce a secret with the key stores and trust stores. So, configuring the TLS registry is the same as when using Kubernetes secrets. The generated secret uses the following files:

  • tls.crt for the certificate

  • tls.key for the private key

  • ca.crt for the CA certificate (if needed)

To handle the renewal, you can use the periodic reloading mechanism:

# ...
# TLS Registry configuration
%prod.quarkus.tls.http.key-store.pem.0.cert=/certs/tls.crt
%prod.quarkus.tls.http.key-store.pem.0.key=/certs/tls.key
%prod.quarkus.tls.http.reload-period=24h

# HTTP server configuration:
%prod.quarkus.http.tls-configuration-name=http
%prod.quarkus.http.insecure-requests=disabled

9. Utilizing OpenShift serving certificates

When running your application in OpenShift, you can leverage the OpenShift serving certificates to automatically generate and renew TLS certificates. The Quarkus TLS registry can use these certificates and Certificate Authority (CA) files to handle HTTPS traffic securely and to validate certificates.

9.1. Acquiring a certificate

To have OpenShift generate a certificate, you need to annotate an existing Service object. The generated certificate will be stored in a secret, which you can then mount in your pod.

Consider the following Service example:

---
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.openshift.io/serving-cert-secret-name: my-tls-secret
  labels:
    app.kubernetes.io/name: ...
    app.kubernetes.io/version: ...
    app.kubernetes.io/managed-by: quarkus
  name: hero-service
spec:
  ports:
    - name: http
      port: 443
      protocol: TCP
      targetPort: 8443
  selector:
    app.kubernetes.io/name: ...
    app.kubernetes.io/version: ...
  type: ClusterIP

The annotation service.beta.openshift.io/serving-cert-secret-name instructs OpenShift to generate a certificate and store it in a secret named my-tls-secret. If your service is already running, you can add this annotation with the following command:

oc annotate service hero-service \
     service.beta.openshift.io/serving-cert-secret-name=my-tls-secret

Next, mount the secret in your pod by updating your Deployment configuration to include a volume and mount the secret:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: ...
    app.kubernetes.io/version: ...
  name: my-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ...
      app.kubernetes.io/version: ...
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ...
        app.kubernetes.io/version: ...
    spec:
      volumes:
        - name: my-tls-secret  (1)
          secret:
            secretName: my-tls-secret
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: QUARKUS_TLS_KEY_STORE_PEM_ACME_CERT (2)
              value: /etc/tls/tls.crt
            - name: QUARKUS_TLS_KEY_STORE_PEM_ACME_KEY
              value: /etc/tls/tls.key
          image: ...
          imagePullPolicy: Always
          name: my-service
          volumeMounts:  (3)
            - name: my-tls-secret
              mountPath: /etc/tls
              readOnly: true
          ports:
            - containerPort: 8443  (4)
              name: https
              protocol: TCP
1 Define a volume to mount the secret. Use the same name as the secret declared above.
2 Set up the key store with the paths to the certificate and private key. This can be configured using environment variables or configuration files. Here, we use environment variables. OpenShift serving certificates always create the tls.crt and tls.key files.
3 Mount the secret in the container. Ensure the path matches the one used in the configuration (here /etc/tls).
4 Configure the port to serve HTTPS.

By setting the quarkus.tls.key-store.pem.acme.cert and quarkus.tls.key-store.pem.acme.key variables (or their environment variable variant as done above), the TLS registry will use the certificate and private key from the secret. This configures the default key store for the Quarkus HTTP server, allowing it to use the certificate. For using this certificate in a named configuration, refer to Referencing a TLS configuration.

Deploy your application, and it will utilize the certificate generated by OpenShift, making the service available over HTTPS.

9.2. Trusting the Certificate Authority (CA)

Now that your service uses a certificate issued by OpenShift, you might need to configure your client applications to trust this certificate. To accomplish this, create a ConfigMap that holds the CA certificate and mount it in the application’s pod.

In this example, we’ll use a Quarkus REST client, but the same principle applies to any client.

First, create a ConfigMap for the CA certificate. Start by defining an empty ConfigMap, which will be populated with the CA certificate:

apiVersion: v1
kind: ConfigMap
metadata:
  name: client-tls-config
  annotations:
    service.beta.openshift.io/inject-cabundle: "true"

The service.beta.openshift.io/inject-cabundle annotation is used to inject the CA certificate into the ConfigMap. Note that the ConfigMap initially has no data — it is empty. During its processing, OpenShift injects the CA certificate into the ConfigMap in the service-ca.crt file.

Next, mount the ConfigMap by adding a volume and mount it in your Deployment configuration:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service-client
  labels:
    app.kubernetes.io/name: ...
    app.kubernetes.io/version: ...
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ...
      app.kubernetes.io/version: ...
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ...
        app.kubernetes.io/version: ...
    spec:
      containers:
        - name: my-service-client
          image: ...
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          volumeMounts: (1)
            - name: my-client-volume
              mountPath: /deployments/tls
      volumes: (2)
        - name: my-client-volume
          configMap:
            name: client-tls-config
1 Mount the ConfigMap in the container. Ensure the path matches the one used in the configuration (here /deployments/tls).
2 Define a volume to mount the ConfigMap and reference the ConfigMap that receives the CA certificate.

Finally, configure the REST client to use this CA certificate. Consider the following REST client interface:

package org.acme;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

@RegisterRestClient(baseUri = "https://hero-service.cescoffi-dev.svc", configKey = "hero") (1)
public interface HeroClient {

    record Hero (Long id, String name, String otherName, int level, String picture, String powers) {
    }

    @GET
    @Path("/api/heroes/random")
    Hero getRandomHero();

}
1 Configure the base URI and the configuration key. The name must be in the format <service-name>.<namespace>.svc, otherwise the certificate will not be trusted. Ensure to also configure the configKey.

Next, configure the REST client to trust the CA certificate:

quarkus.rest-client.hero.tls-configuration-name=my-service-tls (1)
quarkus.tls.my-service-tls.trust-store.pem.certs=/deployments/tls/service-ca.crt (2)
1 Configure the hero REST client with the TLS configuration named my-service-tls.
2 Set up the my-service-tls TLS configuration, specifically the trust store with the CA certificate. Ensure the path matches the one used in the Kubernetes Deployment configuration. The file is always named service-ca.crt.

Now, the REST client is configured to trust the certificate generated by OpenShift.

9.3. Certificate renewal

OpenShift automatically renews the certificates it generates. When the certificate is renewed, the secret is updated with the new certificate and private key.

To ensure your application uses the new certificate, you can leverage the Quarkus TLS registry’s periodic reloading feature. By setting the reload-period property, the TLS registry will periodically check the key stores and trust stores for changes and reload them if needed:

quarkus.tls.reload-period=24h

You can also implement a custom mechanism to reload the certificates when the secret is updated. See Reloading certificates for more information.

10. Quarkus CLI commands and development CA (Certificate Authority)

The TLS registry provides CLI commands to generate a development CA and trusted certificates. This avoids having to use self-signed certificates locally.

> quarkus tls
Install and Manage TLS development certificates
Usage: tls [COMMAND]
Commands:
  generate-quarkus-ca   Generate Quarkus Dev CA certificate and private key.
  generate-certificate  Generate a TLS certificate with the Quarkus Dev CA if
                          available.

In most cases, you generate the Quarkus Development CA once, and then generate certificates signed by this CA. The Quarkus Development CA is a Certificate Authority that can be used to sign certificates locally. It is only valid for development purposes and only trusted on the local machine. The generated CA is located in $HOME/.quarkus/quarkus-dev-root-ca.pem, and installed in the system trust store.

10.1. CA, signed vs. self-signed certificates

When developing with TLS, you can use two types of certificates:

  • a self-signed certificate: the certificate is signed by the same entity that uses it. It is not trusted by default. It’s generally what we use when we don’t have a CA, or don’t want to dig too much into TLS. This is not a production setup, and may be used only for development.

  • a signed certificate: the certificate is signed by a Certificate Authority (CA). The CA is a trusted entity that signs the certificate. The certificate is trusted by default. This is what we use in production.

We could use self-signed certificate when running application locally, but it’s not always convenient. Typically, browsers will not trust the certificate, and you will have to import it manually. curl, wget, httpie and other tools will also not trust the certificate.

To avoid this, we can use a development CA to sign the certificates, and install it into the system trust store. Thus, every certificate signed by this CA will be trusted by the system.

Quarkus makes it easy to generate a development CA and certificates signed by this CA.

10.2. Generate a development CA

The development CA is a Certificate Authority that can be used to sign certificates locally. Note that the generated CA is only valid for development purposes, and only trusted on the local machine.

To generate a development CA, use the following command:

quarkus tls generate-ca-certificate --install --renew --truststore

--install installs the CA in the system trust store. Windows, Mac and Linux (Fedora and Ubuntu) are supported. However, depending on your browser, you may need to import the generated CA manually. Refer to the browser documentation for more information. The generated CA is located in $HOME/.quarkus/quarkus-dev-root-ca.pem.

When installing the certificate, your system may ask for your password to install the certificate in the system trust store, or ask for confirmation in a dialog (on Windows).
On Windows, makes sure you run from an elevated terminal (run as administrator) to install the CA in the system trust store.

--renew renews the CA if it already exists. When this option is used, you need to re-generate the certificates that were signed by the CA, as the private key is changed. Note that if the CA expires, it will automatically be renewed (without passing --renew).

--truststore also generates a PKCS12 trust store containing the CA certificate.

10.3. Generate a trusted (signed) certificate

Once you have installed the Quarkus Development CA, you can generate a trusted certificate. It will be signed by the Quarkus Development CA, and so trusted by your system.

quarkus tls generate-certificate --name my-cert

This generates a certificate signed by the Quarkus Development CA, and so if properly installed / imported, will be trusted by your system.

The certificate is stored in ./.certs/. Two files are generated:

  • $NAME-keystore.p12 - contains the private key and the certificate. It’s password protected.

  • $NAME-truststore.p12 - contains the CA certificate, that you can used as trust store (for test, for instance).

More options are available:

Usage: tls generate-certificate [-hrV] [-c=<cn>] [-d=<directory>]
       -n=<name> [-p=<password>]
Generate a TLS certificate with the Quarkus Dev CA if available.
  -c, --cn=<cn>       The common name of the certificate. Default is 'localhost'
  -d, --directory=<directory>
                      The directory in which the certificates will be created.
                        Default is `.certs`
  -n, --name=<name>   Name of the certificate. It will be used as file name and
                        alias in the keystore
  -p, --password=<password>
                      The password of the keystore. Default is 'password'
  -r, --renew         Whether existing certificates will need to be replaced

When generating the certificate, a .env file is also generated making the Quarkus dev mode aware of these certificates. So, then, if you run your application in dev mode, it will use these certificates:

./mvnw quarkus:dev
...
INFO  [io.quarkus] (Quarkus Main Thread) demo 1.0.0-SNAPSHOT on JVM (powered by Quarkus 999-SNAPSHOT) started in 1.286s. Listening on: http://localhost:8080 and https://localhost:8443

Now, you can open the Dev UI using HTTPS: https://localhost:8443/q/dev, or issue a request using curl:

curl https://localhost:8443/hello
Hello from Quarkus REST%
If the Quarkus Development CA is not installed, a self-signed certificate is generated.

10.4. Generating a self-signed certificate

Even if the Quarkus Development CA is installed, you can generate a self-signed certificate:

quarkus tls generate-certificate --name my-cert --self-signed

This generates a self-signed certificate, not signed by the Quarkus Development CA.

10.5. Uninstalling the Quarkus Development CA

Uninstalling the Quarkus Development CA from your system depends on your OS.

10.5.1. Deleting the CA certificate on Windows

To delete the CA certificate on Windows, use the following commands from a Powershell terminal with administrator rights:

# First, we need to identify the serial number of the CA certificate
> certutil -store -user Root
root "Trusted Root Certification Authorities"
================ Certificate 0 ================
Serial Number: 019036d564c8
Issuer: O=Quarkus, CN=quarkus-dev-root-ca # <-That's the CA, copy the Serial Number (the line above)
NotBefore: 6/19/2024 11:07 AM
NotAfter: 6/20/2025 11:07 AM
Subject: C=Cloud, S=world, L=home, OU=Quarkus Dev, O=Quarkus Dev, CN=quarkus-dev-root-ca
Signature matches Public Key
Non-root Certificate uses same Public Key as Issuer
Cert Hash(sha1): 3679bc95b613a2112a3d3256fe8321b6eccce720
No key provider information
Cannot find the certificate and private key for decryption.
CertUtil: -store command completed successfully.

> certutil -delstore -user -v Root $Serial_Number

Replace $Serial_Number with the serial number of the CA certificate.

10.5.2. Deleting the CA certificate on Linux

On Fedora, you can use the following command:

sudo rm /etc/pki/ca-trust/source/anchors/quarkus-dev-root-ca.pem
sudo update-ca-trust

On Ubuntu, you can use the following command:

sudo rm /usr/local/share/ca-certificates/quarkus-dev-root-ca.pem
sudo update-ca-certificates

10.5.3. Deleting the CA certificate on Mac

On Mac, you can use the following command:

sudo security -v remove-trusted-cert -d /Users/clement/.quarkus/quarkus-dev-root-ca.pem

11. Automatic certificate management with Let’s Encrypt

Let’s Encrypt is a free, automated certificate authority provided by Internet Security Research Group.

Let’s Encrypt uses Automated certificate management environment (ACME) protocol to support an automatic certificate issuance and renewal. Please read Let’s Encrypt documentation to learn more about Let’s Encrypt and ACME.

TLS registry project provides a CLI ACME client to issue and renew Let’s Encrypt certificates. Your application uses TLS registry to resolve ACME protocol challenges.

Follow the steps below to have your Quarkus application prepared and automatically updated with new and renewed Let’s Encrypt certificates.

11.1. Prerequisites

Make sure that a fully resolvable DNS domain name is available and can be used to access your application. This domain name is used for creating a Let’s Encrypt account, and supporting Let’s Encrypt ACME challenges to prove that you own this domain. You can use Ngrok to start experimenting with the Quarkus Let’s Encrypt ACME feature, see Use NGrok for testing section below for more information.

Your Quarkus HTTPS application must use a build-time property to enable a Let’s Encrypt ACME challenge route:

quarkus.tls.lets-encrypt.enabled=true

The TLS registry can manage the challenge process from either the main HTTP interface or from the management interface. Using a management interface is strongly recommended to let Quarkus deal with ACME challenge configuration separately to the main application’s deployment and security requirements:

quarkus.tls.lets-encrypt.enabled=true
quarkus.management.enabled=true

The challenge itself is served from the primary HTTP interface (the one accessible from your DNS domain name).

Do not start your application yet.

11.2. Application preparation

Before you request a Let’s Encrypt certificate, you must run TLS registry Let’s Encrypt CLI prepare command to prepare your application:

quarkus tls lets-encrypt prepare --domain=<domain-dns-name>
Make sure you run a prepare command in the root directory of your application.

The prepare command does the following:

  • Creates a .letsencrypt folder in your application’s root directory

  • Creates a self-signed domain certificate and private key for your application configured in the previous Prerequisites step to be able to start and accept HTTPS requests.

  • Create a .env configuration file in your application’s root directory configure the application to use the self-signed domain certificate and private key (until we get the Let’s Encrypt certificate).

The following snippet shows an example of the generated .env file:

quarkus.tls.key-store.pem.acme.cert=.letsencrypt/lets-encrypt.crt
quarkus.tls.key-store.pem.acme.key=.letsencrypt/lets-encrypt.key
The .env file does not contain the quarkus.tls.lets-encrypt.enabled and quarkus.management.enabled properties as they are build-time properties requiring a rebuild of the application.

11.3. Start your application

You can start your application:

java -jar quarkus-run.jar

Access your application endpoint using https://your-domain-name:8443/, for example, https://your-domain-name:8443/hello, accept a self-signed certificate in the browser.

Next, keep the application running and request your first Let’s Encrypt certificate.

11.4. Issue certificate

From the application directory, run the issue-certificate command to acquire your first Let’s Encrypt certificate:

quarkus tls lets-encrypt issue-certificate \
  --domain=<domain-dns-name> \ (1)
  --email=<your contact email> \ (2)
  --management-url=https://localhost:9000 (3)
1 Set your domain name.
2 Provide your contact email address that Let’s Encrypt can use to contact you in case of any issues with your Let’s Encrypt account.
3 Set your application management URL which can be used to handle ACME challenges. Use https://localhost:8443/ if you chose not to enable a management router in the Prerequisites step.

During this command, the TLS registry CLI checks if the application is prepared to serve the challenge, creates and records Let’s Encrypt account information, issues a Let’s Encrypt certificate request, and interacts with the Quarkus application to resolve ACME challenges.

Once the Let’s Encrypt certificate chain and private key have been successfully acquired, they are converted to PEM format and copied to your application’s .letsencrypt folder. The TLS registry is informed that a new certificate and private key are ready, and reloads them automatically.

Now, access your application’s endpoint using https://your-domain-name:8443/ again. Confirm in the browser that your domain certificate is now signed by the Let’s Encrypt certificate authority.

Note that currently, a Let’s Encrypt account is created implicitly by the issue-certificate command to make it easy for users to get started with the ACME protocol. Support for the Let’s Encrypt account management will evolve further.

11.5. Renew certificate

Renewing certificates is similar to issuing the first certificate, but it requires an existing account created during the Issue certificate step.

Run the following command to renew your Let’s Encrypt certificate:

quarkus tls lets-encrypt renew-certificate \
  --domain=<domain-dns-name> (1)
1 Set your domain name.

During this command, TLS registry CLI reads a Let’s Encrypt account information recorded during the Issue certificate step, issues a Let’s Encrypt certificate request, and communicates with a Quarkus application to have ACME challenges resolved.

Once the Let’s Encrypt certificate chain and private key have been successfully renewed, they are converted to PEM format and copied to your application’s .letsencrypt folder. TLS registry is informed that a new certificate and private key are ready and it reloads them automatically.

11.6. Use NGrok for testing

Ngrok can be used to provide a secure HTTPS tunnel to your application running on localhost, and make it easy to test HTTPS based applications.

Using Ngrok provides an easiest option to get started with the Quarkus Let’s Encrypt ACME feature.

The first thing you have to do with Ngrok is to ask it to reserve a domain. You can use Quarkiverse NGrok in devmode, or have it reserved directly in the NGrok dashboard.

Unfortunately, you can’t use your NGrok domain to test the Quarkus Let’s Encrypt ACME feature immediately. This is due to the fact that Ngrok is itself using Let’s Encrypt and intercepts ACME challenges which are meant to be handled by the Quarkus application instead.

Therefore, you need to remove an NGrok Let’s Encrypt certificate policy from your NGrok domain:

ngrok api --api-key <YOUR-API-KEY> reserved-domains delete-certificate-management-policy <YOUR-RESERVED-DOMAIN-ID>

YOUR-RESERVED-DOMAIN-ID is your reserved domain’s id which starts from rd_, you can find it in the NGrok dashboard domains section.

Now, NGrok will forward ACME challenges over HTTP only, therefore you need to start Ngrok like this:

ngrok http --domain <YOUR-NGROK-DOMAIN> 8080 --scheme http

where 8080 is the localhost HTTP port that your application is listening on.

You can now test the Quarkus Let’s Encrypt ACME feature from your local machine.