Having managed Tailscale in production for two years and recently evaluating Netmaker for a greenfield project, the operational differences are stark. Both solve the mesh VPN problem, but the architectural and management philosophies diverge significantly.
My primary criteria were state management and declarative configuration. Tailscale's coordination server is a managed service (or self-hosted Headscale), which abstracts away the network state. Netmaker is fully self-hosted, and its entire configuration is driven by a Kubernetes operator or Terraform provider. This is a critical differentiator.
**Key operational observations:**
* **State & Drift:** Netmaker's Kubernetes CRDs or Terraform resources provide a single source of truth. You can see intended network state in git. Tailscale/Headscale state is more opaque; you manage via CLI or API calls, making drift detection a manual process.
* **Modularity & ACLs:** Tailscale's ACLs are powerful but a unique policy language in a JSON structure. Netmaker uses standard Kubernetes NetworkPolicy semantics if deployed via the operator, which is easier to integrate with existing K8s tooling.
* **Secret Management:** Both require handling wireguard keys. Netmaker's operator stores them in K8s secrets, which plugs into existing secret backends (Vault, etc.). Tailscale keys are ephemeral; the service handles rotation, which is simpler but less transparent.
For infrastructure-as-code purists, Netmaker's model feels more native. You define everything declaratively.
```hcl
# Example Netmaker node definition via Terraform (conceptual)
resource "netmaker_node" "aws_app_server" {
network_name = netmaker_network.main.name
name = "app-01"
public_key = var.wireguard_public_key
endpoint = aws_eip.this.public_ip
local_range = "10.10.10.0/24"
}
```
However, the simplicity and "it just works" factor of Tailscale is non-trivial for smaller teams. The cost of operating the Netmaker control plane (K8s cluster, Postgres, etc.) is a real consideration versus Tailscale's SaaS or a single Headscale binary.
Looking for concrete experiences on:
* Long-term state stability in Netmaker with >50 nodes.
* Real-world ACL management complexity comparison for a multi-team environment.
* Automation workflows for node provisioning/deprovisioning in both systems.
plan before apply
I'm a cloud security lead at a mid-sized fintech (around 300 employees) running a hybrid stack with 60% of our services in AWS EKS and the rest on bare metal in colocation. We've been running a self-hosted Headscale instance for internal access and developer VPN for about 18 months, and I completed a proof-of-concept deployment of Netmaker on a test K8s cluster last quarter to evaluate it as a potential replacement.
1. **Operational State and Drift Control:** The distinction in state management is the deciding factor for platform teams. Netmaker, when deployed via its Kubernetes operator, stores all network definitions - hosts, ACLs, DNS settings - as Custom Resource Definitions in your cluster. This means `kubectl diff` and your GitOps workflow (Flux in our case) become your source of truth and change audit. Tailscale/Headscale relies on the coordination server's internal state; you query it via `headscale nodes list` or the API, but reconciling intended vs. actual state requires custom scripting. In our POC, rolling back a Netmaker network policy was a `kubectl apply` of a previous commit, whereas auditing a Tailscale ACL change meant checking our ephemeral Terraform run logs.
2. **Throughput and Latency Profile:** For basic SSH and HTTP traffic to internal tools, both perform identically in my testing. However, for sustained data transfer, the kernel-space WireGuard implementation in Netmaker shows measurable gains. In a controlled test copying a 10GB file between two EC2 instances in different regions, the Netmaker tunnel sustained about 1.2 Gbps, while Tailscale's userspace WireGuard implementation capped around 650-700 Mbps. The trade-off is that Netmaker's kernel module requirement needs host-level configuration (DKMS), which isn't feasible in some locked-down environments.
3. **Secret and Authentication Integration Burden:** Both require managing a private key for the coordination server. The operational burden comes from node authentication. Tailscale's magic is its SSO integration; we push a Groupe Policy to developer machines that auto-joins them to our Headscale instance via OIDC. For Netmaker, each node (virtual or physical) needs its access key injected via environment variable, cloud-init, or a separate secret manager. This added approximately 40 hours of engineering time in our POC to adapt our existing provisioning pipelines for non-Kubernetes hosts.
4. **True Cost for 250+ Users:** Tailscale's free tier is generous for small teams, but their paid plan starts at $4.80/user/month (billed annually) for the features we needed like SSO and device groups. Our self-hosted Headscale costs are just the compute for a `t3.small` instance (~$15/month) and engineering time for upkeep. Netmaker's core is Apache-licensed and free; their commercial license for the enterprise features (like the UI and single sign-on) starts at $10/user/month for the first 100 users. The hidden cost for Netmaker is the operational overhead of the control plane - it's a stateful application requiring Postgres and Redis, which for high availability meant an additional $180/month for managed databases in our design.
My pick is Headscale for organizations already using Tailscale's managed service and wanting to bring it in-house without retraining staff or rewriting ACLs. For a true greenfield project where the team is Kubernetes-native and has the bandwidth to manage the underlying database and host provisioning, Netmaker provides superior network definition as code. To make a clean call, tell us if your team has more experience with Kubernetes operators than WireGuard configuration, and what your tolerance is for managing a stateful control plane database.
Trust but verify
Your point about state reconciliation for Tailscale ACLs is valid. However, that ephemeral Terraform log problem is solvable by treating the Headscale API as a resource to manage, not just provision. We use a dedicated Terraform workspace with state file persistence solely for Headscale objects, coupled with a CI/CD pipeline that enforces a merge-request-and-apply model. This gives us an audit trail and declarative config.
The operational weight shifts from managing drift to managing API compatibility and state migrations, which is a different kind of overhead. Netmaker's CRD approach inherently bundles that state with the cluster's lifecycle, which is elegant if your entire team lives in kubectl. It becomes a harder sell if you have infrastructure teams managing non-K8s assets who aren't fluent in those workflows.
Show me the data
> managing API compatibility and state migrations
That's the real vendor lock-in, isn't it? You're not just adopting their product, you're adopting their API lifecycle. When they decide to sunset v1 for v2, your "dedicated Terraform workspace" becomes a migration project. How's their deprecation policy? That's the overhead they never put on the pricing page.
Check the fine print.
Your point about the ACL semantics is crucial. Tailscale's policy language becomes another domain-specific thing you have to learn and maintain, separate from any existing firewall or network policy tooling you might already use.
The Netmaker approach using Kubernetes NetworkPolicy CRDs means your mesh VPN rules can live alongside your application ingress/egress definitions, and you can use the same tooling (like `kubectl` or `kubeconform`) to validate them. That consistency reduces cognitive load for platform teams.
However, I've found Tailscale's ACL syntax, while proprietary, is far more expressive for complex user/group-based rules across non-Kubernetes endpoints. Netmaker's model forces a Kubernetes-native mindset onto everything, which can feel awkward for legacy servers or IoT devices that are just nodes on the mesh.
Instrument everything.
>State & Drift: Netmaker's Kubernetes CRDs or Terraform resources provide a single source of truth.
That's a good point about the single source of truth, but you have to define what your reliability target is for that source. If your GitOps controller or Terraform state file becomes unavailable, can you still make critical access changes during an incident? Netmaker's model centralizes control.
Tailscale's ephemeral nature means each node has its own cached ACLs and can still connect if the coordination server has an outage, as long as the peering is already established. For us, that operational resilience is a non-negotiable SLO for a core access layer. The trade-off is exactly the drift you mention. You pick which failure mode you want to manage.
SRE: Sleep Randomly Eventually
That emphasis on declarative config is the right starting point, but you're skipping the operational tax you pay for it. Managing Netmaker's CRDs means you're now responsible for the availability and consistency of your Kubernetes control plane as part of your VPN's core service. If etcd has a bad day, your ability to modify network access is frozen.
Tailscale's "opaque" state via API is actually a feature for recovery scenarios. You can still issue imperative API calls or use the CLI from any node if the central management plane is degraded. The trade-off isn't just manual drift detection, it's choosing between preventing config drift and ensuring you can *change* config during an incident.
Your point about secret management is cut off, but that's another layer. Netmaker's operator needs those secrets to reconcile state. If your secret management (like Vault) has an outage, reconciliation fails. Tailscale/Headscale uses ephemeral auth keys; once a node is authorized, it doesn't need continuous secret access to maintain its connections.