Tailscale — Dependencies#
Module info#
- Module:
tailscale.com - Go version: 1.26.1
- Direct dependencies: 145
- Indirect dependencies: 344 (total in go.mod: 489)
- go.sum entries: 1794 (≈ 897 unique module versions, each listed twice for mod + zip hashes)
Dependency categories#
Core infrastructure#
| Dependency | Purpose |
|---|
github.com/peterbourgon/ff/v3 | Flag and config parsing for tailscaled; flags can be set from environment variables or files |
go.uber.org/zap | Structured logging (used in Kubernetes operator and some sub-systems) |
github.com/go-json-experiment/json | Next-generation JSON encoding (40+ non-test usages); Brad Fitzpatrick is a primary author — Tailscale uses this as a drop-in for encoding/json with richer semantics |
github.com/tailscale/hujson | HuJSON (JSON with comments/trailing commas) for config files like acl.json |
github.com/creachadair/taskgroup / mds / msync | Structured concurrency (taskgroup), data-structure utilities, and sync primitives from a dependency author closely associated with core Tailscale engineering |
github.com/dsnet/try | try.E / try.F helper for error handling — lets deeply nested functions propagate errors without explicit if err != nil chains |
github.com/fsnotify/fsnotify | File system notification for config reload and inotify integration |
github.com/tailscale/depaware | Tailscale’s own tool to track and snapshot dependency graphs; depaware.txt files in cmd/tailscale/ and cmd/tailscaled/ capture exact transitive imports |
github.com/tailscale/setec | Secret management service client (Tailscale internal secrets infrastructure) |
Networking / WireGuard / NAT traversal#
| Dependency | Purpose |
|---|
github.com/tailscale/wireguard-go | Tailscale’s fork of wireguard-go; the core WireGuard userspace implementation. Tailscale maintains this fork to backport fixes, add their own TUN abstractions, and integrate with their netstack mode |
golang.zx2c4.com/wintun | Windows TUN driver by WireGuard’s author Jason Donenfeld; enables WireGuard on Windows |
golang.zx2c4.com/wireguard/windows | Windows-specific WireGuard support library |
github.com/miekg/dns | Full-featured DNS library used in Tailscale’s MagicDNS resolver and DNS fallback logic |
github.com/huin/goupnp | UPnP/IGD for NAT-PMP traversal — discovers and programs consumer routers to open ports |
github.com/inetaf/tcpproxy | inet.af TCP proxy library for HTTPS/SNI-based routing in the Tailscale ingress proxy |
github.com/coder/websocket | WebSocket used in the DERP server’s HTTP upgrade path |
github.com/mdlayher/netlink / genetlink / socket | Low-level Linux netlink socket access for kernel network configuration |
github.com/jsimonetti/rtnetlink | Linux routing table manipulation via rtnetlink |
github.com/tailscale/netlink | Tailscale’s fork of vishvananda/netlink with additional patches |
github.com/coreos/go-iptables | iptables rule management on Linux |
github.com/google/nftables | nftables for modern Linux firewall rule management (kernel 4.9+) |
github.com/vishvananda/netns | Linux network namespace management |
github.com/cilium/ebpf | eBPF programs for the xdpderper DERP server variant that processes WireGuard packets in the kernel via XDP |
github.com/insomniacslk/dhcp | DHCP server/client for Tailscale’s subnet router and exit node scenarios |
golang.org/x/net | Extended Go networking — notably golang.org/x/net/dns/dnsmessage for low-level DNS wire-format parsing |
github.com/pires/go-proxyproto | PROXY protocol (HAProxy protocol) support for proxied connections |
go4.org/netipx | Extended IP address types beyond net/netip — IPRange, IPSet, IPPort with set operations |
github.com/gaissmai/bart | Binary Art Routing Table — highly efficient longest-prefix match IP routing table used in Tailscale’s packet routing |
github.com/akutz/memconn | In-memory net.Conn pairs used extensively in tests to simulate network connections |
github.com/prometheus-community/pro-bing | ICMP ping for the prober subsystem that monitors DERP and relay health |
github.com/kortschak/wol | Wake-on-LAN packet construction |
Security / Cryptography#
| Dependency | Purpose |
|---|
github.com/tailscale/golang-x-crypto | Tailscale’s fork of golang.org/x/crypto — extends it with the Noise protocol implementation used in DERP’s encrypted relay handshake |
golang.org/x/crypto | Standard Go extended crypto (chacha20poly1305, curve25519, blake2s, etc.) |
github.com/hdevalence/ed25519consensus | Ed25519 in “consensus mode” (ZIP 215 specification) — used in TKA (Tailscale Key Authority) where signature verification must be deterministic across implementations |
github.com/fxamacker/cbor/v2 | CBOR binary serialization for TKA Authority Update Messages (AUMs), where compact wire format and deterministic encoding matter |
github.com/google/go-tpm | TPM 2.0 client for hardware device attestation and posture reporting |
github.com/alexbrainman/sspi | Windows Security Support Provider Interface for Windows authentication integration |
software.sslmate.com/src/go-pkcs12 | PKCS#12 certificate bundle handling for Windows certificate store integration |
filippo.io/mkcert | Local TLS certificate generation for development and internal services |
gopkg.in/square/go-jose.v2 | JOSE/JWT library used in the tsidp (Tailscale Identity Provider / OIDC) command |
filippo.io/edwards25519 | Low-level Edwards25519 curve arithmetic backing ed25519consensus |
github.com/tailscale/certstore | Cross-platform access to OS certificate stores (macOS Keychain, Windows cert store) |
github.com/tailscale/peercred | Unix socket peer credential extraction (UID/GID of connecting process) for local IPC authentication |
github.com/tailscale/wf | Windows Filtering Platform bindings — used to implement firewall rules at the Windows kernel level |
github.com/gorilla/csrf | CSRF protection for the local web client served by tailscaled |
Data / Storage / Routing#
| Dependency | Purpose |
|---|
github.com/hashicorp/raft | Raft consensus algorithm — used in the Kubernetes operator for leader election among replicated operator instances |
github.com/hashicorp/raft-boltdb/v2 | BoltDB-backed Raft log store |
go.etcd.io/bbolt | BoltDB embedded key-value store (used via raft-boltdb) |
github.com/axiomhq/hyperloglog | HyperLogLog cardinality estimation for counting unique peer connections at scale |
github.com/jellydator/ttlcache/v3 | TTL-based in-memory cache with generic type parameters |
github.com/golang/groupcache | Distributed singleflight/LRU cache (used in control client to deduplicate concurrent fetches) |
github.com/klauspost/compress | Multi-format compression (zstd, gzip, deflate, s2) for log transport and storage |
github.com/andybalholm/brotli | Brotli compression for HTTP responses in internal services |
github.com/golang/snappy | Snappy compression used in log encoding |
Observability#
| Dependency | Purpose |
|---|
github.com/prometheus/client_golang | Prometheus metrics exposition — Tailscale exposes /metrics from tailscaled |
github.com/prometheus/common | Prometheus utility types and expfmt |
github.com/prometheus/prometheus | Direct Prometheus import used in the proxy-to-grafana tool and prober subsystem for remote write |
go.uber.org/zap / github.com/go-logr/zapr | Zap structured logging used in the Kubernetes operator (which follows controller-runtime’s logr interface) |
Kubernetes (k8s-operator)#
| Dependency | Purpose |
|---|
k8s.io/api / apimachinery / apiserver / client-go | Full Kubernetes API client stack for the k8s-operator |
sigs.k8s.io/controller-runtime | Kubebuilder/controller-runtime framework for building the Kubernetes operator |
sigs.k8s.io/controller-tools | CRD schema generation from Go struct annotations |
helm.sh/helm/v3 | Helm client library used in operator to deploy Helm charts |
sigs.k8s.io/kind | KinD for integration testing the operator against a local Kubernetes cluster |
github.com/elastic/crd-ref-docs | Generates API reference docs from CRD definitions |
k8s.io/apiextensions-apiserver | CRD validation and registration |
| Dependency | Purpose |
|---|
github.com/aws/aws-sdk-go-v2 (core + S3, SSM, EC2 IMDS, STS) | AWS integration: S3 for log storage, SSM for secrets, EC2 IMDS for cloud environment detection |
github.com/coreos/go-systemd | systemd journal and unit management for Linux daemon integration |
github.com/mdlayher/sdnotify | sd_notify protocol to signal readiness to systemd |
github.com/godbus/dbus/v5 | D-Bus for Linux desktop integration (network manager notifications, etc.) |
github.com/gokrazy/gokrazy | gokrazy is a Go-only embedded Linux distribution; Tailscale supports running as a gokrazy appliance for Raspberry Pi/embedded router use cases |
github.com/gokrazy/breakglass / serial-busybox / gokrazy-kernel | gokrazy ecosystem components for the Tailscale appliance build |
github.com/digitalocean/go-smbios | SMBIOS/DMI table reading for hardware posture reporting |
github.com/dblohm7/wingoes | Windows helper library for COM/process management |
github.com/go-ole/go-ole | Windows OLE/COM automation |
SSH / File sharing (Tailscale SSH / Drive)#
| Dependency | Purpose |
|---|
github.com/pkg/sftp | SFTP server implementation for Tailscale SSH’s file transfer capability |
github.com/bramvdbogaerde/go-scp | SCP for scripted file copy in tests and SSH tooling |
github.com/creack/pty | PTY allocation for the SSH server (attaches shell sessions) |
github.com/anmitsu/go-shlex | Shell tokenization for parsing SSH command strings |
github.com/studio-b12/gowebdav | WebDAV client used in Tailscale Drive (file sharing over WebDAV protocol) |
github.com/kballard/go-shellquote | Shell quoting for constructing safe command strings |
github.com/tailscale/goexpect | Expect-style terminal interaction for SSH integration tests |
Testing#
| Dependency | Purpose |
|---|
github.com/frankban/quicktest | Tailscale’s preferred test assertion library — lighter than testify, chainable qt.Check / qt.Assert with go-cmp integration |
github.com/google/go-cmp | Deep struct comparison with custom comparers; heavily used for tailcfg type comparison in tests |
github.com/stretchr/testify | Also present (some packages use it), but quicktest is preferred |
github.com/google/go-tpm | TPM emulator used in attestation tests |
| Dependency | Purpose |
|---|
github.com/golangci/golangci-lint | Linting — pulled as a module dep so go run github.com/golangci/golangci-lint/cmd/golangci-lint uses a pinned version |
honnef.co/go/tools | staticcheck static analysis |
github.com/goreleaser/nfpm/v2 | Package building (.deb, .rpm) for Linux distribution |
github.com/evanw/esbuild | JavaScript bundler used to compile TypeScript web UI assets (cmd/tsconnect) |
github.com/tc-hib/winres | Windows resource embedding (version info, manifests) into .exe files |
UI / Desktop#
| Dependency | Purpose |
|---|
fyne.io/systray | System tray icon management for the Linux/Windows systray binary |
github.com/skip2/go-qrcode | QR code generation for pairing / displaying node keys |
github.com/atotto/clipboard | Clipboard access for copying node keys/auth URLs |
github.com/toqueteos/webbrowser | Opens the default browser for OAuth / admin console flows |
github.com/mattn/go-colorable / go-isatty | Terminal color detection (used in CLI output) |
github.com/Kodeworks/golang-image-ico | Windows .ico file generation for the system tray |
github.com/fogleman/gg | 2D graphics for rendering tray icons |
gVisor (userspace networking)#
| Dependency | Purpose |
|---|
gvisor.dev/gvisor | Google’s gVisor userspace network stack — Tailscale’s “netstack” mode embeds a complete TCP/IP stack in user space, enabling Tailscale to run without kernel TUN support (useful in containers, CI environments, and as a library). This is one of the largest single dependencies by code size |
Stdlib reliance#
Tailscale is deeply stdlib-first. Counting import occurrences across all non-vendor .go files:
| Package | Occurrences |
|---|
fmt | 591 |
context | 422 |
strings | 393 |
time | 370 |
errors | 358 |
os | 303 |
net/netip | 274 |
io | 264 |
net | 258 |
net/http | 245 |
bytes | 232 |
sync | 211 |
encoding/json | 208 |
log | 179 |
slices | 149 |
Key stdlib choices:
net/netip (274 usages): Tailscale was an early and major adopter of net/netip (the new Go 1.18 IP address types). Brad Fitzpatrick, who designed net/netip, works at Tailscale, and the package was motivated in part by Tailscale’s needs. The codebase uses netip.Addr, netip.Prefix, and netip.AddrPort pervasively rather than net.IP.slices: Heavy use of the Go 1.21 slices package (149 occurrences) indicates a modern Go mindset.- Stdlib crypto:
crypto/ed25519, crypto/sha256, crypto/tls, and crypto/rand appear throughout — third-party crypto is only used where stdlib doesn’t reach (Noise protocol, BLAKE2s, CBOR). - No third-party logging at the core: The core
types/logger package wraps a simple func(string, ...any) type, not any third-party logging framework. zap appears only in Kubernetes operator code where controller-runtime mandates logr.
Shared dependencies#
Dependencies that Tailscale shares with many other projects in the 50-project set — these are cross-cutting connection points:
| Dependency | Shared with |
|---|
github.com/prometheus/client_golang | ~29 projects — near-universal Go metrics standard |
github.com/google/go-cmp | ~25 projects — widely used deep comparison in tests |
golang.org/x/crypto / net / sync / sys | Near-universal (x/ packages are ubiquitous) |
github.com/miekg/dns | caddy, consul, grafana, istio, k3s, minio, nomad, traefik, vault — networking projects share DNS needs |
k8s.io/client-go | ~15 projects with Kubernetes integration (argo-cd, dapr, helm, istio, etc.) |
github.com/stretchr/testify | ~30+ projects |
github.com/klauspost/compress | rclone, minio, grafana, and many others for compression |
gvisor.dev/gvisor | Rare outside Tailscale — only a few projects (moby/Docker) share this heavyweight dep |
github.com/hashicorp/raft | consul, nomad, vault — the HashiCorp distributed systems cluster |
Vendoring#
No vendor directory. Tailscale relies on the Go module proxy and go.sum checksums. Despite the large dependency count (489 in go.mod, ~897 module versions in go.sum), they chose not to vendor, likely because:
- The
depaware.txt snapshot files in each binary’s directory already provide a human-readable record of what’s included and serves as a canary for unexpected dependency additions (enforced via deps_test.go). - Vendoring 897 modules would balloon the repository size significantly.
- Tailscale controls its most critical dependencies by maintaining its own forks (
wireguard-go, golang-x-crypto, netlink, go-winio), reducing the risk of upstream supply-chain surprises.
Notable dependency decisions#
1. Fork-critical, module-proxy the rest. Tailscale maintains 8+ forks of upstream packages (wireguard-go, golang-x-crypto, netlink, go-winio, peercred, xnet, etc.). For packages where correctness is security-critical or where Tailscale needs to move faster than upstream, they fork. For everything else, they use the module proxy. This is a deliberate middle ground between full vendoring and pure upstream dependency.
2. go-json-experiment/json as a bet on the future. Brad Fitzpatrick co-designed this package as the proposed replacement for encoding/json in a future Go version (tracking issue golang/go#71497). Tailscale adopting it in production with 40+ usages is both a dogfooding exercise and a signal of their confidence in the design.
3. net/netip everywhere. The netipx package extends net/netip with IPRange, IPSet, and set algebra operations not in stdlib. Tailscale holds go4.org/netipx as a direct dep and uses it pervasively alongside net/netip. This pairing represents the “full Tailscale IP algebra” that predates (and influenced) the stdlib addition.
4. Toolchain deps in go.mod. golangci-lint, staticcheck (honnef.co/go/tools), nfpm, esbuild, and several other build tools are listed as direct go.mod dependencies with no // indirect. This means developers run go run github.com/golangci/golangci-lint/cmd/golangci-lint at a pinned version rather than installing tools separately — a clean reproducibility approach but one that inflates the go.sum significantly.
5. gVisor as a userspace networking library. Importing gvisor.dev/gvisor pulls in Google’s entire OS kernel sandbox as a library for its TCP/IP stack. This is architecturally extraordinary: Tailscale’s “netstack” mode runs a complete layer-3/4 stack in user space, enabling operation in environments without kernel TUN support. The dependency exists because no lighter-weight, production-quality Go userspace TCP/IP stack existed at the time Tailscale adopted it.
6. CBOR for TKA. The choice of CBOR over JSON/protobuf for TKA (Authority Update Messages) is deliberate: CBOR is both compact and has a canonical encoding form (CBOR Deterministic Encoding) required for cryptographic signing. Protobuf’s canonical encoding is more complex; JSON’s is not standardized. CBOR gives a well-specified byte sequence to sign.
7. Minimal logging framework. The core daemon avoids structured logging frameworks. tailscale.com/types/logger is simply type Logf func(format string, args ...any) — a function type that can be composed, wrapped, and injected. This design means every subsystem can receive a contextual logger without depending on a third-party logging package.