fluent/fluentd · error · Fluent::ConfigError

private_key_path is required when cert_path is specified

Error message

private_key_path is required when cert_path is specified

What it means

cert_option_server_validate! (cert_option.rb:70-73) requires that a <transport tls> (or equivalent TLS server) configuration specifying cert_path must also specify private_key_path: an OpenSSL server context needs both the certificate and its private key to handshake. Without the key, no certificate can be presented, so fluentd raises this Fluent::ConfigError at startup rather than failing later at connection time.

Source

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

          sandbox = Class.new
          ctx.verify_callback = if File.exist?(conf.cert_verifier)
                                  verifier = File.read(conf.cert_verifier)
                                  sandbox.instance_eval(verifier, File.basename(conf.cert_verifier))
                                else
                                  sandbox.instance_eval(conf.cert_verifier)
                                end
        end

        Fluent::TLS.set_version_to_context(ctx, version, conf.min_version, conf.max_version)
        ctx.ciphers = ciphers unless insecure

        ctx
      end

      def cert_option_server_validate!(conf)
        case
        when conf.cert_path
          raise Fluent::ConfigError, "private_key_path is required when cert_path is specified" unless conf.private_key_path
          log.warn "For security reason, setting private_key_passphrase is recommended when cert_path is specified" unless conf.private_key_passphrase
          cert_option_load(conf.cert_path, conf.private_key_path, conf.private_key_passphrase)

        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)

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Add private_key_path /etc/fluent/server.key next to cert_path in <transport tls>
  2. Verify both files exist and the key matches the cert: openssl x509 -noout -modulus -in cert.pem | openssl md5 vs openssl rsa -noout -modulus -in server.key | openssl md5
  3. If the key is passphrase-protected, also set private_key_passphrase (fluentd warns when it is missing)
  4. Check your templating/secret injection actually rendered the private_key_path value (empty strings are treated as unspecified)

Example fix

# before
<transport tls>
  cert_path /etc/fluent/server-cert.pem
</transport>
# => private_key_path is required when cert_path is specified

# after
<transport tls>
  cert_path /etc/fluent/server-cert.pem
  private_key_path /etc/fluent/server-key.pem
</transport>
Defensive patterns

Strategy: validation

Validate before calling

tls = { 'cert_path' => '/etc/fluent/cert.pem', 'private_key_path' => '/etc/fluent/key.pem' }
raise 'private_key_path missing' if tls['cert_path'] && !tls['private_key_path']
raise 'cert file missing PEM' unless File.read(tls['cert_path']).include?('BEGIN CERTIFICATE')

Try / catch

begin
  agent.configure(conf)
rescue Fluent::ConfigError => e
  if e.message.include?('private_key_path is required')
    abort 'add private_key_path to <transport tls> and redeploy'
  end
  raise
end

Prevention

When it happens

Trigger: Config with <transport tls> cert_path /path/cert.pem but no private_key_path line — e.g. cert and key split across template variables and the key variable was empty, or the operator assumed the key would be found next to the cert. Raised during plugin configuration when the server helper builds the SSL context.

Common situations: Copy-paste TLS configs where the private_key_path line was dropped; secret-management systems injecting the cert but failing to inject the key; migrating from a client-only TLS config (which needs just ca_path) into a server config; typos in the parameter name such as private_keypath going unnoticed until startup.

Related errors


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