summaryrefslogtreecommitdiff
path: root/modules/nixos/features/tailscale.nix
blob: ecb793ac89c97ed6ee0a92b10d9c5890d546079c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
{
  config,
  lib,
  pkgs,
  ...
}: let
  cfg = config.features.tailscale;
  secretsDir = ../../../secrets/systems/${config.networking.hostName};
in {
  options.features.tailscale = {
    enable = lib.mkEnableOption "enable support for tailscale";
    ssh.enable = lib.mkEnableOption "enable support for tailscale ssh";
  };

  config = lib.mkIf cfg.enable {
    age.secrets = lib.mkIf cfg.ssh.enable {
      tailscaleAuthKey.file = "${secretsDir}/tailscaleAuthKey.age";
    };

    networking.firewall =
      {
        allowedUDPPorts = [config.services.tailscale.port];
        trustedInterfaces = ["tailscale0"];
      }
      // lib.optionalAttrs cfg.ssh.enable {
        allowedTCPPorts = [22];
      };

    services.tailscale.enable = true;

    # https://tailscale.com/kb/1096/nixos-minecraft/
    systemd.services = lib.mkIf cfg.ssh.enable {
      tailscale-autoconnect = {
        description = "Automatic connection to Tailscale";

        after = ["network-pre.target" "tailscale.service"];
        wants = ["network-pre.target" "tailscale.service"];
        wantedBy = ["multi-user.target"];

        serviceConfig.Type = "oneshot";

        script = ''
          # wait for tailscaled to settle
          sleep 2

          # check if we are already authenticated to tailscale
          status="$(${lib.getExe pkgs.tailscale} status -json | ${lib.getExe pkgs.jq} -r .BackendState)"
          if [ $status = "Running" ]; then # if so, then do nothing
            exit 0
          fi

          # otherwise authenticate with tailscale
          ${lib.getExe pkgs.tailscale} up --ssh \
            --auth-key "file:${config.age.secrets.tailscaleAuthKey.path}"
        '';
      };
    };
  };
}