Enterprise Solutions · Architecture

Enterprise Tailscale + Ansible Multi-Site Management Solution

Defines a governed Tailscale and Ansible architecture for secure subnet-routed management of Linux and Windows systems across four Internet-distributed sites.

Document class: Enterprise architecture solution Applicability: Secure, subnet-routed Ansible management across four Internet-distributed sites with Linux and Windows targets.

Purpose

Use a single organization-owned Tailscale tailnet as the encrypted connectivity and identity layer, with Linux subnet routers at Sites A–D and a directly enrolled Ansible control node at Site B.

The recommended production pattern is:

  • Site A: two Linux subnet routers where possible; the available Linux VM is the minimum viable router and is an explicit single point of failure until a second router is added.
  • Site B: two dedicated Linux subnet routers plus a separate Ansible control node. Do not make the Ansible controller the only routing gateway.
  • Sites C and D: the Linux workstation can be the lab router and managed endpoint; production should add a small second Linux appliance or VM if the office requires router failover.
  • Tailscale advertises only the four site LAN prefixes; no default route or Internet exit-node behavior is part of this design.
  • The Ansible controller connects directly to Tailscale and accepts the four subnet routes. It uses SSH for Linux and WinRM/PSRP for Windows.
  • Site-to-site traffic uses least-privilege Tailscale Grants, route approval, local host firewalls, and site-gateway routing where source preservation is required.

Tailscale subnet routing is an overlay route-advertisement model, not a replacement for LAN firewall policy or host authorization. A route must be advertised and approved, and an access policy must also permit the traffic. The route and the policy are separate controls.

Context and decision drivers

Supplied site model

SiteRoleLAN subnetSupplied systemsMinimum routing role
Site AEnterprise site192.168.0.0/2410 Windows PCs, 2 AD servers, possible 1 Linux VMLinux VM as subnet router; add a second Linux router for production HA
Site BHome / management site192.168.10.0/245 Windows servers, 5 workstations, 5 Linux servers, 10 VMsTwo Linux subnet routers and one separate Ansible control node
Site CRemote office192.168.30.0/241 Linux workstation and up to 10 mobile nodes/PCs/laptops/tabletsLinux workstation as lab router; add a second router for production HA
Site DRemote office192.168.40.0/241 Linux workstation and up to 10 mobile nodes/PCs/laptops/tabletsLinux workstation as lab router; add a second router for production HA

The address ranges are non-overlapping, which is required for straightforward site-to-site subnet routing. If a real site has a duplicate or overlapping range, renumbering, NAT, or a different segmentation design is required before connecting the sites.

Management requirements

  • The Site B Ansible controller must reach all four site networks.
  • SSH is mandatory for Linux systems and any Windows system intentionally configured for OpenSSH.
  • Windows management must also be supported through WinRM HTTPS or PSRP over WinRM, normally TCP 5986.
  • Common additional services must be explicitly approved rather than opened broadly:
  • HTTPS 443 for administration and APIs;
  • RDP 3389 for restricted operator access, if required;
  • SMB 445 only for defined file-management or backup workflows;
  • DNS 53 only when a management workflow needs it;
  • application-specific ports only for named systems and owners.
  • Mobile nodes and tablets can use Tailscale to reach approved site services, but Ansible can manage them only if they expose a supported SSH, WinRM/PSRP, or application API interface.

Reference architecture

flowchart LR IDP[Enterprise IdP and MFA] --> TS[Tailscale tailnet control plane] subgraph B[Site B - 192.168.10.0/24] ANS[Ansible control node<br/>Tailscale client<br/>accepts routes] B1[Subnet router B-01] B2[Subnet router B-02] BNET[Home LAN<br/>Windows, Linux, VMs] ANS --- BNET B1 --- BNET B2 --- BNET end subgraph A[Site A - 192.168.0.0/24] A1[Subnet router A-01] A2[Optional A-02] AD[AD servers and Windows PCs] A1 --- AD A2 -. HA .- AD end subgraph C[Site C - 192.168.30.0/24] C1[Linux workstation / router] CDEV[Mobile and PC nodes] C1 --- CDEV end subgraph D[Site D - 192.168.40.0/24] D1[Linux workstation / router] DDEV[Mobile and PC nodes] D1 --- DDEV end B1 <-- Tailscale overlay --> TS B2 <-- Tailscale overlay --> TS A1 <-- Tailscale overlay --> TS A2 -. Tailscale overlay .-> TS C1 <-- Tailscale overlay --> TS D1 <-- Tailscale overlay --> TS ANS <-- Direct Tailscale node --> TS

The control plane distributes node identity, route advertisements, and policy. Data traffic normally flows directly between Tailscale nodes where possible; traffic to a non-Tailscale LAN host is forwarded by that site's subnet router.

Address and naming plan

The following addresses are examples for a lab or design workbook. Reserve them in the real DHCP/IPAM system before use.

SiteFunctionExample nameExample LAN address
APrimary subnet routertsr-a-01192.168.0.2
ASecondary subnet routertsr-a-02192.168.0.3
AAD server 1a-ad-01192.168.0.10
AAD server 2a-ad-02192.168.0.11
AWindows PCsa-pc-01 to a-pc-10192.168.0.101 to 192.168.0.110
BPrimary subnet routertsr-b-01192.168.10.2
BSecondary subnet routertsr-b-02192.168.10.3
BAnsible control nodeansible-b-01192.168.10.20
BWindows serversb-win-srv-01 to b-win-srv-05192.168.10.21 to 192.168.10.25
BWorkstationsb-pc-01 to b-pc-05192.168.10.101 to 192.168.10.105
BLinux serversb-linux-01 to b-linux-05192.168.10.41 to 192.168.10.45
BVMsb-vm-01 to b-vm-10192.168.10.61 to 192.168.10.70
CLinux workstation / routertsr-c-01192.168.30.2
CMobile and PC reservationc-node-01 to c-node-10192.168.30.101 to 192.168.30.110
DLinux workstation / routertsr-d-01192.168.40.2
DMobile and PC reservationd-node-01 to d-node-10192.168.40.101 to 192.168.40.110

Use stable hostnames in Ansible inventory and set ansible_host to the LAN address when managing a host behind a subnet router. Use Tailscale MagicDNS names for directly enrolled nodes such as ansible-b-01 and the subnet routers themselves.

Routing model

Advertised routes

Router tagAdvertised routeSite
tag:subnet-router-a192.168.0.0/24A
tag:subnet-router-b192.168.10.0/24B
tag:subnet-router-c192.168.30.0/24C
tag:subnet-router-d192.168.40.0/24D

For HA, the two routers at one site must advertise the exact same prefix. Tailscale failover does not promote a broader prefix when a more-specific route fails, and there is no administrator-selected preferred router in the standard failover model. The route must be approved either manually in the admin console or through an autoApprovers policy.

Do not advertise 0.0.0.0/0 for this use case. An exit node is a different function from a site subnet router and would create a much larger security and troubleshooting scope.

SNAT choices

ModeAdvantagesTrade-offUse
Default subnet-route SNATRequires fewer changes to existing LAN gateways; good for the first labRemote hosts see the local subnet router as the source; site-to-site return-path and audit detail are less explicitLab fast path and environments where gateways cannot add static routes
No SNAT with static routesPreserves the originating Tailscale/LAN source address and supports clearer site-to-site routing and loggingRequires static routes on site gateways and carefully designed firewall rulesEnterprise baseline when gateway control is available

The no-SNAT design requires every participating LAN gateway to know how to return traffic to the relevant remote prefixes through its local subnet router. If that cannot be implemented safely, retain SNAT and limit access to directly enrolled Tailscale clients or to explicitly routed management sources.

Site B access

The preferred path is to install Tailscale directly on the home PC and the Ansible controller, then enable route acceptance on the Linux controller. This avoids making every home device depend on a single LAN gateway for remote access.

If the entire Site B LAN must access Sites A, C, and D, add routes on the Site B gateway pointing the remote prefixes to the Site B subnet router. For a no-SNAT design, add corresponding return routes on Sites A, C, and D. Validate whether the gateway supports redundant next hops before claiming router HA for non-Tailscale LAN clients.

Tailscale control-plane design

Identity and device enrollment

  • Use the enterprise identity provider with MFA for human tailnet access.
  • Use role-based groups such as group:netops and group:ansible-operators.
  • Use tags for non-human devices; tag ownership must be limited to the network/security administration group.
  • Use pre-approved, tagged auth keys for servers when device approval is enabled. Keep keys in a secret manager or CI secret store and never commit them.
  • Use separate auth keys per site and purpose so a compromised enrollment secret has a bounded scope.
  • Review node-key expiry, auth-key expiry, reauthentication, and offboarding procedures. Tagged devices have different key-expiry behavior, so document the selected policy rather than relying on defaults.
  • Consider Tailnet Lock, posture checks, and policy-as-code review when the tailnet and operating model support them.

Illustrative Grants policy

The following is a starting example, not a drop-in production policy. Replace the example identity, validate the current Grants syntax in the Tailscale policy editor, and test from both a permitted and denied source.

{
  "groups": {
    "group:netops": ["netops@example.com"],
    "group:ansible-operators": ["automation@example.com"]
  },
  "tagOwners": {
    "tag:subnet-router-a": ["group:netops"],
    "tag:subnet-router-b": ["group:netops"],
    "tag:subnet-router-c": ["group:netops"],
    "tag:subnet-router-d": ["group:netops"],
    "tag:ansible-control": ["group:netops"],
    "tag:linux-managed": ["group:netops"]
  },
  "autoApprovers": {
    "routes": {
      "192.168.0.0/24": ["tag:subnet-router-a"],
      "192.168.10.0/24": ["tag:subnet-router-b"],
      "192.168.30.0/24": ["tag:subnet-router-c"],
      "192.168.40.0/24": ["tag:subnet-router-d"]
    }
  },
  "grants": [
    {
      "src": ["tag:ansible-control", "192.168.10.0/24"],
      "dst": ["192.168.0.0/24"],
      "ip": ["icmp:*", "tcp:22", "tcp:443", "tcp:5986"],
      "via": ["tag:subnet-router-a"]
    },
    {
      "src": ["tag:ansible-control", "192.168.10.0/24"],
      "dst": ["192.168.30.0/24"],
      "ip": ["icmp:*", "tcp:22", "tcp:443", "tcp:5986"],
      "via": ["tag:subnet-router-c"]
    },
    {
      "src": ["tag:ansible-control", "192.168.10.0/24"],
      "dst": ["192.168.40.0/24"],
      "ip": ["icmp:*", "tcp:22", "tcp:443", "tcp:5986"],
      "via": ["tag:subnet-router-d"]
    },
    {
      "src": ["group:ansible-operators"],
      "dst": ["tag:subnet-router-a", "tag:subnet-router-b", "tag:subnet-router-c", "tag:subnet-router-d"],
      "ip": ["tcp:22", "tcp:443"]
    }
  ],
  "ssh": [
    {
      "action": "check",
      "src": ["group:ansible-operators"],
      "dst": ["tag:linux-managed"],
      "users": ["autogroup:nonroot"],
      "checkPeriod": "12h"
    }
  ]
}

The network Grants allow routed IP access; they do not configure an operating-system SSH daemon or create Windows accounts. The ssh policy applies only to Tailscale SSH on directly enrolled Linux/macOS devices. It does not provide SSH to a host that is merely behind a subnet router.

Tailscale SSH versus standard SSH

Use standard SSH over the Tailscale network for Ansible Linux management by default. This keeps the inventory and key-management model familiar and works for Linux hosts reached through a subnet route. Tailscale SSH is a useful operator access option for Linux nodes that run Tailscale directly, but it is not a replacement for standard SSH on every routed host.

Tailscale SSH is not the Windows management protocol and cannot reach devices behind a subnet router unless the destination itself runs Tailscale SSH. Windows systems should use WinRM/PSRP or Windows OpenSSH according to the approved host standard.

Ansible management architecture

Control node

ansible-b-01 is a Linux control node on Site B with:

  • a direct Tailscale client and --accept-routes enabled;
  • an SSH key held by ssh-agent or a protected key store;
  • Ansible Vault for passwords, WinRM certificates, API tokens, and other secrets;
  • a Git repository containing inventory, group variables, roles, playbooks, tests, and change history;
  • local logs and a backup of the configuration repository;
  • a documented recovery procedure or a secondary control node.

Do not place the only Ansible controller and the only Site B subnet router on the same VM for production. A failure of that VM would remove both automation and routed access.

Ansible connection standards

TargetRecommended connectionTypical portCredential/control
Linux servers, Linux VMs, and Linux subnet routersOpenSSH22Per-purpose ansible account, SSH key, least-privilege sudo
Windows servers, AD servers, and Windows PCsWinRM HTTPS or PSRP over WinRM5986Domain/Kerberos where appropriate, or local account/certificate over trusted HTTPS
Windows lab-only rapid pathWinRM with NTLM and message encryption over Tailscale5985Lab credential in Vault; never expose the listener to the public Internet
Directly enrolled Linux operator nodesStandard SSH or Tailscale SSH22Standard SSH keys or tailnet identity policy
Mobile/tablet clientsNot an Ansible target by defaultVariesTailscale access only unless a supported management API exists

Ansible inventory should use group variables for connection behavior and host variables for the routed LAN address. Use FQCNs such as ansible.builtin.ssh, ansible.builtin.winrm, ansible.windows.win_ping, and ansible.builtin.ping in playbooks and documentation.

Service access policy

ServiceSourceDestinationDecision
SSH TCP 22Ansible control, approved netops devicesLinux targets and subnet routersRequired
WinRM HTTPS TCP 5986Ansible controlWindows targetsRequired for Windows automation
WinRM HTTP TCP 5985Lab control onlyLab Windows targetsTemporary lab exception only; use message encryption and remove after the lab
HTTPS TCP 443Ansible control and approved operatorsAdmin portals/APIsRequired only for named services
RDP TCP 3389Approved operator groupNamed Windows targetsOptional, restricted, audited
SMB TCP 445Approved backup/file-management jobNamed file serversOptional, never broad tailnet access
DNS TCP/UDP 53Approved DNS clientsApproved DNS serversOptional; prefer known DNS resolvers and IP inventory where practical

Do not grant *:* from the Ansible controller to all four LANs as the production default. Add an application-specific rule with an owner, purpose, expiration/review date, and validation test.

Security, resilience, and cost

The principal cost drivers are the Tailscale subscription tier, Linux subnet-router hosts, optional redundant router and WAN capacity, Ansible controller hosting, backup and monitoring, and engineering time for policy, firewall, and recovery testing. The design should be costed against the required RTO rather than assuming every site needs identical hardware.

ComponentFailure impactEnterprise treatment
Tailscale control planeNew policy, route distribution, or new-node enrollment may be affected; established paths have different continuity characteristicsProtect the tailnet administrator accounts, recovery methods, policy backups, and vendor escalation path
Site A Linux VM routerSite A is unreachable through the overlayAdd tsr-a-02 on a separate host, power path, and preferably separate virtualization or hardware boundary
Site B router pairSite B LAN routing can fail or become asymmetricUse two routers with the same route; keep Ansible control separate; test router failure and return paths
Site B Ansible controllerAutomation stops, but Tailscale routes can remain availableMaintain a backed-up repository and a secondary controller or rebuild procedure
Site C/D Linux workstation routerEach small office becomes unreachable through the overlayAdd a second always-on Linux router/appliance if RTO requires it; do not claim HA with one workstation
Site ISP or powerLocal users may lose cloud access and the subnet router may disappearUPS, configuration backups, spare equipment, and optional secondary WAN/5G based on approved RTO
Host firewall or gateway routesServices may be unreachable despite a healthy Tailscale routeManage local firewall and static-route configuration as code where possible

When overlapping subnet routers advertise the exact same prefix, Tailscale can fail over between them. The documented failover behavior can take approximately 15 seconds, and broader or differently sized prefixes are not equivalent failover candidates. If a site has only one Linux router, record that as an accepted SPOF until the second router is installed and tested.

For HA routers advertising the same local prefix, avoid enabling route acceptance on the standby unless the design specifically needs that behavior; otherwise the standby can route traffic for its own directly connected LAN through the other router. Test --accept-routes behavior deliberately rather than copying the setting to every router.

Operational considerations

Secrets and privileged access

  • Store Tailscale auth keys, SSH private keys, WinRM passwords, certificates, and API credentials outside Git.
  • Use short-lived or scoped enrollment keys where the device lifecycle permits it.
  • Use unique local automation accounts per operating-system class and site, or centrally governed identities where available.
  • Use sudo rules that permit only the required Ansible roles; do not make every playbook an unrestricted root workflow.
  • Use Windows local/domain accounts with only the permissions required by the playbook. Protect WinRM listener certificates and CA trust chains.
  • Require MFA and periodic reauthentication for human operator access; do not use a shared Tailscale user.

Monitoring and evidence

Monitor and retain:

  • subnet-router health, route advertisements, route approval, and route changes;
  • Tailscale node authorization, tag changes, key events, and policy changes;
  • Ansible job identity, inventory revision, playbook revision, result, and failure reason;
  • SSH, WinRM, RDP, SMB, and application firewall events on managed hosts;
  • connectivity latency and packet loss from Site B to each site;
  • backup and restore tests for the Ansible repository, policy export, router configuration, and critical service data.

Change control

Route advertisements, Grants, subnet-router firewall rules, static gateway routes, WinRM listeners, and Ansible privileged tasks are production changes. Every change should record the request, owner, affected sites, exact prefixes/ports, rollback action, validation result, and next review date.

Implementation roadmap

  1. Confirm IPAM, gateway ownership, non-overlap, DNS behavior, and the real inventory at Sites A–D.
  2. Create the tailnet, identity integration, MFA, administrator groups, device-approval model, tag ownership, and recovery procedures.
  3. Build one isolated lab route per site and validate the policy with both allowed and denied tests.
  4. Deploy the Site B Ansible controller and bootstrap Linux SSH and Windows WinRM/PSRP credentials using Vault.
  5. Enroll Site A, then Site C and D, then the remaining Site B nodes. Start with one representative Linux and Windows host per site.
  6. Approve only the exact four site prefixes and validate route acceptance on the controller and home PC.
  7. Add service-specific Grants and host-firewall rules; do not broaden access because a single test failed.
  8. Add the second subnet router at each site where the availability target requires it, then test exact-prefix failover.
  9. Automate configuration drift checks, patching, inventory collection, backup verification, and recovery testing.
  10. Sign off the acceptance matrix before treating the design as production-ready.

Validation

TestExpected result
Ansible controller sees all four advertised routesip route or equivalent shows the four approved prefixes
Controller reaches each subnet routerTailscale IP and LAN IP tests succeed
Controller reaches Linux targetsSSH succeeds on TCP 22 using the approved key and account
Controller reaches Windows targetsWinRM/PSRP succeeds on TCP 5986 with certificate validation and Vault credentials
Home PC reaches Site A/C/D approved servicesOnly explicitly permitted ports succeed
Unauthorized tailnet user or tag reaches a protected serviceConnection is denied by Tailscale policy or the host firewall
Site gateway return pathNo-SNAT traffic returns through the correct local subnet router
Subnet-router failureExact-prefix route fails over to the second router where HA is deployed
New-device recoveryA rebuilt router or controller can be enrolled without a shared permanent secret
Ansible idempotencyThe same playbook run produces no unexpected changes on the second run
Audit and rollbackPolicy, route, firewall, and playbook changes have evidence and a tested rollback

Scope boundaries

  • Tailscale does not remove the need for local Windows firewalls, Linux firewalls, gateway ACLs, operating-system accounts, or application authorization.
  • Subnet routing does not make a mobile phone or tablet an Ansible-managed node.
  • Tailscale SSH is not a universal SSH gateway for hosts behind subnet routers.
  • Ansible is agentless; it still requires a supported connection protocol and sufficient host permissions.
  • AD servers can be managed through WinRM/PSRP, but normal AD DS protocols and DNS dependencies remain application concerns and should not be exposed broadly through the tailnet.
  • A single Linux workstation acting as both user endpoint and subnet router is suitable for a lab, not a high-availability production office.

References