about summary refs log tree commit diff
path: root/ops/modules/tvl-headscale.nix
blob: 7f08e7aa20ce777b8cdf6046b06589c9248848f7 (plain) (blame)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# Configuration for the coordination server for net.tvl.fyi, a
# tailscale network run using headscale.
#
# All TVL members can join this network, which provides several exit
# nodes through which traffic can be routed.
#
# The coordination server is currently run on sanduny.tvl.su. It is
# managed manually, ping somebody with access ... for access.
#
# Servers should join using approximately this command:
#   tailscale up --login-server https://net.tvl.fyi --accept-dns --advertise-exit-node --advertise-tags="tag:tvl"
#
# Clients should join using approximately this command:
#   tailscale up --login-server https://net.tvl.fyi --accept-dns=false
{ config, pkgs, ... }:

let
  accept = src: dst: {
    action = "accept";
    src = [ src ];
    dst = [ dst ];
  };
  acl = with builtins; toFile "headscale-acl.json" (toJSON {
    acls = [
      # allow any tailnet traffic to TVL machines
      (accept "*" "tag:tvl:*")

      # allow any tailnet node to use any exit node
      (accept "*" "autogroup:internet:*")

      # builders can talk to each other
      (accept "tag:builders" "tag:builders:*")

      # anything goes inside tazjin's net
      (accept "group:taznet" "group:taznet:*")
    ];

    # TVL is ... TVL
    groups."group:tvl" = [ "tvl@" ];
    tagOwners."tag:tvl" = [ "group:tvl" ];

    # TVL builder machines (talking to each other through builderball)
    groups."group:builders" = [ "tvl@" "tvl-builders@" ];
    tagOwners."tag:builders" = [ "group:builders" ];

    # tazjin's personal home group
    groups."group:taznet" = [ "tazjin@" "varia@" ];
    tagOwners."tag:taznet" = [ "group:taznet" ];
  });
in
{
  # TODO(tazjin): run embedded DERP server
  services.headscale = {
    enable = true;
    port = 4725; # hscl

    settings = {
      server_url = "https://net.tvl.fyi";
      policy.path = acl;

      dns = {
        # assign DNS names within tail.tvl.fyi (delegated to sanduny)
        magic_dns = true;
        base_domain = "tail.tvl.fyi";
        override_local_dns = false;
        nameservers.global = [
          "8.8.8.8"
          "77.88.8.8"
          "2001:4860:4860::8888"
          "2a02:6b8::feed:0ff"
        ];

        search_domains = [ "tvl.fyi" ];
      };

      # TLS is handled by nginx
      tls_cert_path = null;
      tls_key_path = null;
    };
  };

  environment.systemPackages = [ pkgs.headscale ]; # admin CLI

  services.nginx.virtualHosts."net.tvl.fyi" = {
    serverName = "net.tvl.fyi";
    enableACME = true;
    forceSSL = true;

    # See https://github.com/juanfont/headscale/blob/v0.22.3/docs/reverse-proxy.md#nginx
    extraConfig = ''
      location / {
        proxy_pass http://localhost:${toString config.services.headscale.port};
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $server_name;
        proxy_redirect http:// https://;
        proxy_buffering off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
      }
    '';
  };

}