pulumi-tailscale

A Pulumi provider that lets you manage Tailscale devices, ACLs, and DNS settings as infrastructure code across TypeScript, Python, Go, C#, and Java.

SDK
npm
v0.29.0
24stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
71/100Good
Development Activity96
Maintenance96
Community24
Maturity56
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
69/100Good
Architecture78
Code Quality68
Innovation55
Learning Curve75

@pulumi/tailscale is the Node.js SDK for Pulumi’s Tailscale resource provider, generated by bridging the official Terraform provider for Tailscale into the Pulumi ecosystem. It exposes Tailscale’s tailnet configuration surface — ACL/policy files, device tags and subnet routes, DNS nameservers and search paths, OAuth clients, posture integrations, and webhook log streaming — as typed Pulumi resources and data sources that participate in the same declarative up/preview/destroy lifecycle as any other cloud resource in a Pulumi program.

Because it is a thin, auto-generated layer over the Terraform provider (via pulumi-terraform-bridge’s plugin-framework shim), the package inherits the semantics and API surface of terraform-provider-tailscale almost one-to-one, while giving Pulumi users native language bindings instead of HCL. Authentication uses either a static API key or OAuth client credentials scoped to the tailnet being managed.

It’s aimed at teams who already provision cloud infrastructure with Pulumi and want their Tailscale network configuration — device tagging, ACL policy, DNS split-tunneling — version-controlled and applied through the same pipeline, rather than managed by hand in the Tailscale admin console or through a separate Terraform workspace.

What You Get

  • Typed resources for the tailnet policy file (Acl), device attributes (DeviceTags, DeviceKey, DeviceSubnetRoutes, DeviceAuthorization), and DNS configuration (DnsNameservers, DnsSearchPaths, DnsPreferences, DnsSplitNameservers)
  • OAuth client and API-key authentication, configurable via provider config or TAILSCALE_API_KEY/TAILSCALE_TAILNET/OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET environment variables
  • Data sources (getDevice, getDevices, getUser, getUsers, getAcl, getService) for reading existing tailnet state into a Pulumi program
  • Resources for webhook log streaming (LogstreamConfiguration), device posture integrations (PostureIntegration), and federated identity/AWS external ID configuration
  • Generated SDKs across five languages (Node.js/TypeScript, Python, Go, .NET, Java) from a single Terraform-bridge schema, so behavior stays consistent regardless of which language a team uses
  • Import support for adopting existing Tailscale resources (e.g. device tags by node ID) into Pulumi state without recreating them

Common Use Cases

  • Auto-tagging devices with DeviceTags as part of a Pulumi-managed onboarding pipeline, driven by data pulled from getDevice/getDevices
  • Version-controlling a tailnet’s ACL policy file (Acl resource) so policy changes go through the same PR/preview/apply flow as other infrastructure
  • Provisioning split-tunnel DNS (DnsSplitNameservers) or global nameservers (DnsNameservers) for a tailnet alongside the VPCs/networks Pulumi already manages
  • Wiring up OAuth clients and posture integrations for MDM-driven device compliance checks as part of an infrastructure-as-code security baseline
  • Standing up ephemeral/test tailnets in CI by combining this provider with other Pulumi cloud resources in one program

Under The Hood

Architecture The package is one of five generated SDKs (Node.js, Python, Go, .NET, Java) produced from a single Go-based bridge provider in provider/. provider/resources.go instantiates tailscale.NewFrameworkProvider() from github.com/tailscale/terraform-provider-tailscale and wraps it with pulumi-terraform-bridge/v3’s plugin-framework shim (pfbridge.ShimProvider), mapping each Terraform resource/data-source schema into Pulumi tfbridge.ResourceInfo/DataSourceInfo entries with a handful of field-level overrides (e.g. renaming acl to AclJson for C#). pulumi-tfgen-tailscale consumes this mapping to emit a schema.json, which the per-language code generators (invoked transitively via pulumi-resource-tailscale) turn into the hand-off-limits, auto-generated .ts/.py/.go files under each sdk/<lang>/ directory — every resource file in sdk/nodejs/ opens with an explicit “do not edit by hand” warning. Changing this package’s actual behavior means changing the upstream Terraform provider or the bridge mapping, not the generated TypeScript directly.

Tech Stack The bridge provider is Go (module github.com/pulumi/pulumi-tailscale/provider, go.mod pinned to a recent toolchain), depending on pulumi-terraform-bridge/v3 v3.139.0 and tailscale/terraform-provider-tailscale v0.29.2, with a local replace directive pointing terraform-plugin-sdk/v2 at Pulumi’s own fork. The Node.js SDK itself has a minimal runtime footprint — its only dependency is @pulumi/pulumi (^3.142.0) — with TypeScript ^4.7 and @types/node as dev-only build dependencies; tsc is the entire build step. The repo also builds Python (setuptools), Go, .NET, and Java SDKs from the same schema, and uses devbox/mise for reproducible local toolchain pinning.

Code Quality Testing lives in the Go provider layer rather than the generated SDKs (which, being generated, aren’t unit-tested themselves): provider/provider_program_test.go runs example Pulumi programs (test-programs/index_dnssearchpaths, index_dnsnameservers) through up/preview cycles using Pulumi’s providertest/pulumitest harness, and separately checks provider-version upgrade compatibility by diffing preview output against a pinned baseline version for unwanted resource replacements. examples/examples_test.go and per-language variants (examples_nodejs_test.go, examples_py_test.go) exercise the example programs (examples/dns-ts, examples/py-tailnet-key) end-to-end. CI (.github/workflows/test.yml, run-acceptance-tests.yml) runs these against real or recorded Tailscale API interactions. There is no traditional unit-test suite for business logic — quality is enforced via generated-schema correctness and full-program acceptance tests instead.

API Design Because the API surface is generated from Terraform’s schema, naming and shape follow Terraform’s resource/data-source conventions translated into idiomatic Pulumi classes (DeviceTags, DnsSearchPaths, getDevice) rather than a hand-designed SDK — this gives strong consistency across the five language SDKs at the cost of some naming quirks inherited from the upstream provider (e.g. the Acl resource actually controlling the entire tailnet policy file, noted explicitly in its own doc comment). Every generated resource carries an inline example (## Example Usage) and import instructions in its TSDoc, so onboarding for a user already familiar with Pulumi is close to zero — the main learning curve is understanding Tailscale’s own ACL/policy-file model, not the SDK’s shape.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search