{"record":{"id":"98da3b14c5189fda","repo":"caddyserver/caddy","slug":"making-tls-client-config-v","errorCode":null,"errorMessage":"making TLS client config: %v","messagePattern":"making TLS client config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/httptransport.go","lineNumber":417,"sourceCode":"\t}\n\n\trt := &http.Transport{\n\t\tProxy:                  proxyWrapper,\n\t\tDialContext:            dialContext,\n\t\tMaxConnsPerHost:        h.MaxConnsPerHost,\n\t\tResponseHeaderTimeout:  time.Duration(h.ResponseHeaderTimeout),\n\t\tExpectContinueTimeout:  time.Duration(h.ExpectContinueTimeout),\n\t\tMaxResponseHeaderBytes: h.MaxResponseHeaderSize,\n\t\tWriteBufferSize:        h.WriteBufferSize,\n\t\tReadBufferSize:         h.ReadBufferSize,\n\t}\n\n\tif h.TLS != nil {\n\t\trt.TLSHandshakeTimeout = time.Duration(h.TLS.HandshakeTimeout)\n\t\tvar err error\n\t\trt.TLSClientConfig, err = h.TLS.MakeTLSClientConfig(caddyCtx)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"making TLS client config: %v\", err)\n\t\t}\n\n\t\tserverNameHasPlaceholder := strings.Contains(h.TLS.ServerName, \"{\")\n\n\t\t// We need to use custom DialTLSContext if:\n\t\t// 1. ServerName has a placeholder that needs to be replaced at request-time, OR\n\t\t// 2. ProxyProtocol is enabled, because req.URL.Host is modified to include\n\t\t//    client address info with \"->\" separator which breaks Go's address parsing\n\t\tif serverNameHasPlaceholder || h.ProxyProtocol != \"\" {\n\t\t\trt.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {\n\t\t\t\t// reuses the dialer from above to establish a plaintext connection\n\t\t\t\tconn, err := dialContext(ctx, network, addr)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\t// but add our own handshake logic\n\t\t\t\ttlsConfig := rt.TLSClientConfig.Clone()","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/httptransport.go#L399-L435","documentation":"The reverse_proxy HTTP transport delegates to the TLS connection policy module (`h.TLS.MakeTLSClientConfig`) to build a *tls.Config for upstream connections. Any failure there — bad client certificate files, invalid cipher suites, unsupported TLS version bounds — surfaces wrapped with this message during provisioning.","triggerScenarios":"`transport http { tls_client_auth { cert_file ... key_file ... } }` pointing to unreadable/corrupt PEM files; `tls_versions` with values like `tls1.4`; `ciphers` naming an unsupported suite; bad `tls_trusted_ca_certs` file in reverse_proxy's tls block.","commonSituations":"Cert paths relative to the wrong working directory, PEM files containing a cert where a key is expected, mTLS rotation leaving a half-updated keypair, or copying TLS settings from an nginx frontend config with different cipher names.","solutions":["Read the nested cause after the colon — it names the exact TLS setting that failed","Verify file paths are absolute or relative to where caddy runs, and that cert/key are valid PEM","Restrict tls_versions to tls1.2/tls1.3 and remove cipher overrides unless required (Go 1.3 suites are fixed)","Validate the pair with openssl: openssl x509 -in cert.pem -noout && openssl pkey -in key.pem -noout"],"exampleFix":"# before\ntransport http {\n\ttls {\n\t\tciphers TLS_ECDHE_RSA_WITH_AES_128_SHA256\n\t}\n}\n# after\ntransport http {\n\ttls\n}","handlingStrategy":"validation","validationCode":"// preflight the key material used by the TLS block\nfunc checkTLSFiles(certPath, keyPath, caPath string) error {\n\tfor _, p := range []string{certPath, keyPath, caPath} {\n\t\tif p == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif _, err := os.Stat(p); err != nil {\n\t\t\treturn fmt.Errorf(\"tls file %s: %w\", p, err)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use absolute paths for cert/CA files in proxy TLS blocks","Validate PEMs with openssl during mTLS rotation before reloading Caddy","Avoid cipher/version overrides unless a specific upstream requires them"],"tags":["reverse-proxy","tls","http-transport","config"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}