crowdsecurity/crowdsec · error
user/password authentication and TLS authentication are mutu
Error message
user/password authentication and TLS authentication are mutually exclusive
What it means
The LAPI client supports either username/password authentication or TLS mutual (certificate) authentication, not both. Load() rejects a configuration that sets client TLS cert/key auth while a login is present, because the two credential mechanisms are mutually exclusive by design.
Source
Thrown at pkg/csconfig/api.go:187
if strings.HasPrefix(l.Credentials.URL, "http") && !strings.HasSuffix(l.Credentials.URL, "/") {
l.Credentials.URL += "/"
}
}
// is the configuration asking for client authentication via TLS?
credTLSClientAuth := l.Credentials.CertPath != "" || l.Credentials.KeyPath != ""
// is the configuration asking for TLS encryption and server authentication?
credTLS := credTLSClientAuth || l.Credentials.CACertPath != ""
credSocket := strings.HasPrefix(l.Credentials.URL, "/")
if credTLS && credSocket {
return errors.New("cannot use TLS with a unix socket")
}
if credTLSClientAuth && l.Credentials.Login != "" {
return errors.New("user/password authentication and TLS authentication are mutually exclusive")
}
if l.InsecureSkipVerify == nil {
apiclient.InsecureSkipVerify = false
} else {
apiclient.InsecureSkipVerify = *l.InsecureSkipVerify
}
if l.Credentials.CACertPath != "" {
caCert, err := os.ReadFile(l.Credentials.CACertPath)
if err != nil {
return fmt.Errorf("failed to load cacert: %w", err)
}
caCertPool, err := x509.SystemCertPool()
if err != nil {
log.Warningf("Error loading system CA certificates: %s", err)
}View on GitHub (pinned to 909b515798)
Solutions
- Remove the login (and password) entries when authenticating with a client certificate
- Or remove the client cert/key and ca_cert_path entries and keep login/password
- Restart crowdsec after cleaning the credentials block
Example fix
// before
api:
client:
credentials:
login: myuser
cert_path: /etc/crowdsec/ssl/client.crt
key_path: /etc/crowdsec/ssl/client.key
// after
api:
client:
credentials:
login: myuser
password: mypassword
url: https://lapi.example.com:8080 Defensive patterns
Strategy: validation
Validate before calling
if l.Credentials.Login != "" && (l.Credentials.CertPath != "" || l.Credentials.KeyPath != "") {
return errors.New("choose either login/password or TLS client cert auth")
}
if err := l.Load(); err != nil { ... } Type guard
func usesTLSClientAuth(cred Credentials) bool { return cred.CertPath != "" && cred.KeyPath != "" } Try / catch
if err := clientCfg.Load(); err != nil {
return fmt.Errorf("lapi client config: %w", err)
} Prevention
- Pick one auth scheme per host and remove the other entries entirely
- After migrating auth schemes, verify no stale cert/key or login fields remain
- Test agent startup in CI with the shipped default config
When it happens
Trigger: api.client.credentials contains login (non-empty) together with client cert/key paths that enable credTLSClientAuth; LocalApiClientCfg.Load() raises the error during config load.
Common situations: Merging a bouncer-style cert config with an agent-style login/password config; leftovers from a previous auth scheme after migrating from TLS certs to password auth; copy-pasted credentials blocks from two different hosts.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- cannot use TLS with a unix socket
- could not access CRL file: %w
- client certificate OU %v doesn't match expected OU %v
- basic_auth is selected, but basic_auth is not provided
- basic_auth is selected, but username is not provided
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/ab0328c8a0e19964.
Report an issue: GitHub.