crowdsecurity/crowdsec · error

failed to append CA cert file %s: %w

Error message

failed to append CA cert file %s: %w

What it means

After successfully reading the CA file, ConnectionString calls AppendCertsFromPEM on the x509 pool. If the content is not valid PEM (or contains no usable certificates), it returns false and the code wraps the (nil) read error as 'failed to append CA cert file %s: %w'. Note: the wrapped err here is nil, so the underlying cause is the file content itself.

Source

Thrown at pkg/csconfig/database.go:176

		} else {
			connString = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", d.User, d.Password, d.Host, d.Port, d.DbName)
		}

		if d.SSLMode != "" {
			// This will be overridden if a CA or client cert is provided
			params.Set("tls", d.SSLMode)
		}

		if d.SSLCACert != "" {
			caCert, err := os.ReadFile(d.SSLCACert)
			if err != nil {
				return "", fmt.Errorf("failed to read CA cert file %s: %w", d.SSLCACert, err)
			}
			if tlsConfig.RootCAs == nil {
				tlsConfig.RootCAs = x509.NewCertPool()
			}
			if !tlsConfig.RootCAs.AppendCertsFromPEM(caCert) {
				return "", fmt.Errorf("failed to append CA cert file %s: %w", d.SSLCACert, err)
			}
			params.Set("tls", "custom")
		}

		if d.SSLClientCert != "" && d.SSLClientKey != "" {
			cert, err := tls.LoadX509KeyPair(d.SSLClientCert, d.SSLClientKey)
			if err != nil {
				return "", fmt.Errorf("failed to load client cert/key pair: %w", err)
			}
			tlsConfig.Certificates = []tls.Certificate{cert}
			params.Set("tls", "custom")
		}

		if params.Get("tls") == "custom" {
			// Register the custom TLS config
			err := mysql.RegisterTLSConfig("custom", tlsConfig)
			if err != nil {
				return "", fmt.Errorf("failed to register custom TLS config: %w", err)

View on GitHub (pinned to 909b515798)

Solutions

  1. Convert the certificate to PEM: `openssl x509 -inform der -in ca.der -out ca.pem`
  2. Verify content: file should start with '-----BEGIN CERTIFICATE-----' (`head -1 ca.pem`)
  3. Ensure you point at the CA certificate, not a client key or CSR

Example fix

// before
openssl x509 -inform der -in ca.cer -out ca.pem  # or check head -1
// after
ssl_ca_cert: /etc/crowdsec/db/ca.pem  # PEM, '-----BEGIN CERTIFICATE-----'
Defensive patterns

Strategy: validation

Validate before calling

pemBytes, _ := os.ReadFile(caPath); if block, _ := pem.Decode(pemBytes); block == nil || block.Type != "CERTIFICATE" { return fmt.Errorf("%s is not a PEM certificate", caPath) }

Try / catch

if _, err := dbCfg.ConnectionString(); err != nil { if strings.Contains(err.Error(), "failed to append CA cert") { log.Fatalf("CA file is not valid PEM: %v", err) } }

Prevention

When it happens

Trigger: ssl_ca_cert points to an existing but non-PEM file: DER-encoded cert, an already-chained/binary file, empty file, or a private key instead of a certificate.

Common situations: Users export certs in DER format from Windows tooling; download HTML error page instead of cert; paste key material where a certificate is expected.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/9160d2adaa5fb92b. Report an issue: GitHub.