1import ./make-test-python.nix ({ pkgs, lib, ... }:
2 let
3 tls-cert =
4 pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
5 openssl req \
6 -x509 -newkey rsa:4096 -sha256 -days 365 \
7 -nodes -out cert.pem -keyout key.pem \
8 -subj '/CN=headscale' -addext "subjectAltName=DNS:headscale"
9
10 mkdir -p $out
11 cp key.pem cert.pem $out
12 '';
13 in {
14 name = "headscale";
15 meta.maintainers = with lib.maintainers; [ misterio77 ];
16
17 nodes = let
18 headscalePort = 8080;
19 stunPort = 3478;
20 peer = {
21 services.tailscale.enable = true;
22 security.pki.certificateFiles = [ "${tls-cert}/cert.pem" ];
23 };
24 in {
25 peer1 = peer;
26 peer2 = peer;
27
28 headscale = {
29 services = {
30 headscale = {
31 enable = true;
32 port = headscalePort;
33 settings = {
34 server_url = "https://headscale";
35 ip_prefixes = [ "100.64.0.0/10" ];
36 derp.server = {
37 enabled = true;
38 region_id = 999;
39 stun_listen_addr = "0.0.0.0:${toString stunPort}";
40 };
41 };
42 };
43 nginx = {
44 enable = true;
45 virtualHosts.headscale = {
46 addSSL = true;
47 sslCertificate = "${tls-cert}/cert.pem";
48 sslCertificateKey = "${tls-cert}/key.pem";
49 locations."/" = {
50 proxyPass = "http://127.0.0.1:${toString headscalePort}";
51 proxyWebsockets = true;
52 };
53 };
54 };
55 };
56 networking.firewall = {
57 allowedTCPPorts = [ 80 443 ];
58 allowedUDPPorts = [ stunPort ];
59 };
60 environment.systemPackages = [ pkgs.headscale ];
61 };
62 };
63
64 testScript = ''
65 start_all()
66 headscale.wait_for_unit("headscale")
67 headscale.wait_for_open_port(443)
68
69 # Create headscale user and preauth-key
70 headscale.succeed("headscale users create test")
71 authkey = headscale.succeed("headscale preauthkeys -u test create --reusable")
72
73 # Connect peers
74 up_cmd = f"tailscale up --login-server 'https://headscale' --auth-key {authkey}"
75 peer1.execute(up_cmd)
76 peer2.execute(up_cmd)
77
78 # Check that they are reachable from the tailnet
79 peer1.wait_until_succeeds("tailscale ping peer2")
80 peer2.wait_until_succeeds("tailscale ping peer1")
81 '';
82 })