cloudflare/cloudflared · error
either ServerName or InsecureSkipVerify must be specified…
Error message
either ServerName or InsecureSkipVerify must be specified in the tls.Config
What it means
At the end of CreateTunnelConfig, the resulting *tls.Config is validated: TLS server-name verification requires either a ServerName (the hostname to validate the server certificate against) or InsecureSkipVerify=true. If both ServerName is empty and InsecureSkipVerify is false, crypto/tls could never verify the peer, so cloudflared rejects the config up front with this error instead of failing obscurely at handshake time.
Solutions
- Pass the correct hostname (e.g. the edge or origin SNI, such as your tunnel's Cloudflare hostname) as the serverName argument.
- If verification must be disabled (testing only), construct the config then set tlsConfig.InsecureSkipVerify = true before use — or better, keep ServerName set and avoid disabling verification.
- Fix the upstream source of the hostname (flag/config/env) so it is non-empty by the time CreateTunnelConfig is called; validate it earlier in startup.
Example fix
// before
hostname := os.Getenv("TUNNEL_HOSTNAME") // may be ""
tlsCfg, err := tlsconfig.CreateTunnelConfig(caPath, hostname)
// after
hostname := os.Getenv("TUNNEL_HOSTNAME")
if hostname == "" {
log.Fatal().Msg("TUNNEL_HOSTNAME must be set")
}
tlsCfg, err := tlsconfig.CreateTunnelConfig(caPath, hostname) Defensive patterns
Strategy: validation
Validate before calling
func validateTunnelTLSInput(caCert, serverName string) error {
if serverName == "" {
return errors.New("serverName must be non-empty (or set InsecureSkipVerify on the returned config)")
}
return nil
} Try / catch
tlsCfg, err := tlsconfig.CreateTunnelConfig(caCert, serverName)
if err != nil {
if strings.Contains(err.Error(), "ServerName or InsecureSkipVerify") {
log.Fatal().Msg("hostname/SNI missing in config; set the tunnel hostname")
}
log.Fatal().Err(err).Msg("failed to build tunnel TLS config")
} Prevention
- Fail fast on empty hostname flags/env vars before building TLS config.
- Prefer setting ServerName over InsecureSkipVerify; never ship skip-verify in production.
- Derive serverName from the tunnel hostname already validated at startup.
When it happens
Trigger: Calling CreateTunnelConfig(caCert, "") — i.e. with an empty serverName — and not setting InsecureSkipVerify on the returned config before use. Any caller (prepareTunnelConfig, probeTLSConfig, tests) that passes an empty server name without disabling verification.
Common situations: A config file omits the hostname/SNI field; hostname is derived from an env var or flag that is unset and yields ""; code builds the tunnel config before the target hostname is known and forgets to set InsecureSkipVerify for that case.
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.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- error appending custom CA to cert pool
- error loading the certificate pool
- parse CA certificate
- read CA certificate
- unable to create TLS config to connect with edge
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/f804931246973f30.
Report an issue: GitHub.
Appendix: source
Thrown at tlsconfig/origin_ca.go:107
}
if tlsConfig.RootCAs == nil {
rootCAPool, err := x509.SystemCertPool()
if err != nil {
return nil, errors.Wrap(err, "unable to get x509 system cert pool")
}
cfRootCA, err := GetCloudflareRootCA()
if err != nil {
return nil, errors.Wrap(err, "could not append Cloudflare Root CAs to cloudflared certificate pool")
}
for _, cert := range cfRootCA {
rootCAPool.AddCert(cert)
}
tlsConfig.RootCAs = rootCAPool
}
if tlsConfig.ServerName == "" && !tlsConfig.InsecureSkipVerify {
return nil, fmt.Errorf("either ServerName or InsecureSkipVerify must be specified in the tls.Config")
}
return tlsConfig, nil
}
func loadOriginCertPool(originCAPoolPEM []byte, log *zerolog.Logger) (*x509.CertPool, error) {
// Get the global pool
certPool, err := loadGlobalCertPool(log)
if err != nil {
return nil, err
}
// Then, add any custom origin CA pool the user may have passed
if originCAPoolPEM != nil {
if !certPool.AppendCertsFromPEM(originCAPoolPEM) {
log.Info().Msg("could not append the provided origin CA to the cloudflared certificate pool")
}
}
View on GitHub (pinned to 2253eeeb25)