Configuration: security and TLS

This page documents the TLS crypto directives available inside a tls { ... } block. These settings are optional. Ferron uses safe defaults when you omit a setting. The TLS crypto configuration applies to all TLS providers: manual, acme, and local.

Directives⁠#

Certificate and private key⁠#

  • cert <path: string>
    • This directive specifies the path to the server certificate file. The file must be PEM format and include the leaf certificate and any intermediate certificates your CA requires.
  • key <path: string>
    • This directive specifies the path to the server private key file. The file must be PEM format.

These directives are required for the manual provider. Make sure Ferron can read both files. The certificate and private key must match. If they do not match, TLS handshakes fail. You can use environment variable interpolation for the paths.

Configuration example:

example.com {
    tls {
        provider manual
        cert "/path/cert.pem"
        key "/path/key.pem"
    }
}

Cipher suites⁠#

  • cipher_suite <suite: string>
    • This directive specifies a cipher suite to add to the allowed list. Repeatable. Each occurrence adds one suite. When you omit it, rustls defaults apply. Default: rustls defaults.

Configuration example:

example.com {
    tls {
        provider manual
        cert "/path/cert.pem"
        key "/path/key.pem"
        cipher_suite TLS_AES_128_GCM_SHA256
        cipher_suite TLS_AES_256_GCM_SHA384
    }
}

Supported cipher suites⁠#

SuiteProtocolKey exchangeNotes
TLS_AES_128_GCM_SHA256TLS 1.3AnyDefault in most deployments
TLS_AES_256_GCM_SHA384TLS 1.3AnyStronger encryption
TLS_CHACHA20_POLY1305_SHA256TLS 1.3AnySoftware-optimized, good for mobile
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256TLS 1.2ECDHE + ECDSAECDSA certificate required
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384TLS 1.2ECDHE + ECDSAECDSA certificate required
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256TLS 1.2ECDHE + ECDSAECDSA certificate required
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256TLS 1.2ECDHE + RSARSA certificate
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384TLS 1.2ECDHE + RSARSA certificate
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256TLS 1.2ECDHE + RSARSA certificate
Note

TLS 1.2 cipher suites are only effective when min_version allows TLS 1.2.

ECDH curves⁠#

  • ecdh_curve <curve: string>
    • This directive specifies an ECDH key exchange group to add to the allowed list, in priority order. Repeatable. Each occurrence adds one curve. When you omit it, rustls defaults apply. Default: rustls defaults.

Supported curves⁠#

CurveTypeNotes
x25519ECDHFast, widely supported, recommended default
secp256r1ECDHNIST P-256, required for some compliance standards
secp384r1ECDHNIST P-384, higher security level
x25519mlkem768Hybrid (ECDH + ML-KEM)Post-quantum hybrid with x25519
mlkem768ML-KEMPure post-quantum KEM

TLS protocol version⁠#

  • min_version <version: string>
    • This directive specifies the minimum allowed TLS version. Supported values: TLSv1.2, TLSv1.3. Default: min_version TLSv1.2
  • max_version <version: string>
    • This directive specifies the maximum allowed TLS version. Supported values: TLSv1.2, TLSv1.3. Default: max_version TLSv1.3

Configuration example: TLS 1.3 only

example.com {
  tls {
      provider manual
      cert "/path/cert.pem"
      key "/path/key.pem"
      min_version TLSv1.3
      max_version TLSv1.3
  }
}

If you omit both, Ferron uses the safe default range (TLS 1.2 to 1.3). Setting only min_version restricts the lower bound. Setting only max_version restricts the upper bound. Ferron returns an error if max_version is older than min_version.

Client certificate authentication (mTLS)⁠#

  • client_auth [bool: boolean]
    • This directive turns client certificate authentication on or off. When true, clients must present a valid certificate. Default: client_auth false
  • client_auth_ca <source: string>
    • This directive specifies the source of trusted CA certificates for verifying client certificates. Supported values: a file path ("/path/ca-cert.pem"), system (OS native root store, requires native-certs feature), webpki (Mozilla root bundle). Default: client_auth_ca webpki

Configuration example: full mTLS

api.example.com {
    tls {
        provider manual
        cert "/etc/ssl/api.example.com/cert.pem"
        key "/etc/ssl/api.example.com/key.pem"

        min_version TLSv1.3
        max_version TLSv1.3

        cipher_suite TLS_AES_256_GCM_SHA384
        cipher_suite TLS_CHACHA20_POLY1305_SHA256

        ecdh_curve x25519
        ecdh_curve secp256r1

        client_auth
        client_auth_ca "/etc/ssl/internal-ca/ca-bundle.pem"
    }
}
Note
  • Client certificate verification uses the same trust model as server-side TLS. The client cert chain must validate against the configured CA roots.
  • When client_auth_ca points to a file with multiple CA certificates (a bundle), Ferron loads all of them into the trust store.
  • The system trust store includes all OS-trusted root CAs. Use it only when you want to accept client certificates from any publicly trusted CA. This is rarely the right choice for mTLS.
  • For internal mTLS deployments, use a private CA and set client_auth_ca to the CA bundle file path.
Tip

If you see client certificate handshake failures:

  • Verify the client certificate chain validates against the CA specified in client_auth_ca.
  • Check that the CA certificate file is a valid PEM and has not expired.
  • If you use client_auth_ca system, make sure the OS trusts the issuing CA.

Observability⁠#

Metrics⁠#

MetricTypeAttributesDescription
ferron.tls.certificate_not_afterGaugeferron.host, ferron.tls.provider (http), crypto.certificate.serial_numberCertificate notAfter as Unix epoch seconds

See also⁠#

Best practices⁠#

ferron doctor reports the following best-practice checks for directives on this page.

  • max_version TLSv1.2: Disabling TLS 1.3 reduces security and performance. Allow TLS 1.3 unless legacy clients require TLS 1.2 only.
  • client_auth with public trust store: Using system or webpki roots for mTLS client authentication trusts any certificate from the public PKI. Use a private CA bundle file for mTLS instead.
  • ocsp disabled: OCSP stapling improves TLS privacy, performance, and revocation behavior. Keep it enabled.
  • ticket_keys without auto_rotate: Session ticket keys should rotate automatically in production to limit the impact of key compromise.
  • ticket_keys.max_keys outside 2–5: The optimal range keeps enough old keys for rotation without interruption and without excessive retention.
  • ticket_keys.rotation_interval > 24h: Rotate session ticket keys every 12–24 hours in production.