ACLs, ABAC, RBAC, and network security policies

Access control lists (ACLs) restrict who can access which nodes on your network. ACLs can be defined in the admin console.


Our Solo and Connectivity plans do not officially support centralized ACLs but you are free to experiment with them during your trial period. You may also find our “Block incoming connections” feature enough for your needs.


Let’s say you have 11 employees in your organization. Five of them are in the accounting department, five are in the engineering department, and then there’s the president.

How can you make it so that engineers can access the engineering servers, accountants can access the accounting servers, and the president can access all of them?

On old-fashioned physical networks, you could try using physical segregation: put the engineering workstations and servers into one subnet, the accounting servers into another subnet, and then use a firewall to stop traffic flowing from one subnet to the other. This complicates things for the president, who wants access to both networks, but that’s okay: perhaps the president can have two computers, one on each network.

That was a relatively common setup before but is harder to do now in the days of Wi-Fi, laptops, multiple offices, and remote workers. A newer method, now in vogue, is to move all your servers into the cloud and then use BeyondCorp-style proxies to restrict which users can access which servers. This works, as long as all your servers are web based, and as long as you want to put them all in the cloud, and as long as you don’t mind running a network of proxy servers that create a network bottleneck between clients and servers.

Tailscale’s security architecture is different. Instead of proxy servers, physical networks, and firewalls, each node can talk directly to each other node, no matter where they are. But to prevent that from becoming a security problem, Tailscale also lets you define security policies - basically, a list of which nodes can access which other nodes. Architecturally, you can think of this as a firewall (packet filter) running on every Tailscale node.

With a traditional firewall, security policies are expressed as a set of packet filtering rules allowing one IP address to talk to another IP address. There’s a rule for Engineer A’s laptop ( to let it talk to Git Server G (, and so on for Engineers B..K. When someone brings up CI Server C (, you file a ticket with the security department to open a firewall rule that lets 10.1.1.x/24 access, and so on.

Tailscale ACLs are similar, but refer to users (and groups) and services, instead of just IP addresses. You can write rules like “everyone in the engineering group should be allowed to access servers tagged as ‘engineering’.” The rules are stored in the central coordination server, and compiled into a set of traditional packet filter rules (“these IP addresses can talk to these other IP addresses”) behind the scenes, then sent to each node for enforcement (also known as access control).

Role-based Access Control (RBAC) and Attribute-based Access Control (ABAC) are variations of the same concept. In RBAC, each user acts in exactly one role at a time (engineering, accounting, IT administrator, etc). In ABAC, each user or server is tagged with a flexible set of attributes that describe their job (employee + engineer + Montreal), and those attributes each grant access to relevant services (employees can access the payroll viewer, engineers can access the Git server, and Montreal users can access the printers in Montreal).

Tailscale allows you to build complex RBAC/ABAC rule sets in a simple way, based on identities pulled in from your identity provider. When you make a change to a user’s group memberships (i.e. roles and attributes) or your ACL policies, the changes are immediately reflected out to all Tailscale nodes to update their enforcement rules. All this typically happens in a few hundred milliseconds.

Tailscale ACL policy format

The Tailscale ACL policy is in a format called “human usable json.” It’s a superset of JSON that additionally allows comments and trailing commas, which makes the files easy to maintain while staying read/writable by both humans and machines.

For simple cases, you can easily edit the policy file yourself. Advanced organizations with complex policies can write automated scripts to generate Tailscale ACL configurations however and whenever they want. This makes it easy to integrate Tailscale ACLs with virtually any existing authorization system you might already use.

There are several main sections in the ACL file. Let’s go through them one by one.


// Declare static groups of users beyond those in the identity service.
"Groups": {
    "group:example": [

The Groups section lets you define groups of users (in RBAC, these are called “roles”). A user can be in more than one group. Every group name must start with the prefix group:.

For explicitness, you must include the full email address of each user. However, Tailscale currently only lets you share your nodes with users inside the same domain as you. If you write an ACL that permits users outside your domain, it will be silently ignored. Eventually, we will allow inviting users outside your domain.

We suggest putting a comma at the end of each line, even though this is not allowed in regular JSON format. That makes it easier to cut, paste, and rearrange rows without worrying about adding and removing commas.


// Declare convenient hostname aliases to use in place of IP addresses.
"Hosts": {
    "example-host-1": "",
    "example-host-2": "",

Hosts are convenient names that you can use to refer to particular servers when writing ACL rules, so that the ACLs themselves are more human-readable and thus auditable by non-technical users who need to check regulatory compliance.

Right now, a host can only refer to a single IP address, not a subnet. Later, we will extend the ACL policy to allow subnet ACLs.

Some people have asked whether the "Hosts" section can allow lists of hosts, like the Groups section allows lists of users. This is not necessary, because ACL rules (the next section) allow you to create lists of hosts at that level instead. Disallowing host lists in this section makes it easier to audit ACL rules.


// Access control lists.
"ACLs": [
    // Engineering users, plus the president, can access port 22 (ssh)
    // and port 3389 (remote desktop protocol) on all servers, and all
    // ports on development servers.
        "Action": "accept",
        "Users": ["group:engineering", ""],
        "Ports": ["*:22,3389", "git-server:*", "ci-server:*"],

    // Permit absolutely everything (for logged-in users only). Comment
    // out this section if you want to define specific ACL restrictions
    // above.
        "Action": "accept",
        "Users": ["*"],
        "Ports": ["*:*"],

Each entry in the "ACLs" section defines a rule that grants access by a set of users or groups (i.e. roles in RBAC), to a set of servers and ports.

The "Action" field must always be present, but only the value "accept" is allowed. There is no way to explicitly reject connections. Instead, no connections are allowed unless granted by an "accept" rule. Once again, this makes compliance audits much simpler: there is no way to hide a rule inside complex logic.

If you’re a Tailscale domain administrator, you can visit the ACL admin page.


// Declare tests to check functionality of ACL rules
"Tests": [
    {"User": "", "Allow": ["example-host-1:22", "example-host-2:80"], "Deny": ["exapmle-host-2:100"]},
    {"User": "", "Allow": [""]},

ACLs can get large and it may be hard to keep track of what groups, roles, tags, etc, give permissions to what machines. The "Tests" section of your ACL lets you declare tests to ensure updates to your ACL don’t accidentally revoke access to key systems, or expose resources you didn’t intend. If a test fails due to an ACL change, you’ll receive an error.

A test requires a target User (email), and either a list of Allow‘d destinations, Deny‘d destinations, or both. Acceptable items in Allow/Deny lists are specific ports to either a user or IP address as shown above.

Editing ACLs

We provide a simple text editor in the admin console, or you can choose to maintain your ACL elsewhere (e.g. to take advantage of version control systems) and paste it in to save. We also hope to offer an API for editing your ACL in the near future.

The editor also has a diff view to view git-style diffs for your current changes and a “Preview Rules” feature, explained in the next section.

Preview Rules

You can preview what rules will affect a user by selecting a user from the dropdown. A list of ports (one per line) accessible to the specified user is shown, as well the line number that defines that rule. It also includes any other users/groups that can access that port due to that rule.

Last updated