mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-07 23:30:07 +09:00
nix: run the headscale VM test on the test kit
Drops nginx, the cert and dead ip_prefixes. Proves DERP relay and TLS noise after a restart, and puts nix/module.nix under CI.
This commit is contained in:
committed by
Kristoffer Dalby
parent
200c2c01e8
commit
00663fbbfe
@@ -296,12 +296,14 @@
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
checks = {
|
# Gated to Linux: parts of the tree are Linux-specific, and the VM
|
||||||
headscale = pkgs.testers.nixosTest (import ./nix/tests/headscale.nix);
|
# test needs KVM.
|
||||||
}
|
checks = pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux (
|
||||||
# The Go build/test checks are gated to Linux: parts of the tree are
|
goChecks
|
||||||
# Linux-specific and the pure unit subset is validated by CI.
|
// {
|
||||||
// pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux goChecks;
|
headscale = pkgs.testers.runNixOSTest (import ./nix/tests/headscale.nix self);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-87
@@ -1,14 +1,18 @@
|
|||||||
{ pkgs, lib, ... }:
|
# The test kit's contract test, and CI's coverage of nix/module.nix.
|
||||||
|
self:
|
||||||
|
{ lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
tls-cert = pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
|
policy = pkgs.writeText "policy.json" (
|
||||||
openssl req \
|
builtins.toJSON {
|
||||||
-x509 -newkey rsa:4096 -sha256 -days 365 \
|
acls = [
|
||||||
-nodes -out cert.pem -keyout key.pem \
|
{
|
||||||
-subj '/CN=headscale' -addext "subjectAltName=DNS:headscale"
|
action = "accept";
|
||||||
|
src = [ "*" ];
|
||||||
mkdir -p $out
|
dst = [ "*:*" ];
|
||||||
cp key.pem cert.pem $out
|
}
|
||||||
'';
|
];
|
||||||
|
}
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
name = "headscale";
|
name = "headscale";
|
||||||
@@ -17,89 +21,50 @@ in
|
|||||||
misterio77
|
misterio77
|
||||||
];
|
];
|
||||||
|
|
||||||
nodes =
|
nodes = {
|
||||||
let
|
headscale = {
|
||||||
headscalePort = 8080;
|
imports = [ self.nixosModules.testkit ];
|
||||||
stunPort = 3478;
|
services.headscale.settings.dns.extra_records = [
|
||||||
peer = {
|
{
|
||||||
services.tailscale.enable = true;
|
name = "foo.bar";
|
||||||
security.pki.certificateFiles = [ "${tls-cert}/cert.pem" ];
|
type = "A";
|
||||||
};
|
value = "100.64.0.2";
|
||||||
in
|
}
|
||||||
{
|
];
|
||||||
peer1 = peer;
|
|
||||||
peer2 = peer;
|
|
||||||
|
|
||||||
headscale = {
|
|
||||||
services = {
|
|
||||||
headscale = {
|
|
||||||
enable = true;
|
|
||||||
port = headscalePort;
|
|
||||||
settings = {
|
|
||||||
server_url = "https://headscale";
|
|
||||||
ip_prefixes = [ "100.64.0.0/10" ];
|
|
||||||
derp = {
|
|
||||||
server = {
|
|
||||||
enabled = true;
|
|
||||||
region_id = 999;
|
|
||||||
stun_listen_addr = "0.0.0.0:${toString stunPort}";
|
|
||||||
};
|
|
||||||
urls = [ ];
|
|
||||||
};
|
|
||||||
dns = {
|
|
||||||
base_domain = "tailnet";
|
|
||||||
extra_records = [
|
|
||||||
{
|
|
||||||
name = "foo.bar";
|
|
||||||
type = "A";
|
|
||||||
value = "100.64.0.2";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
override_local_dns = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
nginx = {
|
|
||||||
enable = true;
|
|
||||||
virtualHosts.headscale = {
|
|
||||||
addSSL = true;
|
|
||||||
sslCertificate = "${tls-cert}/cert.pem";
|
|
||||||
sslCertificateKey = "${tls-cert}/key.pem";
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:${toString headscalePort}";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
networking.firewall = {
|
|
||||||
allowedTCPPorts = [
|
|
||||||
80
|
|
||||||
443
|
|
||||||
];
|
|
||||||
allowedUDPPorts = [ stunPort ];
|
|
||||||
};
|
|
||||||
environment.systemPackages = [ pkgs.headscale ];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
# All of peer1's noise goes over the kit's TLS listener, not plain :80.
|
||||||
|
peer1 = {
|
||||||
|
imports = [ self.nixosModules.testkit-peer ];
|
||||||
|
systemd.services.tailscaled.environment.TS_FORCE_NOISE_443 = "1";
|
||||||
|
};
|
||||||
|
# No direct UDP for peer2: its traffic has to cross the kit's DERP.
|
||||||
|
peer2 = {
|
||||||
|
imports = [ self.nixosModules.testkit-peer ];
|
||||||
|
systemd.services.tailscaled.environment.TS_DEBUG_ALWAYS_USE_DERP = "1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
start_all()
|
start_all()
|
||||||
headscale.wait_for_unit("headscale")
|
key = headscale.succeed("hs-authkey test").strip()
|
||||||
headscale.wait_for_open_port(443)
|
for peer in [peer1, peer2]:
|
||||||
|
peer.succeed(f"hs-join {key}")
|
||||||
|
|
||||||
# Create headscale user and preauth-key
|
peer1.wait_until_succeeds("tailscale ping --until-direct=false -c 1 peer2 | grep -F 'via DERP(headscale)'")
|
||||||
headscale.succeed("headscale users create test")
|
peer2.wait_until_succeeds("tailscale ping --until-direct=false -c 1 peer1.tailnet")
|
||||||
authkey = headscale.succeed("headscale preauthkeys -u 1 create --reusable")
|
res = peer1.wait_until_succeeds("${lib.getExe pkgs.dig} +short foo.bar").strip()
|
||||||
|
assert res == "100.64.0.2", res
|
||||||
|
|
||||||
# Connect peers
|
headscale.succeed("headscale policy set -f ${policy}")
|
||||||
up_cmd = f"tailscale up --login-server 'https://headscale' --auth-key {authkey}"
|
|
||||||
peer1.execute(up_cmd)
|
|
||||||
peer2.execute(up_cmd)
|
|
||||||
|
|
||||||
# Check that they are reachable from the tailnet
|
# Clients reconnect after a control restart, peer1 over the TLS listener.
|
||||||
peer1.wait_until_succeeds("tailscale ping peer2")
|
headscale.systemctl("restart headscale.service")
|
||||||
peer2.wait_until_succeeds("tailscale ping peer1.tailnet")
|
headscale.wait_until_succeeds(
|
||||||
assert (res := peer1.wait_until_succeeds("${lib.getExe pkgs.dig} +short foo.bar").strip()) == "100.64.0.2", f"Domain {res} did not match 100.64.0.2"
|
"headscale nodes list -o json | ${lib.getExe pkgs.jq} -e 'length == 2 and all(.[]; .online)'",
|
||||||
|
timeout=timedelta(minutes=2),
|
||||||
|
)
|
||||||
|
peer1.wait_until_succeeds("tailscale ping --until-direct=false -c 1 peer2")
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user