{ config, inputs, outputs, pkgs, ... }: { boot = { initrd.kernelModules = [ "zfs" ]; kernel.sysctl = { "net.ipv4.ip_forward" = 1; "net.ipv4.conf.all.proxy_arp" = 1; }; #kernelPackages = pkgs.linuxPackages_6_10; loader = { efi = { canTouchEfiVariables = true; efiSysMountPoint = "/efiboot/efi1"; }; systemd-boot = { enable = true; extraInstallCommands = '' ${pkgs.rsync}/bin/rsync -av --delete /efiboot/efi1/ /efiboot/efi2 ''; }; timeout = 3; }; supportedFilesystems = [ "zfs" ]; }; environment.etc."nftables-vpn.conf".text = '' # VPN firewall flush ruleset table inet filter { chain input { type filter hook input priority filter; policy drop; # established/related connections ct state established,related accept # invalid connections ct state invalid drop # loopback interface iif lo accept # ICMP (routers may also want: mld-listener-query, nd-router-solicit) #ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, echo-reply, echo-request, nd-neighbor-advert, nd-neighbor-solicit, nd-router-advert, packet-too-big, parameter-problem, time-exceeded } accept ip protocol icmp icmp type { destination-unreachable, echo-reply, echo-request, parameter-problem, router-advertisement, source-quench, time-exceeded } accept # services iif veth.vpn tcp dport 8080 accept # qBittorrent iif veth.vpn tcp dport 9696 accept # Prowlarr iifname wg1 tcp dport { 49152-65535 } accept # Transmission } chain output { type filter hook output priority filter; policy drop; # explicitly allow my DNS traffic without VPN skuid nipsy ip daddr 192.168.1.1 tcp dport domain accept skuid nipsy ip daddr 192.168.1.1 udp dport domain accept # explicitly allow my traffic without VPN oifname veth.vpn skuid nipsy tcp sport 8080 accept # qBittorrent oifname veth.vpn skuid nipsy tcp sport 9696 accept # Prowlarr oifname veth.vpn skuid nipsy ip daddr 192.168.1.2 tcp dport { 7878, 8686, 8787, 8989 } accept # Prowlarr to { Radarr, Lidarr, Readarr, Sonarr } # allow any traffic out through VPN oifname wg1 accept # drop everything else counter drop } chain forward { type filter hook forward priority filter; policy drop; } } ''; environment.systemPackages = with pkgs; [ angband assaultcube bsdgames bzflag extremetuxracer frozen-bubble hedgewars kobodeluxe lidarr mailutils moc nethack openttd prowlarr qbittorrent-nox radarr rdiff-backup readarr scorched3d signal-desktop sonarr superTux superTuxKart umoria warzone2100 wpa_supplicant xonotic-sdl xpilot-ng ]; imports = [ ./disks.nix ./hardware-configuration.nix ./services.nix ../common/core ../common/optional/adb.nix ../common/optional/db.nix ../common/optional/dev.nix ../common/optional/ebooks.nix ../common/optional/games.nix ../common/optional/google-authenticator.nix ../common/optional/misc.nix ../common/optional/multimedia.nix ../common/optional/pipewire.nix ../common/optional/sdr.nix ../common/optional/services/chrony.nix ../common/optional/services/openssh.nix ../common/optional/services/xorg.nix ../common/optional/sound.nix ../common/optional/zfs.nix ../common/users/nipsy ../common/users/root ]; networking = { defaultGateway = { address = "192.168.1.1"; interface = "wlp5s0"; }; domain = "bitgnome.net"; hostId = "2ae4c89f"; hostName = "arrakis"; interfaces = { wlp5s0 = { ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; }; }; nameservers = [ "192.168.1.1" ]; nftables.enable = true; useDHCP = false; wg-quick.interfaces = { wg0 = { address = [ "10.4.20.1/24" ]; listenPort = 51820; peers = [ { # black-sheep allowedIPs = [ "10.4.20.2/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/black-sheep_psk".path}"; publicKey = "wQsGWsfXI2+GmKHdCH2V2xIeTyV2YlH/IFp6gerxcW8="; } { # lilnasx allowedIPs = [ "10.4.20.3/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/lilnasx_psk".path}"; publicKey = "87cANtuPf28vGrB0uL69/tXgsD/30FUYt/XevQjpz3o="; } { # ramped allowedIPs = [ "10.4.20.4/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/ramped_psk".path}"; publicKey = "TvE3f0QKJXUn8pxmKMaztFvRIdi9z9dxNDN2KNdtRXQ="; } { # homer allowedIPs = [ "10.4.20.5/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/homer_psk".path}"; publicKey = "FBc2ZnypwHgjLQcZrwzPR35gax8JsXLa1ZcZy6iAc3Q="; } { # treebeard allowedIPs = [ "10.4.20.6/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/treebeard_psk".path}"; publicKey = "aYh7q1QNmz6TLYx5OsZcyHQe45Dv0SyIOCtRp1NHDU8="; } { # lolli allowedIPs = [ "10.4.20.7/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/lolli_psk".path}"; publicKey = "npt86Lt/f/9J3qS6u6C0X1MFHIONaA5PKE6lzwwUxTc="; } { # timetrad allowedIPs = [ "10.4.20.8/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/timetrad_psk".path}"; publicKey = "/lWCEMGRIr3Gl/3GQYuweAKylhH5H2KqamiXeocYFVM="; } { # ginaz allowedIPs = [ "10.4.20.254/32" ]; presharedKeyFile = "${config.sops.secrets."wireguard/ginaz_psk".path}"; publicKey = "GuE9PVeS0IDTcaBxOSJmKlvEx2xflxwVGOU+uM0HhBk="; } ]; privateKeyFile = "${config.sops.secrets."wireguard/arrakis_key".path}"; }; }; wireless = { enable = true; networks = { "Crystal Palace" = { pskRaw = "ext:psk_crystal_palace"; }; }; secretsFile = "${config.sops.secrets."wpa_supplicant".path}"; }; }; nixpkgs = { config = { allowUnfree = true; permittedInsecurePackages = [ "aspnetcore-runtime-6.0.36" "aspnetcore-runtime-wrapped-6.0.36" "dotnet-sdk-wrapped-6.0.428" ]; }; hostPlatform = "x86_64-linux"; overlays = [ inputs.nvidia-patch.overlays.default outputs.overlays.additions outputs.overlays.modifications outputs.overlays.master-packages outputs.overlays.stable-packages ]; }; services.openssh.settings.X11Forwarding = true; services.xserver.videoDrivers = [ "nvidia" ]; sops = { age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; defaultSopsFile = ../secrets/arrakis.yaml; secrets = { "nftables/ssh" = {}; "nix-access-token-github" = {}; "wireguard/arrakis_key" = {}; "wireguard/black-sheep_psk" = {}; "wireguard/ginaz_psk" = {}; "wireguard/homer_psk" = {}; "wireguard/lilnasx_psk" = {}; "wireguard/lolli_psk" = {}; "wireguard/ramped_psk" = {}; "wireguard/timetrad_psk" = {}; "wireguard/treebeard_psk" = {}; "wireguard/wg1_conf" = {}; "wpa_supplicant" = {}; }; }; system.activationScripts = { fix-acl-cgit-home-nipsy = '' ${pkgs.acl}/bin/setfacl -m u:cgit:--x /home/nipsy ''; }; system.stateVersion = "23.11"; systemd.services = { "lidarr" = { after = [ "network.target" ]; description = "Lidarr Daemon"; serviceConfig = { User = "nipsy"; Group = "nipsy"; Restart = "always"; RestartSec= 5; Type = "simple"; ExecStart = "${pkgs.lidarr}/bin/Lidarr -nobrowser"; TimeoutStopSec = 20; PIDFile = "/home/nipsy/.config/Lidarr/lidarr.pid"; }; wantedBy = [ "multi-user.target" ]; }; "nftables-extra" = let rules_script = '' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" tcp dport { http, https } counter accept # 80, 443' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" udp dport { netbios-ns, netbios-dgm } counter accept # 137, 138' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" tcp dport { netbios-ssn, microsoft-ds } counter accept # 139, 445' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" tcp dport 2049 counter accept' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" udp dport { 2456, 2457 } counter accept # Valheim dedicated server' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" udp dport 5121 counter accept # Neverwinter Nights Server' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "veth.host" tcp dport { 7878, 8080, 8686, 8787, 8989 } counter accept # Radarr, Sabnzb, Lidarr, Sonarr, Readarr' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" tcp dport { 7878, 8080, 8686, 8787, 8989 } counter accept # Radarr, Sabnzb, Lidarr, Sonarr, Readarr' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" udp dport 15637 counter accept # Enshrouded' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" ip saddr 192.168.1.0/24 udp dport { 27031, 27036 } counter accept # Steam Remote Play' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" ip saddr 192.168.1.0/24 tcp dport { 27036, 27037 } counter accept # Steam Remote Play' ${pkgs.nftables}/bin/nft insert rule inet nixos-fw input 'iifname "wlp5s0" udp dport 51820 counter accept # WireGuard' ${pkgs.nftables}/bin/nft -f ${config.sops.secrets."nftables/ssh".path} ''; in { description = "nftables extra firewall rules"; reload = rules_script; script = rules_script; serviceConfig = { RemainAfterExit = true; Type = "oneshot"; }; unitConfig = { ConditionPathExists = [ config.sops.secrets."nftables/ssh".path ]; ReloadPropagatedFrom = "nftables.service"; }; wantedBy = [ "multi-user.target" ]; after = [ "nftables.service" ]; partOf = [ "nftables.service" ]; }; "prowlarr" = { after = [ "vpn.service" ]; description = "Prowlarr Daemon"; serviceConfig = { User = "nipsy"; Group = "nipsy"; Restart = "always"; RestartSec= 5; Type = "simple"; ExecStart = "${pkgs.prowlarr}/bin/Prowlarr -nobrowser"; TimeoutStopSec = 20; PIDFile = "/home/nipsy/.config/Prowlarr/prowlarr.pid"; NetworkNamespacePath = "/run/netns/vpn"; }; wantedBy = [ "multi-user.target" ]; }; "qbittorrent" = { after = [ "vpn.service" ]; description = "qBittorrent-nox service"; serviceConfig = { User = "nipsy"; Group = "nipsy"; Type = "simple"; ExecStart = "${pkgs.qbittorrent-nox}/bin/qbittorrent-nox"; TimeoutStopSec = 1800; NetworkNamespacePath = "/run/netns/vpn"; }; wantedBy = [ "multi-user.target" ]; }; "radarr" = { after = [ "network.target" ]; description = "Radarr Daemon"; serviceConfig = { User = "nipsy"; Group = "nipsy"; Restart = "always"; RestartSec= 5; Type = "simple"; ExecStart = "${pkgs.radarr}/bin/Radarr -nobrowser"; TimeoutStopSec = 20; PIDFile = "/home/nipsy/.config/Radarr/radarr.pid"; }; wantedBy = [ "multi-user.target" ]; }; "readarr" = { after = [ "network.target" ]; description = "Readarr Daemon"; serviceConfig = { User = "nipsy"; Group = "nipsy"; Restart = "always"; RestartSec= 5; Type = "simple"; ExecStart = "${pkgs.readarr}/bin/Readarr -nobrowser"; TimeoutStopSec = 20; PIDFile = "/home/nipsy/.config/Readarr/readarr.pid"; }; wantedBy = [ "multi-user.target" ]; }; "sonarr" = { after = [ "network.target" ]; description = "Sonarr Daemon"; serviceConfig = { User = "nipsy"; Group = "nipsy"; Restart = "always"; RestartSec= 5; Type = "simple"; ExecStart = "${pkgs.sonarr}/bin/Sonarr -nobrowser"; TimeoutStopSec = 20; PIDFile = "/home/nipsy/.config/Sonarr/sonarr.pid"; }; wantedBy = [ "multi-user.target" ]; }; "vpn" = { after = [ "network.target" ]; description = "VPN service"; serviceConfig = { RemainAfterExit = true; Type = "oneshot"; ExecStart = "/root/bin/vpnctl start"; }; unitConfig = { ConditionPathExists = [ "/root/bin/vpnctl" ]; }; wantedBy = [ "multi-user.target" ]; }; }; systemd.paths."nftables-extra" = { pathConfig = { PathExists = [ config.sops.secrets."nftables/ssh".path ]; }; wantedBy = [ "multi-user.target" ]; }; }