we-promise/sure · warning

[SSL] Could not create combined CA bundle, using custom CA o

Error message

[SSL] Could not create combined CA bundle, using custom CA only. Connections to public services (not using your custom CA) may fail.

What it means

Startup warning from config/initializers/00_ssl.rb (line 258) when a custom CA is valid but SslInitializerHelper.create_combined_ca_bundle returns nil — the combined system+custom bundle at tmp/ssl_ca_bundle.pem could not be produced (e.g. system CA missing/unreadable, or tmp/ not writable). The initializer then falls back to ENV['SSL_CERT_FILE'] = the custom CA path only, so OpenSSL will trust ONLY your custom CA and TLS handshakes to public services (Plaid, Wise, etc.) will likely fail certificate verification.

Source

Thrown at config/initializers/00_ssl.rb:258

    ca_file_status = SslInitializerHelper.validate_ca_certificate_file(ca_file)
    config.x.ssl.ca_file = ca_file_status[:path]
    config.x.ssl.ca_file_valid = ca_file_status[:valid]
    config.x.ssl.ca_file_error = ca_file_status[:error]

    # Create combined CA bundle and set SSL_CERT_FILE for global SSL configuration.
    #
    # This sets ENV["SSL_CERT_FILE"] globally so that ALL Ruby SSL connections
    # (including gems like openid_connect that bypass SslConfigurable) will trust
    # both system CAs (for public services) and the custom CA (for self-signed services).
    if ca_file_status[:valid]
      combined_path = SslInitializerHelper.create_combined_ca_bundle(ca_file_status[:path])
      if combined_path
        config.x.ssl.combined_ca_bundle = combined_path
        ENV["SSL_CERT_FILE"] = combined_path
        Rails.logger.info("[SSL] Set SSL_CERT_FILE=#{combined_path} for global SSL configuration")
      else
        # Fallback: just use the custom CA (may break connections to public services)
        Rails.logger.warn("[SSL] Could not create combined CA bundle, using custom CA only. " \
          "Connections to public services (not using your custom CA) may fail.")
        ENV["SSL_CERT_FILE"] = ca_file_status[:path]
      end
    end
  end

  # Log configuration summary at startup
  SslInitializerHelper.log_ssl_configuration(config.x.ssl)
end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Install the system CA package (ca-certificates) so the combined bundle can be built; check boot logs for the paired 'Could not find system CA bundle' warning.
  2. Ensure the Rails tmp/ directory is writable by the app user and no stale directory exists at tmp/ssl_ca_bundle.pem.
  3. After fixing, confirm the log line 'Set SSL_CERT_FILE=.../tmp/ssl_ca_bundle.pem' appears instead of the fallback warning.
  4. Interim workaround for a single endpoint: set SSL_CERT_FILE manually to a bundle you assemble, but the durable fix is repairing system CA + tmp writability.

Example fix

// before
# custom CA valid, tmp/ read-only -> warning; public TLS fails

// after
RUN apt-get update && apt-get install -y ca-certificates
RUN mkdir -p /app/tmp && chown app:app /app/tmp
Defensive patterns

Strategy: fallback

Validate before calling

writable = File.writable?(Rails.root.join('tmp'))
system_ca = File.readable?('/etc/ssl/certs/ca-certificates.crt')
Rails.logger.warn('combined CA bundle will fail') unless writable && system_ca

Prevention

When it happens

Trigger: Booting with a valid custom CA configured while the system CA bundle cannot be found or read, or tmp/ lacks write permission for the app user; any File.read/File.write error inside create_combined_ca_bundle is swallowed into the nil return.

Common situations: Minimal containers missing ca-certificates (root cause shared with the 'Could not find system CA bundle' warning); read-only or permission-restricted tmp directories in hardened deploys; volume mounts shadowing tmp/ssl_ca_bundle.pem with a directory.

Understand the failure class

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/25c3d7fa09a1483b. Report an issue: GitHub.