From 279d00ae82907bb3669d49ebe1282618dc8251da Mon Sep 17 00:00:00 2001 From: m3tam3re Date: Tue, 6 May 2025 13:22:39 +0200 Subject: [PATCH] Headscale and Tailscale config modules --- hosts/m3-ares/services/tailscale.nix | 42 +++++++----------------- hosts/m3-atlas/services/headscale.nix | 43 ++++++++++++------------- hosts/m3-atlas/services/tailscale.nix | 28 +++------------- hosts/m3-kratos/secrets.nix | 4 ++- hosts/m3-kratos/services/tailscale.nix | 9 +++--- secrets/tailscale-key.age | Bin 1130 -> 1130 bytes 6 files changed, 44 insertions(+), 82 deletions(-) diff --git a/hosts/m3-ares/services/tailscale.nix b/hosts/m3-ares/services/tailscale.nix index 15f40d6..4748fea 100644 --- a/hosts/m3-ares/services/tailscale.nix +++ b/hosts/m3-ares/services/tailscale.nix @@ -5,36 +5,16 @@ }: { services.tailscale = { enable = true; - useRoutingFeatures = "client"; + authKeyFile = config.age.secrets.tailscale-key.path; + extraUpFlags = [ + "--login-server=https://va.m3tam3re.com" + ]; + extraSetFlags = [ + "--exit-node=m3-atlas" + "--exit-node-allow-lan-access" + ]; }; - - # systemd.services.tailscale-autoconnect = { - # description = "Automatic connection to Tailscale"; - - # # make sure tailscale is running before trying to connect to tailscale - # after = ["network-pre.target" "tailscale.service"]; - # wants = ["network-pre.target" "tailscale.service"]; - # wantedBy = ["multi-user.target"]; - - # # set this service as a oneshot job - # serviceConfig = { - # Type = "oneshot"; - # EnvironmentFile = "${config.age.secrets.tailscale-key.path}"; - # }; - - # # have the job run this shell script - # script = with pkgs; '' - # # wait for tailscaled to settle - # sleep 2 - - # # check if we are already authenticated to tailscale - # status="$(${tailscale}/bin/tailscale status -json | ${jq}/bin/jq -r .BackendState)" - # if [ $status = "Running" ]; then # if so, then do nothing - # exit 0 - # fi - - # # otherwise authenticate with tailscale - # ${tailscale}/bin/tailscale up --exit-node 100.88.96.77 --authkey $TAILSCALE_KEY - # ''; - # }; + environment.systemPackages = with pkgs; [ + tailscale + ]; } diff --git a/hosts/m3-atlas/services/headscale.nix b/hosts/m3-atlas/services/headscale.nix index 871bfdb..9e9ca13 100644 --- a/hosts/m3-atlas/services/headscale.nix +++ b/hosts/m3-atlas/services/headscale.nix @@ -1,7 +1,7 @@ { - pkgs, config, lib, + pkgs, ... }: { # Define a new option for the admin user @@ -42,14 +42,12 @@ routes = { "0.0.0.0/0" = ["${adminUser}"]; "10.0.0.0/8" = ["${adminUser}"]; - "172.16.0.0/12" = ["${adminUser}"]; "192.168.0.0/16" = ["${adminUser}"]; }; exitNode = ["${adminUser}"]; }; }; - # Convert to HuJSON format with comments aclHuJson = '' // Headscale ACL Policy - Generated by NixOS @@ -57,14 +55,13 @@ ${builtins.toJSON aclConfig} ''; - aclFile = pkgs.writeText "acl-policy.hujson" aclHuJson; in { services = { headscale = { enable = true; - port = 3009; adminUser = "m3tam3re"; + port = 3009; settings = { server_url = "https://va.m3tam3re.com"; dns = { @@ -76,24 +73,6 @@ }; }; - # Traefik configuration - services.traefik.dynamicConfigOptions.http = { - services.headscale.loadBalancer.servers = [ - { - url = "http://localhost:3009/"; - } - ]; - - routers.headscale = { - rule = "Host(`va.m3tam3re.com`)"; - tls = { - certResolver = "godaddy"; - }; - service = "headscale"; - entrypoints = "websecure"; - }; - }; - # Create a systemd service to ensure the admin user exists systemd.services.headscale-ensure-admin = lib.mkIf config.services.headscale.enable { description = "Ensure Headscale admin user exists"; @@ -117,5 +96,23 @@ fi ''; }; + + # Traefik configuration for headscale + services.traefik.dynamicConfigOptions.http = { + services.headscale.loadBalancer.servers = [ + { + url = "http://localhost:3009/"; + } + ]; + + routers.headscale = { + rule = "Host(`va.m3tam3re.com`)"; + tls = { + certResolver = "godaddy"; + }; + service = "headscale"; + entrypoints = "websecure"; + }; + }; }; } diff --git a/hosts/m3-atlas/services/tailscale.nix b/hosts/m3-atlas/services/tailscale.nix index a8ef6d0..ae948e9 100644 --- a/hosts/m3-atlas/services/tailscale.nix +++ b/hosts/m3-atlas/services/tailscale.nix @@ -1,45 +1,27 @@ { config, + lib, pkgs, ... }: { services.tailscale = { enable = true; - useRoutingFeatures = "both"; authKeyFile = config.age.secrets.tailscale-key.path; + useRoutingFeatures = "both"; extraUpFlags = [ "--login-server=${config.services.headscale.settings.server_url}" "--advertise-exit-node" "--accept-routes" ]; }; - - services.networkd-dispatcher = { + services.networkd-dispatcher = lib.mkIf config.services.tailscale.enable { enable = true; rules."50-tailscale" = { onState = ["routable"]; script = '' - "${pkgs.ethtool} NETDEV=$(ip -o route get 8.8.8.8 | cut -f 5 -d " ") | -K $NETDEV rx-udp-gro-forwarding on rx-gro-list off + NETDEV=$(ip -o route get 8.8.8.8 | cut -f 5 -d " ") + ${pkgs.ethtool}/bin/ethtool -K $NETDEV rx-udp-gro-forwarding on rx-gro-list off ''; }; }; - - boot.kernel.sysctl = { - "net.ipv4.ip_forward" = 1; - "net.ipv6.conf.all.forwarding" = 1; - "net.core.gro_normal_batch" = 8; - "net.core.gro_flush_timeout" = 200000; - }; - - networking.firewall = { - trustedInterfaces = ["tailscale0"]; - allowedUDPPorts = [41641]; - checkReversePath = "loose"; - }; - - environment.systemPackages = with pkgs; [ - ethtool - tailscale - networkd-dispatcher - ]; } diff --git a/hosts/m3-kratos/secrets.nix b/hosts/m3-kratos/secrets.nix index 5f50d47..d57ef4d 100644 --- a/hosts/m3-kratos/secrets.nix +++ b/hosts/m3-kratos/secrets.nix @@ -1,6 +1,9 @@ { age = { secrets = { + tailscale-key = { + file = ../../secrets/tailscale-key.age; + }; wg-DE = { file = ../../secrets/wg-DE.age; path = "/etc/wireguard/DE.conf"; @@ -21,7 +24,6 @@ file = ../../secrets/wg-BR.age; path = "/etc/wireguard/BR.conf"; }; - tailscale-key.file = ../../secrets/tailscale-key.age; m3tam3re-secrets = { file = ../../secrets/m3tam3re-secrets.age; owner = "m3tam3re"; diff --git a/hosts/m3-kratos/services/tailscale.nix b/hosts/m3-kratos/services/tailscale.nix index 49a8bba..50a22a6 100644 --- a/hosts/m3-kratos/services/tailscale.nix +++ b/hosts/m3-kratos/services/tailscale.nix @@ -1,10 +1,11 @@ -{ +{config, ...}: { services.tailscale = { enable = true; - useRoutingFeatures = "client"; + authKeyFile = config.age.secrets.tailscale-key.path; + useRoutingFeatures = "both"; extraUpFlags = [ - "--login-server https://va.m3tam3re.com" - "--exit-node=m3-atlas" + "--login-server=https://va.m3tam3re.com" + "--accept-routes" "--exit-node-allow-lan-access" ]; }; diff --git a/secrets/tailscale-key.age b/secrets/tailscale-key.age index 0f1b32aed40e91a4cfeaac041a0e4afd91548ab9..b8a6dfd1d81cc90160d81bfac76ab4c17694999a 100644 GIT binary patch delta 1062 zcmaFG@rq-DPJOtyhlz1kj;p7?TTx_jxJ7w^Yp!X5PiUx&WwM)b zHdjGTeujBOfVZbpXmD~yT12?1uYYN}bE2tlxOu~}Jmgj8W>%qPZc>qcXk=lMxq(NHXQi{gQHWEPUzKB+iHnzKl3BRL z#E;_PW!XMio}~u)k=g0RMSi8}Ub)^S`Tm(HQTeICS)P?ex!y_TA;BgFWiBRMuFi#l zxdvvgey)K5VR1KIpIj$bTMed%t#m+`)-eo08QN>>L!vUZt19yRy()8kOMSF0+%qimok|Tdl8n6!j6FiRip;#TgF@26^#e1?EiL@Y zib})twVkuvQ%o|-JpFP!Qwu^X%OlLfTq=rTp;T0ysNfQq<7!^cl@#ET>~5?bn(kHZ z8)fcXp6XLl=vE(l;>B zmBi)l6qpzs=x>(p>{uQgn3SlWR#utf=oV60Wtf(cpYCFAn&zJo5t$#DmFQYjRTY?& zWL#8WUKpO_Qdw-0S5eGWm|kp>mtL8YQ{iJ!W$But9a^7e<{Fk<65(7DVPbA-Vdxo> zR8X2(>R#w%VU}B-?i-fo;hp82XPjM}kz(o|#AR-gT^L+$s9)seo?YeV>6w$~ljl>G znOzcAVi;)ZTV-w*=HeA*>}lX!5a5;SRu*1v8RT1(Yf@xXoUCt@<;oT0rC(GU7*JSL z=38Opn_lnl6cm)LZ{e5ikyYRy?pRJ|*T0=P&<(u!C zlp9gz@8hg*lwav=lAoDv!sVaonNuDbp>LGyn_ur88dMNvkeXYVXYL&2<>O>g=2)6l zrpl|FMVGv}PR#95)6=fWvpH~*)RZtY_l$9NvS03SGnBiW?#igsOtB{r& zl3p2*nwxKs=uQo>7|Er&!~cEIt$9z< zEB16|axD10R=Zm|cW=!KiOhnJuDTj87tAp~(q(e+8TWG0o|saXJ&)=<5-q+hY>-G5 c($xO{S?yxN#bdUMZmqulv$n^562G+?09*uZVE_OC delta 1062 zcmaFG@rq-DPJM=XWk7I|SCWUBaY15Hd5Vd?pP651x^Gpkmw#YnczIrgpQ&k7hDDWA zB$u1Jt5cj(OoO=^ozc`tE*C$^Io~>1kEI?jF9Ler2g<=EW5mW)+cK#l|Tf zZpDekNkvY<#s)zFg((G*;l3qh5oz9DsUeB;H7hOVxY;~B;4gNyYITmoF2 z-BJ>>OkIjYT=I=PQ{?%55aw!F8S0kllpgMq=j<97oE_@y8B~_;?wS-}=Ifu~o#f~lWl$F6 zn#^VFY#tdJ5uQ`#T$Q2i;%;Uc;O}ExXy{~FTo&b0SnB9mSP^dNuynAY-AW{;#innQ5?oqX_{PE>g;S$m75Y)>{_AklvST+C8LppSkYZNq zo#s-UW$2$A<{jXfgDC`;}mA|LB!sh@3<8d*|c8C>C6 zl9W+WVH93aT4G%3U+Cg&XzpelYL-@zkr$Pi5oyj<7@3{vmm8E>T#yr)?Vp$9ljrMa zo>=Z}Sy&ihX6X}}tsQCPZc^f17**;SClw_FWn^$345NQ_1#igsOtKg;W zkysg+?vbA7@9SHfYv7q#ky{m(W>k^rVv*rkR#}v9?p)@i?_Z!F5Xtr0sB-Uu4^JA} z0-w8YyW6l?@5-rJ1zO<^Z{I5X=0CNk=gc(El{@q<{_PR`EqddQbLVo8&xh5v9`JS$ dRC@8d_>Rx~{*W$@8v!2_-n^}`7GyZL9RRGiahL!A