{ ... }: {
  flake.nixosModules.systemTailscale =
    { config, lib, ... }:
    let
      cfg = config.chiasson.system.networking.tailscale;
      tsCfg = config.services.tailscale;
    in
    {
      options.chiasson.system.networking.tailscale = {
        enable = lib.mkEnableOption ''
          Tailscale mesh VPN. Joins this host to your tailnet for encrypted access
          from anywhere without opening inbound ports on your router.
        '';

        authKeyFile = lib.mkOption {
          type = lib.types.nullOr lib.types.path;
          default = null;
          example = "/run/secrets/tailscale/auth-key";
          description = ''
            Reusable Tailscale auth key (sops path). Create one at
            https://login.tailscale.com/admin/settings/keys — enable Reusable and
            Pre-approved. Store under `tailscale/auth-key` in secrets/secrets.yaml.
          '';
        };

        openFirewall = lib.mkOption {
          type = lib.types.bool;
          default = true;
          description = "Allow Tailscale UDP 41641 through the host firewall.";
        };

        acceptRoutes = lib.mkOption {
          type = lib.types.bool;
          default = false;
          description = ''
            Accept subnet routes advertised by other tailnet nodes (e.g. home LAN
            via nix-server). Enable on portable clients like t2mbp.
          '';
        };

        subnetRouter = {
          enable = lib.mkEnableOption ''
            Advertise the home LAN through this node so other tailnet devices can
            reach local IPs (SSH, Attic, Gitea, Jellyfin, etc.). Enable on an
            always-on home host (nix-server). Approve the route in the Tailscale
            admin console after first connect.
          '';

          routes = lib.mkOption {
            type = lib.types.listOf lib.types.str;
            default = [ "192.168.2.0/24" ];
            example = [ "192.168.2.0/24" ];
            description = "Subnets to advertise to the tailnet.";
          };
        };
      };

      config = lib.mkIf cfg.enable (lib.mkMerge [
        {
          services.tailscale = {
            enable = true;
            openFirewall = cfg.openFirewall;
            authKeyFile = cfg.authKeyFile;
          };

          networking.firewall.trustedInterfaces = lib.mkAfter [ "tailscale0" ];
        }
        (lib.mkIf cfg.acceptRoutes {
          services.tailscale.useRoutingFeatures = "client";
          services.tailscale.extraUpFlags = [ "--accept-routes" ];
        })
        (lib.mkIf cfg.subnetRouter.enable {
          services.tailscale.useRoutingFeatures = "both";
          services.tailscale.extraUpFlags =
            map (route: "--advertise-routes=${route}") cfg.subnetRouter.routes;
        })
        (lib.mkIf (cfg.authKeyFile != null) {
          # Upstream uses `$(cat $authKeyFile)` which breaks when sops leaves a trailing newline.
          systemd.services.tailscaled-autoconnect.script = lib.mkOverride 50 ''
            getState() {
              tailscale status --json --peers=false | jq -r '.BackendState'
            }

            lastState=""
            while state="$(getState)"; do
              if [[ "$state" != "$lastState" ]]; then
                case "$state" in
                  NeedsLogin|NeedsMachineAuth|Stopped)
                    echo "Server needs authentication, sending auth key"
                    tailscale up --auth-key "$(tr -d '\n\r' < ${cfg.authKeyFile})" ${lib.escapeShellArgs tsCfg.extraUpFlags}
                    ;;
                  Running)
                    echo "Tailscale is running"
                    systemd-notify --ready
                    exit 0
                    ;;
                  *)
                    echo "Waiting for Tailscale State = Running or systemd timeout"
                    ;;
                esac
                echo "State = $state"
              fi
              lastState="$state"
              sleep .5
            done
          '';
        })
      ]);
    };
}
