fluent/fluentd · error · Fluent::ConfigError

no valid cert options configured. specify either 'cert_path'

Error message

no valid cert options configured. specify either 'cert_path', 'ca_cert_path' or 'insecure'

What it means

cert_option_server_validate! (cert_option.rb:91-93) accepts exactly one of three ways to provision server TLS material: a pre-issued certificate (cert_path + private_key_path), dynamic CA-signed generation (ca_cert_path + ca_private_key_path), or an explicitly acknowledged self-signed insecure mode (insecure true). If none is present, there is no certificate to serve TLS with, and this Fluent::ConfigError is raised at startup.

Source

Thrown at lib/fluent/plugin_helper/cert_option.rb:92

        when conf.ca_cert_path
          raise Fluent::ConfigError, "ca_private_key_path is required when ca_cert_path is specified" unless conf.ca_private_key_path
          log.warn "For security reason, setting ca_private_key_passphrase is recommended when ca_cert_path is specified" unless conf.ca_private_key_passphrase
          generate_opts = cert_option_cert_generation_opts_from_conf(conf)
          cert_option_generate_server_pair_by_ca(
            conf.ca_cert_path,
            conf.ca_private_key_path,
            conf.ca_private_key_passphrase,
            generate_opts
          )

        when conf.insecure
          log.warn "insecure TLS communication server is configured (using 'insecure' mode)"
          generate_opts = cert_option_cert_generation_opts_from_conf(conf)
          cert_option_generate_server_pair_self_signed(generate_opts)

        else
          raise Fluent::ConfigError, "no valid cert options configured. specify either 'cert_path', 'ca_cert_path' or 'insecure'"
        end
      end

      def cert_option_load(cert_path, private_key_path, private_key_passphrase)
        key = OpenSSL::PKey::read(File.read(private_key_path), private_key_passphrase)
        certs = cert_option_certificates_from_file(cert_path)
        cert = certs.shift
        return cert, key, certs
      end

      def cert_option_cert_generation_opts_from_conf(conf)
        {
          private_key_length: conf.generate_private_key_length,
          country: conf.generate_cert_country,
          state: conf.generate_cert_state,
          locality: conf.generate_cert_locality,
          common_name: conf.generate_cert_common_name || ::Socket.gethostname,
          expiration: conf.generate_cert_expiration,

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Provide a server certificate pair: cert_path + private_key_path (plus private_key_passphrase if encrypted)
  2. Or enable dynamic CA-signed generation: ca_cert_path + ca_private_key_path
  3. Or, for testing only, set insecure true to use a generated self-signed certificate (clients must then skip verification; it is logged with a warning)
  4. Audit templated configs for empty variable expansion around the <transport tls> block

Example fix

# before
<source>
  @type forward
  <transport tls>
    client_cert_auth true
    ca_path /etc/fluent/ca.pem
  </transport>
</source>
# => no valid cert options configured. specify either 'cert_path', 'ca_cert_path' or 'insecure'

# after
<source>
  @type forward
  <transport tls>
    cert_path /etc/fluent/server-cert.pem
    private_key_path /etc/fluent/server-key.pem
    client_cert_auth true
    ca_path /etc/fluent/ca.pem
  </transport>
</source>
Defensive patterns

Strategy: validation

Validate before calling

tls = { 'cert_path' => nil, 'ca_cert_path' => nil, 'insecure' => false } # from rendered conf
raise 'no cert mode: set cert_path, ca_cert_path, or insecure' unless tls['cert_path'] || tls['ca_cert_path'] || tls['insecure']

Try / catch

begin
  agent.configure(conf)
rescue Fluent::ConfigError => e
  if e.message.include?('no valid cert options')
    abort 'configure one of cert_path (+key), ca_cert_path (+ca key), or insecure (test only)'
  end
  raise
end

Prevention

When it happens

Trigger: <transport tls> enabled (via <transport tls> in a forward input, http input, etc.) with none of cert_path, ca_cert_path, or insecure set — e.g. only client_cert_auth or ca_path (CA-for-verifying-clients) configured; or an env-templated config where the cert section rendered empty.

Common situations: Enabling TLS incrementally: operator sets client_cert_auth true and ca_path for mutual TLS but forgets the server side; config templating (erb/helm) omitting the whole cert block when a variable is unset; assuming fluentd will generate a self-signed cert by default (it will not, unless insecure true).

Related errors


AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21). Data as JSON: /api/errors/43cdf4d9654b42bd. Report an issue: GitHub.