Headscale — Dependencies#
Module info#
- Module: github.com/juanfont/headscale
- Go version: 1.26.1
- Direct dependencies: 54
- Indirect dependencies: ~150 (go.sum has 698 lines → ~349 unique module versions)
Dependency categories#
Core infrastructure#
- github.com/rs/zerolog v1.34.0 — structured JSON logging; used throughout every package; zero-allocation design aligns with the project’s performance focus
- github.com/philip-bui/grpc-zerolog v1.0.1 — zerolog interceptor for gRPC; keeps log format uniform across gRPC and HTTP handlers
- github.com/spf13/cobra v1.10.2 — CLI framework for the
headscalemanagement commands (users, nodes, API keys, routes, etc.) - github.com/spf13/viper v1.21.0 — hierarchical config loading from YAML file + env vars + flags
- github.com/pterm/pterm v0.12.82 — terminal table/progress output for CLI commands
- github.com/jagottsicher/termcolor v1.0.2 — terminal color capability detection; respects
NO_COLORmanifesto - github.com/fsnotify/fsnotify v1.9.0 — file watcher (used by viper for hot-reload of config)
- github.com/cenkalti/backoff/v5 v5.0.3 — exponential backoff for connection retries
- github.com/creachadair/command v0.2.0 — alternative CLI sub-command framework used by the
cmd/hiintegration test runner (not the main server) - github.com/creachadair/flax v0.0.5 — flag utility library paired with
creachadair/command - github.com/tcnksm/go-latest v0.0.0 — checks whether the running binary is the latest GitHub release; used in the version command
Networking/HTTP#
- github.com/go-chi/chi/v5 v5.2.5 — main HTTP router for the headscale server; handles both REST API routes and Tailscale Noise endpoint mounting
- github.com/go-chi/metrics v0.1.1 — Prometheus request metrics middleware for chi
- github.com/gorilla/mux v1.8.1 — Gorilla multiplexer; present alongside chi because the Docker SDK (a direct dependency via
docker/docker) depends on it transitively, and theory/dockertestintegration test library also uses it - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 — transcodes REST JSON requests to gRPC, enabling the management API to be served as both gRPC and HTTP/REST from a single
.protodefinition - google.golang.org/grpc v1.78.0 — gRPC server and client for the management API
- github.com/coder/websocket v1.8.14 — WebSocket library used in the Tailscale Noise/polling long-poll transport
- golang.org/x/crypto v0.48.0 — TLS, ACME/autocert for automatic Let’s Encrypt certificate management
- golang.org/x/net v0.50.0 — HTTP/2 support, network utilities
- golang.org/x/oauth2 v0.34.0 — OAuth2 flows for OIDC authentication
- github.com/coreos/go-oidc/v3 v3.17.0 — OpenID Connect provider support for user authentication
- go4.org/netipx v0.0.0 — extended IP set/prefix utilities built on
net/netip; used extensively for the policy engine’s IP-based ACL matching
Data/Storage#
- gorm.io/gorm v1.31.1 — ORM; provides the dual SQLite/PostgreSQL abstraction layer
- gorm.io/driver/postgres v1.6.0 — GORM PostgreSQL driver (for production deployments)
- github.com/glebarez/sqlite v1.11.0 — pure-Go SQLite GORM driver (wraps
modernc.org/sqlite); no CGo required - modernc.org/sqlite v1.44.3 — pure-Go SQLite engine; listed in a specially commented
requireblock alongside itsmodernc.org/libcpin because the pair must be upgraded in lockstep - github.com/go-gormigrate/gormigrate/v2 v2.1.5 — ordered migration framework; headscale’s migrations are an append-only immutable list with strict rules (never reorder, never disable FK)
- github.com/tailscale/squibble v0.0.0 — Tailscale’s own SQLite schema versioning tool; validates that schema matches expected hash
- github.com/tailscale/tailsql v0.0.0 — Tailscale SQL utilities; used for DB query helpers
- google.golang.org/protobuf v1.36.11 — Protocol Buffer runtime for the generated management API types (
gen/) - google.golang.org/genproto/googleapis/api v0.0.0 — Google API well-known proto annotations (HTTP transcoding rules for grpc-gateway)
- gopkg.in/yaml.v3 v3.0.1 — YAML parsing for config files and API output
- github.com/tailscale/hujson v0.0.0 — HuJSON (JSON with comments and trailing commas) for policy/ACL files
- github.com/go-json-experiment/json v0.0.0 — next-generation JSON library (proposal to replace encoding/json); likely used for high-throughput MapResponse serialization
- zgo.at/zcache/v2 v2.4.1 — in-memory TTL cache; used for node registration and auth request caching
- github.com/puzpuzpuz/xsync/v4 v4.4.0 — high-performance concurrent hash map; used in the NodeStore and notifier for lock-free read paths
- github.com/gofrs/uuid/v5 v5.4.0 — UUID generation for node IDs and API keys
- zombiezen.com/go/postgrestest v1.0.1 — embeds a real PostgreSQL instance for testing; used in the DB test suite to avoid mocking
Observability / Diagnostics#
- github.com/prometheus/client_golang v1.23.2 — Prometheus metrics; headscale exposes a
/metricsendpoint - github.com/prometheus/common v0.67.5 — shared Prometheus types (used in config for duration parsing)
- github.com/arl/statsviz v0.8.0 — live Go runtime statistics visualizer served over HTTP at
/debug/statsviz - github.com/pkg/profile v1.7.0 — CPU/memory/block profiling via environment variable toggle
- github.com/sasha-s/go-deadlock v0.3.6 — drop-in
sync.Mutexreplacement that detects deadlocks; used in production code (not just tests) for the NodeStore and notifier
Testing#
- github.com/stretchr/testify v1.11.1 — assertions (
require/assert); near-universal in the test suite - github.com/google/go-cmp v0.7.0 — deep semantic comparison (proto-aware diff)
- github.com/ory/dockertest/v3 v3.12.0 — Docker container lifecycle for database integration tests (spins up real PostgreSQL)
- github.com/docker/docker v28.5.2+incompatible — Docker API client used by the
cmd/hiintegration test runner for full orchestration of Tailscale client containers - github.com/oauth2-proxy/mockoidc v0.0.0 — mock OIDC provider for testing OIDC authentication flows
- github.com/davecgh/go-spew v1.1.2 — deep pretty-printer; required by testify for diff output
The Tailscale Dependency#
- tailscale.com v1.94.1 — the official Tailscale client library; the single most architecturally significant dependency. Headscale imports Tailscale’s own Go types (
tailcfg.MapRequest,tailcfg.MapResponse,tailcfg.Node,types/key,types/dnstype, etc.) directly, ensuring that headscale speaks the exact same wire protocol as the official control server. This dependency also pulls in ~50 transitive indirect dependencies includinggvisor.dev/gvisor(userspace networking),tailscale/wireguard-go, AWS SDK (for certain Tailscale features), andgolang.zx2c4.com/wireguard/windows.
Other#
- github.com/samber/lo v1.52.0 — generic collection utilities (map, filter, find); used throughout to avoid verbose loops
- golang.org/x/exp v0.0.0 — experimental Go stdlib features (primarily generic data structures)
- golang.org/x/sync v0.19.0 —
errgroup,semaphore; used in app.go and state.go for structured goroutine lifecycles - github.com/chasefleming/elem-go v0.31.0 — HTML element builder DSL; used in the OIDC callback and client configuration template pages
Stdlib reliance#
Headscale makes heavy use of stdlib. The core hot-path packages (poll.go, state/state.go, db/db.go, hscontrol/app.go) import 10-20 stdlib packages each:
- Network:
net,net/http,net/netip,net/url— stdlibnet/netipis used directly for all IP address handling (not third-party) - Concurrency:
sync,sync/atomic,context,time— all stdlib; third-party only addserrgroupandxsyncon top - Encoding:
encoding/json,encoding/binary— stdlib as the baseline;go-json-experimentandhujsonare additive for specific formats - Data structures:
slices,maps,cmp(Go 1.21+ generics) — stdlib generics used widely, supplemented bysamber/lofor more complex operations
The pattern is: stdlib handles the majority of business logic; third-party is strictly additive for domain-specific needs (Tailscale protocol, ORM, gRPC, observability).
Shared dependencies#
Dependencies headscale shares with many other projects in the 50-project set:
github.com/spf13/cobra+github.com/spf13/viper— near-universal pairing for Go server CLIgithub.com/rs/zerolog— increasingly adopted alternative tozap/logrusgithub.com/prometheus/client_golang— standard Prometheus instrumentationgithub.com/stretchr/testify— dominant Go test frameworkgithub.com/google/go-cmp— common in test suites alongside testifygolang.org/x/{crypto,net,sync,oauth2,exp}— common extension of stdlibgoogle.golang.org/grpc+google.golang.org/protobuf— standard gRPC stackgopkg.in/yaml.v3— dominant YAML parsergorm.io/gorm— common ORM in production Go serversgithub.com/gorilla/mux— older router, here mostly as a transitive dep
Unique to headscale or rare in the set:
tailscale.com— unique to headscalegvisor.dev/gvisor— pulled in by tailscale.com; very unusual as an indirect depgithub.com/sasha-s/go-deadlockin production code — raremodernc.org/sqlitewith pinnedmodernc.org/libc— niche pure-Go SQLite approachzombiezen.com/go/postgrestest— relatively niche embedded Postgres for tests
Vendoring#
No vendor directory. Headscale uses the Go module proxy for dependency resolution. The go.mod includes inline comments calling out two fragile dependency chains that must be upgraded in lockstep (modernc.org/sqlite + modernc.org/libc, and gvisor.dev/gvisor + tailscale.com), suggesting that the team manages deps carefully even without vendoring.
Notable dependency decisions#
tailscale.comas a first-class dependency. Rather than reverse-engineering Tailscale’s wire format into independent structs, headscale imports the official client library and reuses its types verbatim. This ensures protocol compatibility across Tailscale client upgrades but means headscale’s release cadence is partially coupled to Tailscale’s — a deliberate trade-off for correctness.Two HTTP routers (
chi+gorilla/mux).chi/v5is the primary router;gorilla/muxarrives viadocker/dockerandory/dockertest(both used for integration testing). Thegorilla/muximport ingo.modis listed as a direct dep because the Docker SDK’s module graph forces it, but headscale’s own code uses only chi.Dual SQLite approach (
glebarez/sqlitewrappingmodernc.org/sqlite). The pure-Go SQLite stack (no CGo) is essential for cross-compilation and multi-arch Docker images. Thego.modincludes an unusually detailed comment explaining the fragile dependency chain and exact upgrade procedure — a rare example of dependency governance documentation inline with the module file.go-deadlockin production. Using a deadlock-detecting mutex in production (not just in tests or with a build tag) reflects the seriousness of the NodeStore’s concurrency guarantees. The team clearly experienced real deadlocks during development of the copy-on-write in-memory cache.go-json-experiment/jsonalongsideencoding/json. The experimental next-generation JSON library is imported directly, suggesting the team is evaluating or already using its performance improvements for the high-frequency MapResponse serialization path (every 15–60 seconds per client).Three Tailscale-internal libraries as direct deps (
hujson,squibble,tailsql). Headscale deliberately pulls in Tailscale sub-libraries beyond the maintailscale.commodule. This creates a tight coupling to Tailscale’s internal tooling decisions but ensures consistency with how Tailscale itself manages HuJSON policy files and SQLite schemas.gvisor.dev/gvisoras the heaviest indirect dep. The Google gVisor kernel arrives as an indirect dependency throughtailscale.com(for its userspace network stack). This is a multi-hundred-thousand-line codebase that significantly inflates build times and binary size, entirely outside headscale’s control. Thego.modcalls this out explicitly with a pinned version and upgrade instructions.