From c226353f304296a90cedae55860bf351d9b73641 Mon Sep 17 00:00:00 2001 From: Joshua Gilman Date: Mon, 14 Sep 2026 23:15:40 -0700 Subject: [PATCH 1/2] feat(tailscale): reserve the Mac backend's SSH port for the agentcompute server The Mac Studio is the Phase 8 macOS backend. Its SSH port is the server's only channel to Lume, so no other tailnet node should be able to open it. ACL rules are allow-only, so the blanket admin rule is replaced by the same reach written out, with tag:macbackend:22 and the routed 192.168.1.15:22 carved out. Tagging the host is what makes that expressible: a user-owned device is reachable through autogroup:self, which cannot be narrowed per device. Applying this needs the device tagged first, otherwise tag:macbackend matches nothing and the carve-out is inert while the admin rule is already narrowed. --- tailscale/policy.hujson | 73 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/tailscale/policy.hujson b/tailscale/policy.hujson index ffe31b6..94754df 100644 --- a/tailscale/policy.hujson +++ b/tailscale/policy.hujson @@ -16,6 +16,14 @@ "tagOwners": { "tag:subnet-router": ["autogroup:admin"], "tag:sandbox": ["autogroup:admin", "tag:subnet-router"], + // The Mac Studio hosting the agentcompute macOS backend. Tagging it + // takes it out of user ownership, which is what makes an SSH + // restriction on it expressible: `autogroup:self` cannot be narrowed + // per device. + "tag:macbackend": ["autogroup:admin"], + // The agentcompute server VM. It is the only node allowed to open + // tag:macbackend:22. + "tag:agentcompute": ["autogroup:admin"], }, // Routes a subnet router may advertise without manual approval. These are @@ -30,8 +38,49 @@ }, "acls": [ - // Admins reach everything in the tailnet. - {"action": "accept", "src": ["autogroup:admin"], "dst": ["*:*"]}, + // Admins reach everything in the tailnet except the Mac backend's SSH + // port, which is reserved for the agentcompute server below. ACL rules + // are allow-only, so "everything except one port" has to be written + // out: the wildcard destination is replaced by the same reach, + // enumerated. + { + "action": "accept", + "src": ["autogroup:admin"], + "dst": [ + "autogroup:internet:*", + "autogroup:self:*", + "tag:subnet-router:*", + "tag:sandbox:*", + "tag:agentcompute:*", + "tag:macbackend:0-21,23-65535", + "10.10.0.0/16:*", + "172.16.0.0/16:*", + "192.168.2.0/24:*", + // The Mac backend's LAN address (192.168.1.15) is the same + // host reached through the home subnet route, so the same + // carve-out applies there. Every other home address keeps full + // access, including SSH. + "192.168.1.0/24:0-21,23-65535", + "192.168.1.0/29:22", + "192.168.1.8/30:22", + "192.168.1.12/31:22", + "192.168.1.14/32:22", + "192.168.1.16/28:22", + "192.168.1.32/27:22", + "192.168.1.64/26:22", + "192.168.1.128/25:22", + ], + }, + + // The agentcompute server reaches the Mac backend over SSH only. That + // session is itself forced to a single forwarded port by the host's + // sshd configuration and the key's forced command. + { + "action": "accept", + "src": ["tag:agentcompute"], + "proto": "tcp", + "dst": ["tag:macbackend:22"], + }, // Subnet routers reach each other so routed traffic can transit // between them. @@ -75,6 +124,26 @@ "10.10.10.11:8444", ], }, + // Only the agentcompute server may open the Mac backend's SSH port, + // and it may open nothing else there. + { + "src": "tag:agentcompute", + "accept": ["tag:macbackend:22"], + "deny": ["tag:macbackend:5900", "tag:macbackend:7777"], + }, + // An admin device keeps every other path to that host, including the + // screen-sharing port and the rest of the home range's SSH, but not + // its SSH port by either name or routed address. + { + "src": "joshuagilman@gmail.com", + "accept": ["tag:macbackend:5900", "192.168.1.20:22", "10.10.10.14:8443"], + "deny": ["tag:macbackend:22", "192.168.1.15:22"], + }, + // A sandbox host still reaches nothing on the Mac backend. + { + "src": "tag:sandbox", + "deny": ["tag:macbackend:22", "tag:macbackend:7777"], + }, ], "ssh": [ From dfb57a4cbd3550b5d7521cefcd992ab1960e18b0 Mon Sep 17 00:00:00 2001 From: Joshua Gilman Date: Tue, 15 Sep 2026 01:07:50 -0700 Subject: [PATCH 2/2] fix(tailscale): carve out the Mac backend's measured LAN addresses The host answers on en0 192.168.1.10 and en1 192.168.1.137, not the 192.168.1.15 the first draft assumed, so the routed-path SSH carve-out covered the wrong address. --- tailscale/policy.hujson | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/tailscale/policy.hujson b/tailscale/policy.hujson index 94754df..594175a 100644 --- a/tailscale/policy.hujson +++ b/tailscale/policy.hujson @@ -56,19 +56,26 @@ "10.10.0.0/16:*", "172.16.0.0/16:*", "192.168.2.0/24:*", - // The Mac backend's LAN address (192.168.1.15) is the same - // host reached through the home subnet route, so the same - // carve-out applies there. Every other home address keeps full - // access, including SSH. + // The Mac backend's own LAN addresses are the same sshd reached + // through the home subnet route, so the carve-out applies there + // too: en0 192.168.1.10 and en1 192.168.1.137, measured on the + // host. Every other home address keeps full access, SSH + // included, which is why the range is written out. "192.168.1.0/24:0-21,23-65535", "192.168.1.0/29:22", - "192.168.1.8/30:22", - "192.168.1.12/31:22", - "192.168.1.14/32:22", + "192.168.1.8/31:22", + "192.168.1.11/32:22", + "192.168.1.12/30:22", "192.168.1.16/28:22", "192.168.1.32/27:22", "192.168.1.64/26:22", - "192.168.1.128/25:22", + "192.168.1.128/29:22", + "192.168.1.136/32:22", + "192.168.1.138/31:22", + "192.168.1.140/30:22", + "192.168.1.144/28:22", + "192.168.1.160/27:22", + "192.168.1.192/26:22", ], }, @@ -136,8 +143,8 @@ // its SSH port by either name or routed address. { "src": "joshuagilman@gmail.com", - "accept": ["tag:macbackend:5900", "192.168.1.20:22", "10.10.10.14:8443"], - "deny": ["tag:macbackend:22", "192.168.1.15:22"], + "accept": ["tag:macbackend:5900", "192.168.1.11:22", "10.10.10.14:8443"], + "deny": ["tag:macbackend:22", "192.168.1.10:22", "192.168.1.137:22"], }, // A sandbox host still reaches nothing on the Mac backend. {