Master Tailscale ACLs for Your Enterprise Environment: A Step-by-Step Guide

Hey there! If you’re managing a network for a mid-size company (think 50–500 employees), you’re probably juggling a mix of cloud servers, on-premises systems, and remote teams. Securing all that while keeping access smooth can feel like herding cats. That’s where Tailscale’s Access Control Lists (ACLs) come in. They’re your ticket to a zero-trust network that’s secure, scalable, and surprisingly easy to set up. In this guide, you’ll learn how to use Tailscale ACLs to lock down your enterprise environment, with practical scenarios, a ready to use policy, and tips to avoid common pitfalls. Whether you’re new to Tailscale or leveling up your security game, you’ve got this!



What You’ll Learn

By the end of this guide, you’ll:

  • Understand how Tailscale ACLs work and why they’re perfect for enterprises.
  • Set up a robust ACL policy tailored for a mid-size company.
  • Tackle real-world scenarios like role-based access, device management, and compliance.
  • Avoid common mistakes and customize your policy for scalability.

No prior Tailscale experience? No problem! We’ll break it down step-by-step, using simple language and plenty of examples. Let’s dive in.


Why Tailscale ACLs for Your Enterprise?

Tailscale makes secure networking feel like magic. Its ACLs let you control who can access what in your Tailnet (Tailscale’s virtual private network) with precision. Unlike clunky VPNs that open wide doors, Tailscale’s deny-by-default approach ensures only the right people and devices get through. For a mid-size company, this means:

  • Team-Specific Access: Engineers debug dev servers, ops manage production, and HR stays in their lane.
  • Device Security: Lock down servers and laptops to prevent unauthorized access.
  • Hybrid Flexibility: Connect offices, clouds, and remote workers seamlessly.
  • Compliance Made Easier: Enforce device checks and audit access.

Most features work on the Personal Plus plan, so you won’t need to splurge on Enterprise unless you want fancy logging. Ready to build your ACL policy? Let’s do this!


Step 1: Understand Tailscale ACL Basics

Before you write your ACL policy, let’s cover the core pieces. Think of an ACL as a rulebook for your network. You define who (users or groups) can access what (devices or networks) and how (ports or protocols). Here’s what you’ll work with:

  • Groups: Bundle users by role (e.g., group:eng for engineers).
  • Tags: Label devices (e.g., tag:prod for production servers).
  • Hosts: Give IPs friendly names (e.g., frontend for 100.100.100.10).
  • IP Sets: Group network ranges (e.g., internal-nets for private subnets).
  • ACL Rules: Specify allowed connections (e.g., ops to production on port 22).
  • SSH Rules: Control remote access with full or audited sessions.
  • Advanced Features: Enforce device compliance, approve new nodes, or use custom relays.

Your policy lives in a policy.hujson file (HUJSON is JSON with comments) in the Tailscale admin console. Don’t worry—it’s easier than it sounds! We’ll build a policy step-by-step.


Step 2: Build Your Enterprise ACL Policy

Let’s create a starter ACL policy for a mid-size company with 200 employees, multiple teams (engineering, ops, HR), and a hybrid setup (office, AWS, Azure). This policy covers common needs and scales as you grow. You’ll copy it into the Tailscale admin console, tweak it for your setup, and test it.

Here’s the policy, with comments explaining each part:

// Tailscale ACL Starter Template for Mid-Size Enterprises
// - Copy this into your Tailscale admin console (Settings > Access Controls).
// - Replace emails, IPs, CIDRs, and tags with your own.
// - Uncomment advanced features (e.g., postures, tailnetLock) as needed.
// - Test with `tailscale acl test` or the admin console preview.
// - All traffic is denied by default unless explicitly allowed.
// - For access logs, check the admin console. Need SIEM? Explore Enterprise: https://tailscale.com/enterprise
// Docs: https://tailscale.com/kb/1018/acls/, https://tailscale.com/kb/1337/acl-syntax/

{
  // 1. Groups: Define user groups for role-based access control (RBAC).
  // Replace example emails with your team’s actual emails.
  "groups": {
    "group:eng": ["[email protected]", "[email protected]"],  // Engineering team
    "group:ops": ["[email protected]"],                        // Operations team
    "group:hr": ["[email protected]"],                         // HR team
    // Add more teams as needed (uncomment and customize).
    // "group:finance": ["[email protected]"]
  },

  // 2. Tag Owners: Specify who can apply tags to devices via `--advertise-tags`.
  // Tags categorize devices (e.g., prod, dev) for access rules.
  "tagOwners": {
    "tag:prod": ["group:ops"],           // Only ops can tag production devices
    "tag:dev": ["group:eng"],            // Engineers tag dev devices
    "tag:db": ["group:ops"],             // Ops tag database servers
    "tag:web": ["group:eng"]             // Engineers tag web servers
  },

  // 3. Hosts: Declare convenient hostname aliases to use in place of IP addresses.
  // Use Tailscale CGNAT IPs (100.64.0.0/10) or your private IPs/CIDRs.
  "hosts": {
    "frontend": "100.100.100.10",       // Web frontend server
    "backend": "100.100.100.20",        // Application server
    "db-net": "10.0.0.0/24",            // Internal database subnet
    "office-server": "192.168.1.10",    // On-premises office server
    "aws-vpc": "172.16.0.0/16",         // AWS cloud VPC
    "dns-server": "100.100.100.30"      // DNS server
  },

  // 4. IP Sets: Group multiple CIDR blocks for easier ACL rules.
  // Useful for private or cloud networks.
  "ipSets": {
    "internal-nets": ["10.0.0.0/24", "10.1.0.0/24"], // Private subnets
    // Add cloud VPCs or other subnets (uncomment as needed).
    // "cloud-vpcs": ["172.16.0.0/16", "192.168.0.0/16"]
  },

  // 5. ACLs: Network-layer access rules. Only allow what’s explicitly defined.
  "acls": [
    // Allow ops to SSH and HTTPS into production devices.
    {
      "action": "accept",
      "src": ["group:ops"],
      "dst": ["tag:prod:22", "tag:prod:443"],
      "proto": "tcp"
    },
    // Allow engineers to access web frontends.
    {
      "action": "accept",
      "src": ["group:eng"],
      "dst": ["frontend:80", "frontend:443"],
      "proto": "tcp"
    },
    // Allow HR to access their system via RDP.
    {
      "action": "accept",
      "src": ["group:hr"],
      "dst": ["office-server:3389"],
      "proto": "tcp"
    },
    // Allow web servers to reach databases on PostgreSQL.
    {
      "action": "accept",
      "src": ["tag:web"],
      "dst": ["db-net:5432"],
      "proto": "tcp"
    },
    // Allow internal networks to reach backend on HTTP.
    {
      "action": "accept",
      "src": ["ipSet:internal-nets"],
      "dst": ["backend:80"],
      "proto": "tcp"
    },
    // Allow limited self-to-self access (SSH, RDP) for all users.
    {
      "action": "accept",
      "src": ["autogroup:member"],
      "dst": ["autogroup:self:22", "autogroup:self:3389"],
      "proto": "tcp"
    },
    // Example UDP rule for DNS (uncomment if needed).
    // {
    //   "action": "accept",
    //   "src": ["group:ops"],
    //   "dst": ["dns-server:53"],
    //   "proto": "udp"
    // }
  ],

  // 6. SSH Rules: Control Tailscale SSH access.
  // Available for all plans: https://tailscale.com/kb/1193/tailscale-ssh
  "ssh": [
    // Full SSH access for ops to production.
    {
      "action": "accept",
      "src": ["group:ops"],
      "dst": ["tag:prod"],
      "users": ["*"]  // All local users on destination
    },
    // Audited SSH for engineers to dev devices.
    {
      "action": "check",
      "src": ["group:eng"],
      "dst": ["tag:dev"],
      "users": ["*"]  // Replace with specific usernames if needed
    }
  ],

  // 7. Grants: Application-layer permissions (e.g., container registries).
  // Uncomment for specific services. Available for all plans.
  // "grants": [
  //   {
  //     "src": ["group:eng"],
  //     "dst": ["container-registry:push,pull"]
  //   }
  // ],

  // 8. Auto Approvers: Allow subnet routers or exit nodes.
  // Available for all plans: https://tailscale.com/kb/1019/subnets
  "autoApprovers": {
    "routes": {
      "192.168.1.0/24": ["group:ops"],  // Office subnet
      "172.16.0.0/16": ["group:ops"]    // AWS VPC
    },
    "exitNode": ["autogroup:admin"]      // Admins for exit nodes
  },

  // 9. Node Attributes & Postures: Enforce device compliance.
  // Available for all plans; advanced attributes may need Enterprise.
  // Docs: https://tailscale.com/kb/1288/device-posture
  // "nodeAttrs": [
  //   { "target": ["tag:hr"], "attr": ["os:windows"] }
  // ],
  // "acls": [
  //   { "action": "accept", "src": ["group:hr", "posture:windows"], "dst": ["office-server:3389"] }
  // ],

  // 10. Tailnet Lock: Require node approval (beta, all plans).
  // Test in staging before enabling: https://tailscale.com/kb/1226/tailnet-lock
  // "tailnetLock": {
  //   "enabled": true,
  //   "approvers": ["group:ops"]
  // },

  // 11. Tests: Validate your policy before deployment.
  // Available for all plans: https://tailscale.com/kb/1192/acl-samples
  "tests": [
    {
      "name": "ops-prod-ssh",
      "src": ["group:ops"],
      "dst": ["tag:prod:22"],
      "accept": true
    },
    {
      "name": "eng-frontend-http",
      "src": ["group:eng"],
      "dst": ["frontend:80"],
      "accept": true
    }
  ]
}

How to Use This Policy

  1. Copy the Policy: Paste it into the Tailscale admin console under Settings > Access Controls.
  2. Replace Placeholders:
    • Update emails (e.g., [email protected]) with your team’s actual emails.
    • Swap IPs (e.g., 100.100.100.10) with your Tailscale CGNAT IPs or private addresses.
    • Adjust tags (e.g., tag:prod) to match your device categories.
  3. Test It:
    • Use the admin console’s preview to check for errors.
    • Run tailscale acl test on your local machine to validate.
  4. Deploy and Monitor:
    • Save the policy to apply it.
    • Check the admin console for access logs to ensure everything works as expected.

Pro Tip: If you hit a snag (e.g., someone can’t connect), double-check your email addresses and IP ranges. Typos are sneaky!


Step 3: Solve Real-World Enterprise Scenarios

Now that you have a solid policy, let’s tackle some common enterprise challenges. These scenarios show you how to customize your ACLs for specific needs, with code snippets and tips to keep things secure.

Scenario 1: Restrict Access by Team

Your engineering team needs to debug development servers, ops must manage production, and HR handles internal systems. You want to ensure no one crosses into the wrong territory.

Solution: Use groups and acls to enforce role-based access:

{
  "groups": {
    "group:eng": ["[email protected]"],
    "group:ops": ["[email protected]"],
    "group:hr": ["[email protected]"]
  },
  "acls": [
    { "action": "accept", "src": ["group:eng"], "dst": ["tag:dev:22"], "proto": "tcp" },
    { "action": "accept", "src": ["group:ops"], "dst": ["tag:prod:22", "tag:prod:443"], "proto": "tcp" },
    { "action": "accept", "src": ["group:hr"], "dst": ["office-server:3389"], "proto": "tcp" }
  ]
}

What’s Happening?

  • Engineers SSH into development servers (tag:dev).
  • Ops access production servers via SSH and HTTPS.
  • HR connects to their system via RDP (port 3389).
  • Everyone else is blocked by default.

Customization: Add more teams (e.g., group:finance) as your company grows. Check Manage ACLs for more examples.

Gotcha: Ensure emails match exactly what’s in Tailscale’s user list, or access will fail.

Scenario 2: Secure Device Access

Your production servers and databases should only be accessed by authorized devices, not random laptops.

Solution: Use tags and tagOwners:

{
  "tagOwners": {
    "tag:prod": ["group:ops"],
    "tag:db": ["group:ops"]
  },
  "acls": [
    { "action": "accept", "src": ["group:ops"], "dst": ["tag:prod:443", "tag:db:5432"], "proto": "tcp" }
  ]
}

What’s Happening?

  • Only ops can tag devices as tag:prod or tag:db.
  • Ops access production servers (HTTPS) and databases (PostgreSQL).
  • Untagged devices can’t connect.

Customization: Add tags for other device types (e.g., tag:staging). See ACL Syntax for details.

Gotcha: Apply tags correctly using –advertise-tags when setting up devices, or they won’t match the rules.

Scenario 3: Connect Hybrid Infrastructure

Your company has an office in Chicago, an AWS VPC, and remote workers. You need seamless connectivity without exposing everything.

Solution: Use hosts, ipSets, and autoApprovers:

{
  "hosts": {
    "office-server": "192.168.1.10",
    "aws-vpc": "172.16.0.0/16"
  },
  "ipSets": {
    "internal-nets": ["192.168.1.0/24", "10.0.0.0/24"]
  },
  "acls": [
    { "action": "accept", "src": ["group:ops"], "dst": ["office-server:22", "aws-vpc:443"], "proto": "tcp" },
    { "action": "accept", "src": ["group:eng"], "dst": ["ipSet:internal-nets:22"], "proto": "tcp" }
  ],
  "autoApprovers": {
    "routes": {
      "192.168.1.0/24": ["group:ops"]
    }
  }
}

What’s Happening?

  • Ops access the office server and AWS VPC.
  • Engineers connect to internal networks for debugging.
  • A subnet router auto-approves the office subnet.

Customization: Add more VPCs to ipSets for Azure or GCP. Check Subnet Routers for setup steps.

Gotcha: Ensure subnet routers are configured with –advertise-routes to expose the right networks.

Scenario 4: Control SSH Access

Your ops team needs full SSH access to production, but engineers should only debug with audited sessions.

Solution: Use ssh rules:

{
  "ssh": [
    { "action": "accept", "src": ["group:ops"], "dst": ["tag:prod"], "users": ["root"] },
    { "action": "check", "src": ["group:eng"], "dst": ["tag:dev"], "users": ["ubuntu"] }
  ]
}

What’s Happening?

  • Ops get full SSH access to production as root.
  • Engineers use check mode for audited, session-recorded access to dev servers.
  • Audits appear in the admin console logs.

Customization: Replace users with specific usernames for tighter control. See Tailscale SSH.

Gotcha: check mode requires Tailscale SSH to be enabled on devices.

Scenario 5: Ensure Device Compliance

You need to ensure only Windows devices with specific attributes access HR systems for compliance (e.g., SOC 2).

Solution: Use nodeAttrs and postures:

{
  "nodeAttrs": [
    { "target": ["tag:hr"], "attr": ["os:windows"] }
  ],
  "acls": [
    { "action": "accept", "src": ["group:hr", "posture:windows"], "dst": ["office-server:3389"], "proto": "tcp" }
  ]
}

What’s Happening?

  • HR devices tagged tag:hr must run Windows.
  • Only compliant devices access the HR system via RDP.
  • Non-Windows devices are blocked.

Customization: Add custom attributes (e.g., security agent presence) with Enterprise integrations. Check Device Posture Management.

Gotcha: Test posture rules carefully, as misconfigured attributes can lock out users.

Scenario 6: Approve New Devices

You want to prevent rogue devices from joining your Tailnet without approval.

Solution: Enable tailnetLock:

{
  "tailnetLock": {
    "enabled": true,
    "approvers": ["group:ops"]
  }
}

What’s Happening?

  • New devices require ops approval before joining.
  • Approval requests appear in the admin console.

Customization: Test in a staging Tailnet first, as it’s in beta. See Tailnet Lock.

Gotcha: Ensure approvers are active, or new devices will be stuck pending.


Step 4: Avoid Common Pitfalls

Don’t let these trip you up! Here are mistakes I’ve seen (and made) when setting up Tailscale ACLs:

  • Typo Trouble: Mismatched emails or IPs (e.g., [email protected] vs. [email protected]) block access. Double-check your groups and hosts.
  • Permissive Rules: The autogroup:self:* rule is handy but risky—it allows all ports. Stick to specific ports like 22 or 3389, as in the policy above.
  • Untested Policies: Always preview in the admin console or run tailscale acl test. A small syntax error can lock everyone out.
  • Beta Risks: Tailnet Lock is in beta, so test it in a non-production Tailnet to avoid surprises.
  • Logging Gaps: The admin console shows basic logs, but for SOC 2 or GDPR, you’ll need Enterprise for SIEM integration.

Quick Fix: If something breaks, roll back to a previous policy version in the admin console and check the logs for clues.


Step 5: Scale and Extend Your Setup

Your company’s growing—congrats! Here’s how to keep your ACLs ready for the future:

  • Add Teams: Expand groups for new departments (e.g., group:marketing).
  • Support More Clouds: Update ipSets for additional VPCs or subnets.
  • Enhance Compliance: Uncomment nodeAttrs for stricter device checks, or upgrade to Enterprise for advanced integrations.
  • Monitor Access: Use the admin console logs or Enterprise SIEM for real-time auditing.
  • Experiment: Try exit nodes for secure internet access or custom DERP servers for low-latency connections (DERP Servers).

Want to play around? Duplicate your Tailnet in a test environment and tweak rules to see what works best.


Why This Works for Your Enterprise

This ACL policy is a game-changer for mid-size enterprises because it:

  • Secures Everything: Deny-by-default and role-based rules keep your network tight.
  • Scales Easily: Handles offices, clouds, and remote workers without breaking a sweat.
  • Saves Money: Most features are on Personal Plus, with Enterprise for advanced needs.
  • Simplifies Compliance: Postures and Tailnet Lock help meet SOC 2 or GDPR requirements.

For a 200-employee company with hybrid infrastructure, this policy is a solid foundation. It’s flexible enough to grow with you, whether you’re adding teams or tightening security.


Wrapping Up

You’re now equipped to lock down your enterprise network with Tailscale ACLs! You’ve got a ready-to-use policy, solutions for common scenarios, and tips to avoid headaches. Start by copying the policy, tweaking it for your setup, and testing it thoroughly. As your company evolves, keep experimenting with advanced features like postures or Tailnet Lock to stay ahead.

Need more help? Check out Tailscale’s awesome docs (ACL Syntax, Enterprise Features). You’re on your way to a secure, zero-trust network—nice work!

What’s Next? Try adding a new team to your policy or setting up a subnet router. Share your setup in the comments or let me know what else you want to explore!

Share your love
Himanshu Mahajan
Himanshu Mahajan
Articles: 38

Leave a Reply

Your email address will not be published. Required fields are marked *