crowdsecurity/crowdsec · error

missing TLS key file

Error message

missing TLS key file

What it means

The appsec HTTP server can be started with TLS. TLS is only attempted when at least one of cert_file/key_file is set; if key_file is empty while cert_file is set, ServeTLS cannot be configured and the server startup goroutine emits this error on serverError.

Source

Thrown at pkg/acquisition/modules/appsec/run.go:32

	"github.com/crowdsecurity/go-cs-lib/trace"

	"github.com/crowdsecurity/crowdsec/pkg/apiclient"
	"github.com/crowdsecurity/crowdsec/pkg/appsec"
	"github.com/crowdsecurity/crowdsec/pkg/csnet"
	"github.com/crowdsecurity/crowdsec/pkg/pipeline"
)

func (w *Source) listenAndServe(ctx context.Context, t *tomb.Tomb) error {
	w.logger.Infof("%d appsec runner to start", len(w.AppsecRunners))

	serverError := make(chan error, 2)

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

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

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

			err = w.server.ServeTLS(listener, w.config.CertFilePath, w.config.KeyFilePath)
		} else {
			err = w.server.Serve(listener)
		}

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

View on GitHub (pinned to 909b515798)

Solutions

  1. Add the key_file path next to cert_file in the appsec datasource config
  2. Verify the key file actually exists and the path resolves in the container/mount
  3. If you don't want TLS, remove cert_file so the server starts in plain HTTP mode

Example fix

// before (acquisition.yaml)
source: appsec
 cert_file: /etc/ssl/crowdsec/tls.cert
// after
source: appsec
 cert_file: /etc/ssl/crowdsec/tls.cert
 key_file: /etc/ssl/crowdsec/tls.key
Defensive patterns

Strategy: validation

Validate before calling

if (cfg.CertFilePath != "" || cfg.KeyFilePath != "") && cfg.KeyFilePath == "" {
    return errors.New("cert_file set without key_file")
}

Try / catch

go func() {
    if err := <-serverError; err != nil {
        if strings.Contains(err.Error(), "missing TLS") { /* fix cert/key pair in config */ }
    }
}()

Prevention

When it happens

Trigger: In run(), startServer is called with canTLS and w.config.CertFilePath set but w.config.KeyFilePath empty — the config supplied cert_file but no key_file.

Common situations: appsec acquisition TLS stanza where the user filled in cert_file but forgot key_file, or a secret-mount/env substitution left the key path empty in containers.

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/d537352d75660f66. Report an issue: GitHub.