fix(raptus/headscale): open udp instead of tcp for DERP
This commit is contained in:
parent
b02fdaaa24
commit
d526fdac98
5 changed files with 215 additions and 196 deletions
|
@ -13,7 +13,7 @@ in
|
|||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
./disk-config.nix
|
||||
./forgejo.nix
|
||||
./headscale.nix
|
||||
./headscale
|
||||
];
|
||||
|
||||
age.secrets = {
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
metricsEnable = false;
|
||||
mkAcl = src: dst: {
|
||||
action = "accept";
|
||||
inherit src dst;
|
||||
};
|
||||
mkSshAcl = src: dst: users: {
|
||||
action = "accept";
|
||||
inherit src dst users;
|
||||
};
|
||||
domain = "hs.ccnlc.eu";
|
||||
in
|
||||
mkIf config.services.headscale.enable {
|
||||
environment.systemPackages = [ config.services.headscale.package ];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
3478 # DERP
|
||||
];
|
||||
|
||||
services = {
|
||||
headscale = {
|
||||
address = "127.0.0.1";
|
||||
port = 8521;
|
||||
|
||||
settings = {
|
||||
server_url = "https://${domain}";
|
||||
tls_cert_path = null;
|
||||
tls_key_path = null;
|
||||
ip_prefixes = [
|
||||
"100.64.0.0/10"
|
||||
"fd7a:115c:a1e0::/48"
|
||||
];
|
||||
ephemeral_node_inactivity_timeout = "30m";
|
||||
node_update_check_interval = "10s";
|
||||
metrics_listen_addr = mkIf metricsEnable "127.0.0.1:8086";
|
||||
# logging
|
||||
log = {
|
||||
format = "text";
|
||||
level = "info";
|
||||
};
|
||||
|
||||
logtail.enabled = false;
|
||||
|
||||
dns_config = {
|
||||
override_local_dns = true;
|
||||
magic_dns = true;
|
||||
|
||||
# FIX: shan being down takes down entire tailnet
|
||||
# 1 -> move dns to dedicated device
|
||||
# 2 -> find out if fallback dns's are supported by headscale
|
||||
nameservers = [
|
||||
"100.64.0.4"
|
||||
];
|
||||
extra_records =
|
||||
let
|
||||
mkRecords = map (sub: {
|
||||
name = "${sub}.ccnlc.eu";
|
||||
type = "A";
|
||||
value = "100.64.0.4";
|
||||
});
|
||||
in
|
||||
[
|
||||
{
|
||||
name = "ccnlc.eu";
|
||||
type = "A";
|
||||
value = "100.64.0.4";
|
||||
}
|
||||
{
|
||||
name = "git.ccnlc.eu";
|
||||
type = "A";
|
||||
value = "100.64.0.3";
|
||||
}
|
||||
]
|
||||
# Tailscale doesn't seem to support wildcard A/AAAA records
|
||||
# - https://github.com/juanfont/headscale/issues/2159#issuecomment-2393406444
|
||||
++ mkRecords [
|
||||
"immich"
|
||||
"adguard"
|
||||
"nextcloud"
|
||||
"kitchenowl"
|
||||
"navidrome"
|
||||
"subsonic"
|
||||
"nextcloud"
|
||||
"paperless"
|
||||
"truenas"
|
||||
"fritz"
|
||||
];
|
||||
};
|
||||
|
||||
derp = {
|
||||
# Reference: https://github.com/juanfont/headscale/issues/1326#issuecomment-1505487881
|
||||
server = {
|
||||
enabled = true;
|
||||
stun_listen_addr = "0.0.0.0:3478";
|
||||
|
||||
# Region code and name are displayed in the Tailscale UI to identify a DERP region
|
||||
region_code = "headscale";
|
||||
region_name = "Headscale Embedded DERP";
|
||||
region_id = 999;
|
||||
};
|
||||
|
||||
urls = [ ];
|
||||
paths = [ ];
|
||||
|
||||
auto_update_enabled = false;
|
||||
update_frequency = "6h";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts.${domain} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
quic = true;
|
||||
http3 = true;
|
||||
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://localhost:${toString config.services.headscale.port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
|
||||
"/metrics" = mkIf metricsEnable {
|
||||
proxyPass = "http://${toString config.services.headscale.settings.metrics_listen_addr}/metrics";
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = ''
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
tailscaled.after = [ "headscale.service" ];
|
||||
headscale = {
|
||||
environment = {
|
||||
# required to use ssh
|
||||
HEADSCALE_EXPERIMENTAL_FEATURE_SSH = "1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.headscale.settings.acl_policy_path = pkgs.writeTextFile {
|
||||
name = "headscale-acl.hujson";
|
||||
text = builtins.toJSON {
|
||||
acls = [
|
||||
(mkAcl [ "tag:client" ] [
|
||||
"tag:client:*"
|
||||
"tag:server:*"
|
||||
]) # client -> {client, server}
|
||||
(mkAcl [
|
||||
"tag:client"
|
||||
"tag:server"
|
||||
] [ "tag:backup:${toString options.modules.server.rsync-daemon.port.default}" ])
|
||||
];
|
||||
|
||||
ssh = [
|
||||
(mkSshAcl [ "tag:client" ] [
|
||||
"tag:server"
|
||||
"tag:client"
|
||||
] [ "ny" ]) # client -> {client, server}
|
||||
];
|
||||
|
||||
tags = [
|
||||
"tag:client"
|
||||
"tag:server"
|
||||
"tag:backup"
|
||||
];
|
||||
|
||||
tagOwners =
|
||||
let
|
||||
users = [ "ny" ];
|
||||
tags = map (name: "tag:${name}") [
|
||||
"server"
|
||||
"client"
|
||||
"backup"
|
||||
];
|
||||
in
|
||||
lib.genAttrs tags (_: users);
|
||||
|
||||
autoApprovers = {
|
||||
exitNode = [ "*" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
61
hosts/raptus/headscale/acls.nix
Normal file
61
hosts/raptus/headscale/acls.nix
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
pkgs,
|
||||
options,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
mkAcl = src: dst: {
|
||||
action = "accept";
|
||||
inherit src dst;
|
||||
};
|
||||
mkSshAcl = src: dst: users: {
|
||||
action = "accept";
|
||||
inherit src dst users;
|
||||
};
|
||||
in
|
||||
{
|
||||
services.headscale.settings.acl_policy_path = pkgs.writeTextFile {
|
||||
name = "headscale-acl.hujson";
|
||||
text = builtins.toJSON {
|
||||
acls = [
|
||||
(mkAcl [ "tag:client" ] [
|
||||
"tag:client:*"
|
||||
"tag:server:*"
|
||||
]) # client -> {client, server}
|
||||
(mkAcl [
|
||||
"tag:client"
|
||||
"tag:server"
|
||||
] [ "tag:backup:${toString options.modules.server.rsync-daemon.port.default}" ])
|
||||
];
|
||||
|
||||
ssh = [
|
||||
(mkSshAcl [ "tag:client" ] [
|
||||
"tag:server"
|
||||
"tag:client"
|
||||
] [ "ny" ]) # client -> {client, server}
|
||||
];
|
||||
|
||||
tags = [
|
||||
"tag:client"
|
||||
"tag:server"
|
||||
"tag:backup"
|
||||
];
|
||||
|
||||
tagOwners =
|
||||
let
|
||||
users = [ "ny" ];
|
||||
tags = map (name: "tag:${name}") [
|
||||
"server"
|
||||
"client"
|
||||
"backup"
|
||||
];
|
||||
in
|
||||
lib.genAttrs tags (_: users);
|
||||
|
||||
autoApprovers = {
|
||||
exitNode = [ "*" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
104
hosts/raptus/headscale/default.nix
Normal file
104
hosts/raptus/headscale/default.nix
Normal file
|
@ -0,0 +1,104 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf;
|
||||
metricsEnable = false;
|
||||
domain = "hs.ccnlc.eu";
|
||||
stunPort = 3478;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./dns.nix
|
||||
./acls.nix
|
||||
];
|
||||
|
||||
config = mkIf config.services.headscale.enable {
|
||||
|
||||
environment.systemPackages = [ config.services.headscale.package ];
|
||||
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
stunPort # DERP
|
||||
];
|
||||
|
||||
services = {
|
||||
headscale = {
|
||||
address = "127.0.0.1";
|
||||
port = 8521;
|
||||
|
||||
settings = {
|
||||
server_url = "https://${domain}";
|
||||
tls_cert_path = null;
|
||||
tls_key_path = null;
|
||||
ip_prefixes = [
|
||||
"100.64.0.0/10"
|
||||
"fd7a:115c:a1e0::/48"
|
||||
];
|
||||
ephemeral_node_inactivity_timeout = "30m";
|
||||
node_update_check_interval = "10s";
|
||||
metrics_listen_addr = mkIf metricsEnable "127.0.0.1:8086";
|
||||
# logging
|
||||
log = {
|
||||
format = "text";
|
||||
level = "info";
|
||||
};
|
||||
|
||||
logtail.enabled = false;
|
||||
|
||||
derp = {
|
||||
# Reference: https://github.com/juanfont/headscale/issues/1326#issuecomment-1505487881
|
||||
server = {
|
||||
enabled = true;
|
||||
stun_listen_addr = "0.0.0.0:${toString stunPort}";
|
||||
|
||||
# Region code and name are displayed in the Tailscale UI to identify a DERP region
|
||||
region_code = "headscale";
|
||||
region_name = "Headscale Embedded DERP";
|
||||
region_id = 999;
|
||||
};
|
||||
|
||||
urls = [ ];
|
||||
paths = [ ];
|
||||
|
||||
auto_update_enabled = false;
|
||||
update_frequency = "6h";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts.${domain} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
quic = true;
|
||||
http3 = true;
|
||||
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://localhost:${toString config.services.headscale.port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
|
||||
"/metrics" = mkIf metricsEnable {
|
||||
proxyPass = "http://${toString config.services.headscale.settings.metrics_listen_addr}/metrics";
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = ''
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
tailscaled.after = [ "headscale.service" ];
|
||||
headscale = {
|
||||
environment = {
|
||||
# required to use ssh
|
||||
HEADSCALE_EXPERIMENTAL_FEATURE_SSH = "1";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
49
hosts/raptus/headscale/dns.nix
Normal file
49
hosts/raptus/headscale/dns.nix
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
config = {
|
||||
services.headscale.settings.dns_config = {
|
||||
override_local_dns = true;
|
||||
magic_dns = true;
|
||||
|
||||
# FIX: shan being down takes down entire tailnet
|
||||
# 1 -> move dns to dedicated device
|
||||
# 2 -> find out if fallback dns's are supported by headscale
|
||||
nameservers = [
|
||||
"100.64.0.4"
|
||||
];
|
||||
extra_records =
|
||||
let
|
||||
mkRecords = map (sub: {
|
||||
name = "${sub}.ccnlc.eu";
|
||||
type = "A";
|
||||
value = "100.64.0.4";
|
||||
});
|
||||
in
|
||||
[
|
||||
{
|
||||
name = "ccnlc.eu";
|
||||
type = "A";
|
||||
value = "100.64.0.4";
|
||||
}
|
||||
{
|
||||
name = "git.ccnlc.eu";
|
||||
type = "A";
|
||||
value = "100.64.0.3";
|
||||
}
|
||||
]
|
||||
# Tailscale doesn't seem to support wildcard A/AAAA records
|
||||
# - https://github.com/juanfont/headscale/issues/2159#issuecomment-2393406444
|
||||
++ mkRecords [
|
||||
"immich"
|
||||
"adguard"
|
||||
"nextcloud"
|
||||
"kitchenowl"
|
||||
"navidrome"
|
||||
"subsonic"
|
||||
"nextcloud"
|
||||
"paperless"
|
||||
"truenas"
|
||||
"fritz"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Add table
Reference in a new issue