crowdsecurity/crowdsec · critical

missing TLS cert file

Error message

missing TLS cert file

What it means

Mirror of the key-file check: TLS is enabled because a key file path is configured, but cert_file_path is empty. ServeTLS needs both a certificate and a key, so the server aborts with 'missing TLS cert file'.

Source

Thrown at pkg/apiserver/apiserver.go:382

// listenAndServeLAPI starts the http server and blocks until it's closed
// it also updates the URL field with the actual address the server is listening on
// it's meant to be run in a separate goroutine
func (s *APIServer) listenAndServeLAPI(ctx context.Context, apiReady chan bool) error {
	serverError := make(chan error, 2)

	listenConfig := &net.ListenConfig{}

	startServer := func(listener net.Listener, canTLS bool) {
		var err error

		if canTLS && s.cfg.TLS != nil && (s.cfg.TLS.CertFilePath != "" || s.cfg.TLS.KeyFilePath != "") {
			if s.cfg.TLS.KeyFilePath == "" {
				serverError <- errors.New("missing TLS key file")
				return
			}

			if s.cfg.TLS.CertFilePath == "" {
				serverError <- errors.New("missing TLS cert file")
				return
			}

			err = s.httpServer.ServeTLS(listener, s.cfg.TLS.CertFilePath, s.cfg.TLS.KeyFilePath)
		} else {
			err = s.httpServer.Serve(listener)
		}

		switch {
		case errors.Is(err, http.ErrServerClosed):
			break
		case err != nil:
			serverError <- err
		}
	}

	// Starting TCP listener
	go func(url string) {

View on GitHub (pinned to 909b515798)

Solutions

  1. Set api.server.tls.cert_file_path to the PEM certificate path.
  2. Confirm the cert file exists and is readable by the crowdsec process.
  3. If TLS is not intended, remove the key_file_path too so both fields are empty and the server serves plain HTTP.

Example fix

# before
api:
  server:
    tls:
      key_file_path: /etc/ssl/private/lapi.key
# after
api:
  server:
    tls:
      cert_file_path: /etc/ssl/certs/lapi.crt
      key_file_path: /etc/ssl/private/lapi.key
Defensive patterns

Strategy: validation

Validate before calling

tls := cfg.API.Server.TLS
if tls != nil && (tls.CertFilePath != "" || tls.KeyFilePath != "") {
    if tls.CertFilePath == "" {
        return errors.New("tls.cert_file_path is required when TLS is enabled")
    }
    if _, err := os.Stat(tls.CertFilePath); err != nil { return err }
}

Try / catch

if err := server.StartApiserver(ctx); err != nil {
    log.Fatalf("LAPI startup failed: %v", err)
}

Prevention

When it happens

Trigger: api.server.tls configured with key_file_path set but cert_file_path empty or omitted from the YAML.

Common situations: Partial TLS setup where the key was generated but the cert (or CA-signed cert) was never deployed or the path was mistyped/templated empty; config migration losing one of the two fields.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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