{"record":{"id":"5afcb38444f8623f","repo":"tailscale/tailscale","slug":"ts-experimental-enable-forwarding-optimizations-is","errorCode":null,"errorMessage":"TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS is not supported in userspace mode","messagePattern":"TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS is not supported in userspace mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/containerboot/settings.go","lineNumber":325,"sourceCode":"\t\treturn errors.New(\"TS_ID_TOKEN and TS_AUDIENCE cannot both be set\")\n\t}\n\tif s.Audience != \"\" && s.ClientSecret != \"\" {\n\t\treturn errors.New(\"TS_AUDIENCE and TS_CLIENT_SECRET cannot both be set\")\n\t}\n\tif s.AuthKey != \"\" && (s.ClientID != \"\" || s.ClientSecret != \"\" || s.IDToken != \"\" || s.Audience != \"\") {\n\t\treturn errors.New(\"TS_AUTHKEY cannot be used with TS_CLIENT_ID, TS_CLIENT_SECRET, TS_ID_TOKEN, or TS_AUDIENCE.\")\n\t}\n\tif s.AllowProxyingClusterTrafficViaIngress && s.UserspaceMode {\n\t\treturn errors.New(\"EXPERIMENTAL_ALLOW_PROXYING_CLUSTER_TRAFFIC_VIA_INGRESS is not supported in userspace mode\")\n\t}\n\tif s.AllowProxyingClusterTrafficViaIngress && s.ServeConfigPath == \"\" {\n\t\treturn errors.New(\"EXPERIMENTAL_ALLOW_PROXYING_CLUSTER_TRAFFIC_VIA_INGRESS is set but this is not a cluster ingress proxy\")\n\t}\n\tif s.AllowProxyingClusterTrafficViaIngress && s.PodIP == \"\" {\n\t\treturn errors.New(\"EXPERIMENTAL_ALLOW_PROXYING_CLUSTER_TRAFFIC_VIA_INGRESS is set but POD_IP is not set\")\n\t}\n\tif s.EnableForwardingOptimizations && s.UserspaceMode {\n\t\treturn errors.New(\"TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS is not supported in userspace mode\")\n\t}\n\tif s.HealthCheckAddrPort != \"\" {\n\t\tlog.Printf(\"[warning] TS_HEALTHCHECK_ADDR_PORT is deprecated and will be removed in 1.82.0. Please use TS_ENABLE_HEALTH_CHECK and optionally TS_LOCAL_ADDR_PORT instead.\")\n\t\tif _, err := netip.ParseAddrPort(s.HealthCheckAddrPort); err != nil {\n\t\t\treturn fmt.Errorf(\"error parsing TS_HEALTHCHECK_ADDR_PORT value %q: %w\", s.HealthCheckAddrPort, err)\n\t\t}\n\t}\n\tif s.localMetricsEnabled() || s.localHealthEnabled() || s.EgressProxiesCfgPath != \"\" {\n\t\tif _, err := netip.ParseAddrPort(s.LocalAddrPort); err != nil {\n\t\t\treturn fmt.Errorf(\"error parsing TS_LOCAL_ADDR_PORT value %q: %w\", s.LocalAddrPort, err)\n\t\t}\n\t}\n\tif s.DebugAddrPort != \"\" {\n\t\tif _, err := netip.ParseAddrPort(s.DebugAddrPort); err != nil {\n\t\t\treturn fmt.Errorf(\"error parsing TS_DEBUG_ADDR_PORT value %q: %w\", s.DebugAddrPort, err)\n\t\t}\n\t}\n\tif s.HealthCheckEnabled && s.HealthCheckAddrPort != \"\" {","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/containerboot/settings.go#L307-L343","documentation":"containerboot rejects the combination of TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS=true with userspace networking mode. The forwarding optimizations install kernel-level forwarding rules (iptables/netfilter fast paths) that only exist when tailscaled owns a kernel network stack; in userspace mode (TS_USERSPACE=true, the default at settings.go:109) there is no kernel stack to optimize, so settings validation fails fast instead of silently doing nothing.","triggerScenarios":"TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS set to true (default false, settings.go:129) AND TS_USERSPACE unset (defaults true) or explicitly set to true, in the same container.","commonSituations":"Enabling subnet-router/forwarding optimizations on a proxy pod without also switching it out of the default userspace mode; Helm charts or examples that keep TS_USERSPACE defaulting to true; upgrading a config where userspace mode was previously disabled elsewhere.","solutions":["Set TS_USERSPACE=false in the container env — this requires the container to have /dev/net/tun and the NET_ADMIN capability","If the workload must stay in userspace mode (e.g. no TUN device), unset TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS","Audit the Helm values / manifest for stale defaults that set TS_USERSPACE=true"],"exampleFix":"# before\nenv:\n  - name: TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS\n    value: 'true'\n  - name: TS_USERSPACE\n    value: 'true'\n\n# after\nenv:\n  - name: TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS\n    value: 'true'\n  - name: TS_USERSPACE\n    value: 'false'\n# plus: /dev/net/tun device and NET_ADMIN capability on the container","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\nset -euo pipefail\nuserspace=\"${TS_USERSPACE:-true}\"\nfwd=\"${TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS:-false}\"\nif [[ \"$fwd\" == \"true\" && \"$userspace\" == \"true\" ]]; then\n  echo 'TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS requires TS_USERSPACE=false' >&2\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember TS_USERSPACE defaults to true — never assume unset means kernel mode","When enabling forwarding optimizations, always set TS_USERSPACE=false explicitly in the same change","Pair kernel mode with the required device/capability checks (dev/net/tun, NET_ADMIN) in CI manifest tests"],"tags":["containerboot","userspace-networking","configuration","forwarding","environment-variables"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}