{"record":{"id":"7b4ceaf43cdb2d05","repo":"fluent/fluentd","slug":"private-key-path-is-required-when-cert-path-is-spe","errorCode":null,"errorMessage":"private_key_path is required when cert_path is specified","messagePattern":"private_key_path is required when cert_path is specified","errorType":"exception","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin_helper/cert_option.rb","lineNumber":71,"sourceCode":"          sandbox = Class.new\n          ctx.verify_callback = if File.exist?(conf.cert_verifier)\n                                  verifier = File.read(conf.cert_verifier)\n                                  sandbox.instance_eval(verifier, File.basename(conf.cert_verifier))\n                                else\n                                  sandbox.instance_eval(conf.cert_verifier)\n                                end\n        end\n\n        Fluent::TLS.set_version_to_context(ctx, version, conf.min_version, conf.max_version)\n        ctx.ciphers = ciphers unless insecure\n\n        ctx\n      end\n\n      def cert_option_server_validate!(conf)\n        case\n        when conf.cert_path\n          raise Fluent::ConfigError, \"private_key_path is required when cert_path is specified\" unless conf.private_key_path\n          log.warn \"For security reason, setting private_key_passphrase is recommended when cert_path is specified\" unless conf.private_key_passphrase\n          cert_option_load(conf.cert_path, conf.private_key_path, conf.private_key_passphrase)\n\n        when conf.ca_cert_path\n          raise Fluent::ConfigError, \"ca_private_key_path is required when ca_cert_path is specified\" unless conf.ca_private_key_path\n          log.warn \"For security reason, setting ca_private_key_passphrase is recommended when ca_cert_path is specified\" unless conf.ca_private_key_passphrase\n          generate_opts = cert_option_cert_generation_opts_from_conf(conf)\n          cert_option_generate_server_pair_by_ca(\n            conf.ca_cert_path,\n            conf.ca_private_key_path,\n            conf.ca_private_key_passphrase,\n            generate_opts\n          )\n\n        when conf.insecure\n          log.warn \"insecure TLS communication server is configured (using 'insecure' mode)\"\n          generate_opts = cert_option_cert_generation_opts_from_conf(conf)\n          cert_option_generate_server_pair_self_signed(generate_opts)","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin_helper/cert_option.rb#L53-L89","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add private_key_path /etc/fluent/server.key next to cert_path in <transport tls>","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","If the key is passphrase-protected, also set private_key_passphrase (fluentd warns when it is missing)","Check your templating/secret injection actually rendered the private_key_path value (empty strings are treated as unspecified)"],"exampleFix":"# before\n<transport tls>\n  cert_path /etc/fluent/server-cert.pem\n</transport>\n# => private_key_path is required when cert_path is specified\n\n# after\n<transport tls>\n  cert_path /etc/fluent/server-cert.pem\n  private_key_path /etc/fluent/server-key.pem\n</transport>","handlingStrategy":"validation","validationCode":"tls = { 'cert_path' => '/etc/fluent/cert.pem', 'private_key_path' => '/etc/fluent/key.pem' }\nraise 'private_key_path missing' if tls['cert_path'] && !tls['private_key_path']\nraise 'cert file missing PEM' unless File.read(tls['cert_path']).include?('BEGIN CERTIFICATE')","typeGuard":null,"tryCatchPattern":"begin\n  agent.configure(conf)\nrescue Fluent::ConfigError => e\n  if e.message.include?('private_key_path is required')\n    abort 'add private_key_path to <transport tls> and redeploy'\n  end\n  raise\nend","preventionTips":["Pin TLS config templates to always emit cert_path and private_key_path as a pair (fail the template if either variable is unset)","Validate rendered configs with fluentd --dry-run in CI before they reach production","Keep cert/key pairs co-located in secret stores so one is never provisioned without the other"],"tags":["fluentd","tls","certificate","private-key","config-error","startup"],"backgroundTag":"tls-missing-private-key","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}