feat(headscale): Add ACL support

Tailscale ACLs allow you to restrict connections from/to different
machines on your tailnet; you can think of it as an in-tailnet firewall

It requires a JSON file to be referenced in the tailscale config, but we
can use nix to write this from a normal configuration option

Change-Id: I070f8f124ead7a4fc9b385af6f189c13ecbfe4d3
Reviewed-on: https://git.clicks.codes/c/Infra/NixFiles/+/744
Reviewed-by: Samuel Shuert <coded@clicks.codes>
Tested-by: Skyler Grey <minion@clicks.codes>
diff --git a/modules/nixos/clicks/services/headscale/default.nix b/modules/nixos/clicks/services/headscale/default.nix
index 68ed4fc..1e1b0d8 100644
--- a/modules/nixos/clicks/services/headscale/default.nix
+++ b/modules/nixos/clicks/services/headscale/default.nix
@@ -2,7 +2,12 @@
 #
 # SPDX-License-Identifier: GPL-3.0-only
 
-{ lib, config, ... }:
+{
+  lib,
+  config,
+  pkgs,
+  ...
+}:
 let
   cfg = config.clicks.services.headscale;
 in
@@ -57,6 +62,11 @@
       description = "Headscale private key file path";
       default = null;
     };
+    acl = lib.mkOption {
+      type = lib.types.nullOr (lib.types.attrsOf lib.types.anything);
+      description = "ACL rules for headscale to enforce";
+      default = null;
+    };
   };
 
   config = lib.mkIf cfg.enable {
@@ -109,6 +119,10 @@
         allowed_groups = lib.mkIf (cfg.oidc.allowed_groups != null) cfg.oidc.allowed_groups;
         strip_email_domain = true;
       };
+
+      settings.acl_policy_path = lib.mkIf (cfg.acl != null) (
+        pkgs.writers.writeJSON "tailscale-acls.json" cfg.acl
+      );
     };
 
     systemd.services.headscale.requires = [ "postgresql.service" ];