diff options
Diffstat (limited to 'system/nanopi.nix')
-rwxr-xr-x | system/nanopi.nix | 320 |
1 files changed, 193 insertions, 127 deletions
diff --git a/system/nanopi.nix b/system/nanopi.nix index 45eae872..5083f9e7 100755 --- a/system/nanopi.nix +++ b/system/nanopi.nix @@ -1,16 +1,19 @@ { config , pkgs , lib -, inputs , ... }: let fsTypes = [ "f2fs" "ext" "exfat" "vfat" ]; + domain = "home.arpa"; + ts_domain = "hydra-pinecone.ts.net"; in { imports = [ ./nanopi-hardware.nix - (inputs.nixos-hardware + "/friendlyarm/nanopi-r5s") + <agenix/modules/age.nix> + <nixos-hardware/friendlyarm/nanopi-r5s> + <home-manager/nixos> ]; age.secrets = { @@ -68,6 +71,26 @@ in }; }; + systemd.services.backup-golink = { + enable = true; + startAt = "daily"; + description = "Export short links from golink"; + path = with pkgs; [ curl gitMinimal ]; + script = '' + [ -d golink ] || git init --quiet golink --initial-branch=main --shared=world + git config --global user.email linde@alanpearce.eu + cd golink + curl https://go.${ts_domain}/.export > links.json + git add links.json + git commit -m $(date +%F) + ''; + serviceConfig = { + Type = "oneshot"; + User = "linde"; + WorkingDirectory = config.users.users.linde.home; + }; + }; + services.journald.extraConfig = '' MaxRetentionSec=1 month ''; @@ -85,61 +108,33 @@ in systemd.network.config.networkConfig = { SpeedMeter = true; }; + networking = { hostName = "nanopi"; - domain = "lan"; + domain = domain; + search = [ domain ]; + hosts = { + "fd7a:115c:a1e0::53" = [ "tailscale" "ts" ]; + "192.168.100.1" = [ "modem" "pyur" ]; + "192.168.4.1" = [ "lte" ]; + }; useDHCP = false; useNetworkd = true; - nameservers = [ - "176.9.93.198" - "176.9.1.117" - "2a01:4f8:151:34aa::198" - "2a01:4f8:141:316d::117" - ]; + nat = { + enable = true; + internalInterfaces = [ "bridge0" "lan1" "lan2" ]; + externalInterface = "wan0"; + }; firewall = { enable = true; rejectPackets = true; logRefusedConnections = false; pingLimit = "5/second"; filterForward = true; # we are a router - allowedUDPPorts = [ - 53 - 123 - ]; - allowedTCPPorts = [ - 53 - 123 - 80 - 443 + trustedInterfaces = [ + "bridge0" + "tailscale0" ]; - interfaces.bridge0 = { - allowedTCPPorts = [ - 53 - 67 - 139 - 445 - 1883 - 3000 - 3689 - 5357 - 5533 # SmartDNS - 8096 - 9091 # Transmission - ]; - allowedUDPPorts = [ - 53 - 67 - 69 - 137 - 4011 # PXE - 5533 # SmartDNS - 5353 - 5355 # LLMNR - 3702 # Samba WSDD - 41641 - 51827 - ]; - }; interfaces.wan0 = { allowedTCPPorts = [ 6980 # aria2c @@ -151,8 +146,10 @@ in ]; }; extraForwardRules = '' - iifname { "wan0", "wlan0", "wwan0" } oifname { "lan1", "lan2", "bridge0" } icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept - iifname { "lan1", "lan2", "bridge0" } oifname { "wan0", "wlan0", "wwan0" } accept + iifname { "wlan0", "lte0" } oifname { "lan1", "lan2", "bridge0" } icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept + iifname { "lan1", "lan2", "bridge0" } oifname { "wlan0", "lte0" } accept + iifname "tailscale0" oifname "bridge0" accept + iifname "bridge0" oifname "tailscale0" accept ''; }; nftables = { @@ -163,7 +160,7 @@ in content = '' chain postrouting { type nat hook postrouting priority srcnat; policy accept; - oifname { "wan0", "wlan0", "wwan0" } masquerade + oifname { "wlan0", "lte0" } masquerade } chain prerouting { type nat hook prerouting priority dstnat; @@ -185,7 +182,57 @@ in # }; }; }; - services.resolved.enable = false; + + networking = { + resolvconf = { + # having this enabled (the default) is pointless + # a) this device has fixed upstream nameservers + enable = false; + # b) it makes tailscale think it should change the search domains for MagicDNS + # ... due to this: + # useLocalResolver = false; + # which is set by kresd?! + # https://github.com/NixOS/nixpkgs/blob/7780e5160e011b39019797a4c4b1a4babc80d1bf/nixos/modules/services/networking/kresd.nix#L113 + }; + nameservers = lib.optionals config.services.dnsmasq.enable [ + "::1" + "127.0.0.1" + ]; + }; + services.resolved = { + # this allows link-specific DNS configuration, which is useful. + enable = true; + # why use simple boolean when string do trick? + llmnr = "false"; + dnssec = "true"; + fallbackDns = [ + "9.9.9.9" + "149.112.112.112" + "2620::fe:fe" + "2620::fe:9" + "116.203.248.56" + "2a01:4f8:c012:23a4::1" + ]; + }; + + # leaving this here just in case I ever think about disabling both `resolvconf` and `resolved` + # I thought that there would have been a fallback that does this anyway, but apparently not. + environment.etc."resolv.conf".text = lib.mkDefault (lib.optionalString + ( + !config.networking.resolvconf.enable + && + !config.services.resolved.enable + ) '' + search ${domain} ${ts_domain} + nameserver ::1 + nameserver 127.0.0.1 + options edns0 + ''); + + services.tailscale = { + enable = true; + extraUpFlags = [ "--accept-dns=false" "--advertise-routes=10.0.0.0/20,fd12:d04f:65d:42::/56" ]; + }; programs.command-not-found.enable = false; @@ -193,6 +240,10 @@ in enable = true; openFirewall = true; startWhenNeeded = false; + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + }; }; programs.mosh.enable = true; services.sshguard = { @@ -203,7 +254,7 @@ in systemd.network = { enable = true; wait-online = { - ignoredInterfaces = [ "wan0" "wlan0" "wwan0" ]; + extraArgs = [ "--interface" "bridge0" ]; }; links = { "10-name-lan1" = { @@ -233,10 +284,10 @@ in Name = "wlan0"; }; }; - "10-name-wwan0" = { + "10-name-lte0" = { matchConfig.MACAddress = "34:4b:50:00:00:00"; linkConfig = { - Name = "wwan0"; + Name = "lte0"; }; }; }; @@ -254,7 +305,6 @@ in bridge = [ "bridge0" ]; linkConfig = { MACAddress = "82:E0:06:9C:8E:7C"; - RequiredForOnline = "no"; }; networkConfig.LinkLocalAddressing = "no"; }; @@ -265,11 +315,20 @@ in "10.0.0.1/20" "fd12:d04f:65d:42::1/56" ]; + addresses = [ + { + Address = "fe80::1/64"; + Scope = "link"; + } + ]; networkConfig = { IPv6AcceptRA = false; - IPv6SendRA = true; + IPv6SendRA = false; DHCPPrefixDelegation = true; ConfigureWithoutCarrier = true; + MulticastDNS = true; + BindCarrier = [ "lan0" "lan1" ]; + Domains = [ domain ]; }; dhcpPrefixDelegationConfig = { UplinkInterface = "wan0"; @@ -277,17 +336,9 @@ in Assign = true; Token = "::1"; }; - ipv6SendRAConfig = { - RouterLifetimeSec = 1800; - EmitDNS = true; - DNS = "fd12:d04f:65d:42::1"; - EmitDomains = true; - Domains = [ config.networking.domain ]; - }; }; - "50-wwan0" = { - matchConfig.Name = "wwan0"; - linkConfig.RequiredForOnline = false; + "50-lte0" = { + matchConfig.Name = "lte0"; networkConfig = { DHCP = "yes"; IPv6AcceptRA = true; @@ -296,17 +347,16 @@ in dhcpV4Config = { UseDNS = false; SendHostname = false; - RouteMetric = 2048; + UseRoutes = false; }; ipv6AcceptRAConfig.UseDNS = false; routes = [ { - routeConfig = { - Gateway = "_dhcp4"; - QuickAck = true; - InitialCongestionWindow = 30; - InitialAdvertisedReceiveWindow = 30; - }; + Gateway = "_dhcp4"; + Metric = 2048; + QuickAck = true; + InitialCongestionWindow = 30; + InitialAdvertisedReceiveWindow = 30; } ]; cakeConfig = { @@ -320,7 +370,6 @@ in }; "50-wan" = { matchConfig.Name = "wan0"; - linkConfig.RequiredForOnline = "no"; networkConfig = { DHCP = "yes"; IPv6AcceptRA = true; @@ -328,6 +377,7 @@ in }; dhcpV4Config = { UseDNS = false; + UseRoutes = false; SendHostname = false; SendRelease = false; UseHostname = false; @@ -343,15 +393,28 @@ in }; ipv6AcceptRAConfig = { UseDNS = false; + UseGateway = false; }; addresses = [ { - addressConfig = { - Address = "192.168.100.10/24"; - # Peer = "192.168.100.1/32"; - Label = "wan0:0"; - # Scope = "link"; - }; + Address = "192.168.100.10/24"; + # Peer = "192.168.100.1/32"; + Label = "wan0:0"; + # Scope = "link"; + } + ]; + routes = [ + { + Gateway = "_dhcp4"; + QuickAck = true; + InitialCongestionWindow = 30; + InitialAdvertisedReceiveWindow = 30; + } + { + Gateway = "_ipv6ra"; + QuickAck = true; + InitialCongestionWindow = 30; + InitialAdvertisedReceiveWindow = 30; } ]; cakeConfig = { @@ -365,7 +428,6 @@ in }; "60-wlan" = { matchConfig.MACAddress = "9c:53:22:33:bf:e9"; - linkConfig.RequiredForOnline = "no"; networkConfig = { DHCP = "yes"; IPForward = "yes"; @@ -380,13 +442,11 @@ in }; routes = [ { - routeConfig = { - Metric = 2048; - Gateway = "_dhcp4"; - QuickAck = true; - InitialCongestionWindow = 30; - InitialAdvertisedReceiveWindow = 30; - }; + Metric = 2048; + Gateway = "_dhcp4"; + QuickAck = true; + InitialCongestionWindow = 30; + InitialAdvertisedReceiveWindow = 30; } ]; cakeConfig = { @@ -415,12 +475,13 @@ in services.dnsmasq = { enable = true; - resolveLocalQueries = true; + # let systemd-resolved.do this + resolveLocalQueries = false; alwaysKeepRunning = true; settings = { local-ttl = 60; - domain = "lan"; - dhcp-fqdn = false; + domain = domain; + dhcp-fqdn = true; domain-needed = true; bogus-priv = true; no-resolv = true; @@ -434,34 +495,42 @@ in "2620::fe:9" "116.203.248.56" "2a01:4f8:c012:23a4::1" - # "127.0.0.1#5553" - # "::1#5553" - "127.0.0.1#5533" - "::1#5533" + # kresd + "127.0.0.1#5553" + "::1#5553" + # smartdns + # "127.0.0.1#5533" + # "::1#5533" + "/ts.net/tailscale" ]; localise-queries = true; cname = [ - "homeassistant,ha" + "ha,home-assistant" ]; interface-name = [ - "home.alanpearce.eu,wan0" - "nanopi.alanpearce.eu,wan0" - "nanopi.lan.alanpearce.eu,bridge0" - "syncthing.lan.alanpearce.eu,bridge0" - "wan,wan0" - "wlan,wlan0" - "wwan,wwan0" + "nanopi.${domain},bridge0" + "wan.${domain},wan0" + "wlan.${domain},wlan0" ]; interface = [ + "lo" "bridge0" ]; + no-dhcp-interface = [ + "tailscale0" + ]; # auth-zone = "lan,wan0"; # auth-server = [ # "nanopi.alanpearce.eu,wan0" # ]; - bind-interfaces = false; + bind-interfaces = true; - no-hosts = true; + # if this is false, a remote query for nanopi returns 127.0.0.2, because that's in /etc/hosts + no-hosts = false; + expand-hosts = true; + + dnssec = true; + trust-anchor = ".,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D"; enable-ra = true; dhcp-lease-max = 240; @@ -469,19 +538,18 @@ in dhcp-rapid-commit = true; dhcp-range = [ "10.0.1.0,10.0.1.250,12h" - "::, constructor:bridge0, ra-stateless, 48h" - "fd12:d04f:65d::, ra-stateless, ra-names, 48h" + "fd12:d04f:65d:42::,slaac,ra-names,48h" + "::,constructor:bridge0,ra-stateless,48h" ]; dhcp-host = [ "00:a0:de:b3:0c:01,10.0.0.50,wxa-50" "10:f0:68:12:b1:e0,10.0.0.11,Ruckus" "9c:93:4e:ad:05:c8,10.0.0.210,xerox-b210" "00:08:9b:f5:b8:25,10.0.0.42,dontpanic" - "d8:3a:dd:34:85:cc,d8:3a:dd:34:85:cd,10.0.0.81,ha" + "d8:3a:dd:34:85:cc,d8:3a:dd:34:85:cd,10.0.0.81,home-assistant" ]; dhcp-option = [ "option:ntp-server,0.0.0.0" - "option:dns-server,0.0.0.0,10.0.0.81" "option:tftp-server,0.0.0.0" "option:ip-forward-enable,0" # ip-forwarding "252,\"\\n\"" @@ -512,7 +580,7 @@ in services.networkd-dispatcher = { # broken? - enable = false; + enable = true; rules = { update-home-address = { onState = [ "configured" "configuring" ]; @@ -527,6 +595,18 @@ in exit 0 ''; }; + tailscale-subnet-router-optimisation = { + onState = [ "routable" ]; + script = '' + #!${pkgs.runtimeShell} + set -eu + + if [[ $IFACE == "wan0" && $OperationalState == "routable" ]] + then + ${pkgs.ethtool}/bin/ethtool -K $IFACE rx-udp-gro-forwarding on rx-gro-list off + fi + ''; + }; }; }; @@ -555,6 +635,7 @@ in "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMvcW4Z9VxOQgEJjsRC1uSMwEJ4vru9BwjT+Z50nawp4 lan" ]; }; + home-manager.users.alan = import ../user/nanopi.nix; users.groups = { linde.members = [ ]; @@ -566,6 +647,7 @@ in isSystemUser = true; shell = "/bin/sh"; home = "/srv/backup/linde"; + homeMode = "755"; createHome = true; packages = with pkgs; [ rdiff-backup ]; openssh.authorizedKeys.keys = [ @@ -614,7 +696,7 @@ in }; nixpkgs.config.allowUnfree = true; system.autoUpgrade = { - enable = false; + enable = true; dates = "04:15"; randomizedDelaySec = "59 min"; flake = "git+https://git.alanpearce.eu/nixfiles"; @@ -700,22 +782,6 @@ in ''; }; - services.avahi = { - enable = true; - nssmdns4 = true; - denyInterfaces = [ "wan0" "wwan0" "wlan0" ]; - browseDomains = [ - "alanpearce.eu" - ]; - publish = { - enable = true; - hinfo = true; - addresses = true; - userServices = true; - workstation = true; - }; - }; - services.samba = { enable = true; enableNmbd = false; @@ -786,7 +852,7 @@ in "10.0.0.1:53 -group lan -exclude-default-group" ]; nameserver = [ - "/lan/lan" + "/${domain}/${domain}" ]; dualstack-ip-selection = true; dualstack-ip-selection-threshold = 10; |