tailscale/tailscale · error

TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS is not suppo

Error message

TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS is not supported in userspace mode

What it means

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.

Source

Thrown at cmd/containerboot/settings.go:325

		return errors.New("TS_ID_TOKEN and TS_AUDIENCE cannot both be set")
	}
	if s.Audience != "" && s.ClientSecret != "" {
		return errors.New("TS_AUDIENCE and TS_CLIENT_SECRET cannot both be set")
	}
	if s.AuthKey != "" && (s.ClientID != "" || s.ClientSecret != "" || s.IDToken != "" || s.Audience != "") {
		return errors.New("TS_AUTHKEY cannot be used with TS_CLIENT_ID, TS_CLIENT_SECRET, TS_ID_TOKEN, or TS_AUDIENCE.")
	}
	if s.AllowProxyingClusterTrafficViaIngress && s.UserspaceMode {
		return errors.New("EXPERIMENTAL_ALLOW_PROXYING_CLUSTER_TRAFFIC_VIA_INGRESS is not supported in userspace mode")
	}
	if s.AllowProxyingClusterTrafficViaIngress && s.ServeConfigPath == "" {
		return errors.New("EXPERIMENTAL_ALLOW_PROXYING_CLUSTER_TRAFFIC_VIA_INGRESS is set but this is not a cluster ingress proxy")
	}
	if s.AllowProxyingClusterTrafficViaIngress && s.PodIP == "" {
		return errors.New("EXPERIMENTAL_ALLOW_PROXYING_CLUSTER_TRAFFIC_VIA_INGRESS is set but POD_IP is not set")
	}
	if s.EnableForwardingOptimizations && s.UserspaceMode {
		return errors.New("TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS is not supported in userspace mode")
	}
	if s.HealthCheckAddrPort != "" {
		log.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.")
		if _, err := netip.ParseAddrPort(s.HealthCheckAddrPort); err != nil {
			return fmt.Errorf("error parsing TS_HEALTHCHECK_ADDR_PORT value %q: %w", s.HealthCheckAddrPort, err)
		}
	}
	if s.localMetricsEnabled() || s.localHealthEnabled() || s.EgressProxiesCfgPath != "" {
		if _, err := netip.ParseAddrPort(s.LocalAddrPort); err != nil {
			return fmt.Errorf("error parsing TS_LOCAL_ADDR_PORT value %q: %w", s.LocalAddrPort, err)
		}
	}
	if s.DebugAddrPort != "" {
		if _, err := netip.ParseAddrPort(s.DebugAddrPort); err != nil {
			return fmt.Errorf("error parsing TS_DEBUG_ADDR_PORT value %q: %w", s.DebugAddrPort, err)
		}
	}
	if s.HealthCheckEnabled && s.HealthCheckAddrPort != "" {

View on GitHub (pinned to cfe32b8be6)

Solutions

  1. Set TS_USERSPACE=false in the container env — this requires the container to have /dev/net/tun and the NET_ADMIN capability
  2. If the workload must stay in userspace mode (e.g. no TUN device), unset TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS
  3. Audit the Helm values / manifest for stale defaults that set TS_USERSPACE=true

Example fix

# before
env:
  - name: TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS
    value: 'true'
  - name: TS_USERSPACE
    value: 'true'

# after
env:
  - name: TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS
    value: 'true'
  - name: TS_USERSPACE
    value: 'false'
# plus: /dev/net/tun device and NET_ADMIN capability on the container
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
set -euo pipefail
userspace="${TS_USERSPACE:-true}"
fwd="${TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS:-false}"
if [[ "$fwd" == "true" && "$userspace" == "true" ]]; then
  echo 'TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS requires TS_USERSPACE=false' >&2
  exit 1
fi

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15). Data as JSON: /api/errors/5afcb38444f8623f. Report an issue: GitHub.