Skip to main content
Version: v5

TLS Configuration

Harper uses a top-level tls section in harper-config.yaml to configure Transport Layer Security. This configuration is shared by the HTTP server (HTTPS), the MQTT broker (secure MQTT), and any TLS socket servers created via the HTTP API.

The operationsApi section can optionally define its own tls block, which overrides the root tls for Operations API traffic only. See the Operations API Configuration for more details.

Harper must be restarted for TLS configuration changes to take effect.

TLS Configuration

tls:
certificate: ~/hdb/keys/certificate.pem
certificateAuthority: ~/hdb/keys/ca.pem
privateKey: ~/hdb/keys/privateKey.pem

tls.certificate

Type: string

Default: "<rootPath>/keys/certificate.pem"

Path to the PEM-encoded certificate file.

tls.certificateAuthority

Type: string

Default: "<rootPath>/keys/ca.pem"

Path to the PEM-encoded certificate authority (CA) file. Used to verify client certificates when mTLS is enabled.

tls.privateKey

Type: string

Default: "<rootPath>/keys/privateKey.pem"

Path to the PEM-encoded private key file.

tls.host

Type: string | undefined

The domain name this certificate entry applies to, used for SNI (Server Name Indication) matching. Only relevant when tls is defined as an array. When omitted, the certificate's common name (CN) is used as the host name.

tls.ciphers

Type: string | undefined

Default: crypto.defaultCipherList

Colon-separated list of allowed TLS cipher suites, optionally ending with an OpenSSL security level command such as @SECLEVEL=0. When omitted everywhere, Node.js default ciphers are used. See Node.js Modifying the default TLS cipher suite for more information.

ciphers may be set at the top level, on individual tls array entries, or on certificates added through the operations API. A TLS listener has exactly one effective cipher string, so Harper composes these sources — see Cipher Suites and Security Level.

Cipher Suites and Security Level

Changed in: v5.2.0 — every configured ciphers source is now honored; previously only tls.ciphers (or the first array entry's) took effect and all others were silently ignored.

A TLS listener has a single effective cipher string: OpenSSL applies the cipher list — and any @SECLEVEL command in it, which governs client-certificate chain verification — from the configuration the listener was created with. A per-certificate value cannot take effect on its own, so Harper resolves one effective string per listener from every configured source:

  • The listener's own tls section, in priority order: operationsApi.tls for the Operations API listener, then the root tls section (an object's ciphers directly; an array's entries individually).
  • Certificate records (including certificates added with the add_certificate operation) whose uses matches the listener, plus records with no uses and the legacy generic https use.
  • Certificate authority entries and records participate only for listeners that verify client certificates (mTLS) — a CA's security level matters exactly when its chains are being verified, and does not relax listeners without mTLS.

The resolution composes two separable parts:

  • Cipher suites come from the highest-priority source that specifies any — a CA entry cannot replace or broaden the listener's configured suite list.
  • Security level is the minimum explicit @SECLEVEL across all relevant sources. Sources without an explicit @SECLEVEL keep the runtime default.

For example, a listener configured with strict suites plus a legacy client CA whose chain requires a relaxed level:

http:
securePort: 9927
mtls: true

tls:
- certificate: ~/hdb/keys/certificate.pem
privateKey: ~/hdb/keys/privateKey.pem
ciphers: HIGH:!aNULL
- certificateAuthority: ~/hdb/keys/legacy-client-ca.pem
ciphers: DEFAULT@SECLEVEL=0

resolves to HIGH:!aNULL@SECLEVEL=0 — the configured suites are preserved while the relaxed security level lets the legacy chains (for example SHA-1-signed client CAs, which otherwise fail verification on modern OpenSSL) verify.

Whenever values are composed across sources or a suite list cannot be applied, Harper logs a warning describing what was used and what was ignored. The effective cipher string is fixed when the listener starts: if a later certificate change (such as add_certificate with a ciphers value) alters the resolved value, Harper logs a warning that a restart is required to apply it.

Enabling HTTPS

To enable HTTPS, set http.securePort in addition to the tls section:

http:
securePort: 9927

tls:
certificate: ~/hdb/keys/certificate.pem
certificateAuthority: ~/hdb/keys/ca.pem
privateKey: ~/hdb/keys/privateKey.pem

When http.securePort is set, Harper accepts plaintext connections on http.port and TLS connections on http.securePort simultaneously.

Multi-Domain Certificates (SNI)

To serve different certificates for different domains using Server Name Indication (SNI), define tls as an array of configuration objects. Each entry can optionally include a host property specifying which domain it applies to. If host is omitted, the certificate's common name and subject alternate names (SANs) are used.

tls:
- certificate: ~/hdb/keys/certificate1.pem
certificateAuthority: ~/hdb/keys/ca1.pem
privateKey: ~/hdb/keys/privateKey1.pem
host: example.com
- certificate: ~/hdb/keys/certificate2.pem
certificateAuthority: ~/hdb/keys/ca2.pem
privateKey: ~/hdb/keys/privateKey2.pem
# host omitted: certificate's CN is used

Operations API Override

The operationsApi section can define its own tls block to use a separate certificate for the Operations API:

tls:
certificate: ~/hdb/keys/certificate.pem
certificateAuthority: ~/hdb/keys/ca.pem
privateKey: ~/hdb/keys/privateKey.pem

operationsApi:
network:
securePort: 9924
tls:
certificate: ~/hdb/keys/ops-certificate.pem
certificateAuthority: ~/hdb/keys/ops-ca.pem
privateKey: ~/hdb/keys/ops-privateKey.pem

See the Operations API Configuration for more details.