diff options
| author | Tim Keller <tjk@tjkeller.xyz> | 2026-06-13 14:26:56 -0500 |
|---|---|---|
| committer | Tim Keller <tjk@tjkeller.xyz> | 2026-06-13 14:26:56 -0500 |
| commit | feadf7131e5b6c33ea8485e746361b0529cd6ef4 (patch) | |
| tree | 86c05c33a837eefc566bec45f5ef91e3c7d91eca | |
| parent | b39f24436d5672e90e4261f0dfb906d97e92f1be (diff) | |
| parent | 0397e503b32e73e03ef2dcdda58cc60da262524d (diff) | |
| download | nixos-feadf7131e5b6c33ea8485e746361b0529cd6ef4.tar.xz nixos-feadf7131e5b6c33ea8485e746361b0529cd6ef4.zip | |
Merge branch 'poweredge'
| -rw-r--r-- | archetypes/profiles/default.nix | 1 | ||||
| -rw-r--r-- | archetypes/profiles/router/default.nix | 37 | ||||
| -rw-r--r-- | hosts/poweredge/bitcoind.nix | 35 | ||||
| -rw-r--r-- | hosts/poweredge/configuration.nix | 34 | ||||
| -rw-r--r-- | hosts/poweredge/gitea.nix | 32 | ||||
| -rw-r--r-- | hosts/poweredge/immich.nix | 60 | ||||
| -rw-r--r-- | hosts/poweredge/jellyfin.nix | 68 | ||||
| -rw-r--r-- | hosts/poweredge/networking.nix | 175 | ||||
| -rw-r--r-- | hosts/poweredge/resources/secrets/wg0-router.yaml | 16 | ||||
| -rw-r--r-- | hosts/poweredge/resources/secrets/wg1.yaml | 16 | ||||
| -rw-r--r-- | hosts/poweredge/router-hosts.nix | 71 | ||||
| -rw-r--r-- | hosts/poweredge/transmission.nix | 48 | ||||
| -rw-r--r-- | hosts/poweredge/wg1.nix | 7 | ||||
| -rw-r--r-- | nixos/default.nix | 6 | ||||
| -rw-r--r-- | nixos/services/immich.nix | 36 | ||||
| -rw-r--r-- | nixos/services/jellyfin.nix | 33 | ||||
| -rw-r--r-- | nixos/services/router/blocklists.nix | 35 | ||||
| -rw-r--r-- | nixos/services/router/default.nix | 8 | ||||
| -rw-r--r-- | nixos/services/router/dns-dhcp.nix | 18 | ||||
| -rw-r--r-- | nixos/services/router/routing.nix | 19 |
20 files changed, 512 insertions, 243 deletions
diff --git a/archetypes/profiles/default.nix b/archetypes/profiles/default.nix index 3f5567d..23b5c05 100644 --- a/archetypes/profiles/default.nix +++ b/archetypes/profiles/default.nix @@ -4,7 +4,6 @@ ./desktop ./headless ./pi - ./router ./zfs ]; } diff --git a/archetypes/profiles/router/default.nix b/archetypes/profiles/router/default.nix deleted file mode 100644 index 58e3407..0000000 --- a/archetypes/profiles/router/default.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ lib, pkgs, ... }: let - mkRouter = lib.mkOverride 800; - - # https://wiki.nixos.org/wiki/Networking - nixosConfig = { - services.unbound = { - _blocklists = { - enable = true; - blocklists = let - hageziList = list: [ - "https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/rpz/${list}.txt" - "https://gitlab.com/hagezi/mirror/-/raw/main/dns-blocklists/rpz/${list}.txt" - "https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/rpz/${list}.txt" - ]; - in { - hageziNSFW = hageziList "nsfw"; - hageziPro = hageziList "pro"; - }; - }; - }; - services._router = { - dnsDhcpConfig.enable = mkRouter true; - routing = { - enable = mkRouter true; - interfaces = { - lan = mkRouter "lan0"; - wan = mkRouter "wan0"; - }; - }; - }; - }; - - homeConfig = {}; -in { - imports = [ (lib._mkProfileArchetype "router" nixosConfig homeConfig) ]; -} - diff --git a/hosts/poweredge/bitcoind.nix b/hosts/poweredge/bitcoind.nix new file mode 100644 index 0000000..715fb8a --- /dev/null +++ b/hosts/poweredge/bitcoind.nix @@ -0,0 +1,35 @@ +{ + containers.bitcoind = { + autoStart = true; + ephemeral = true; + privateNetwork = true; + extraVeths.vb-bitcoind = { + hostBridge = "br-lan0"; + #localMacAddress = "02:00:00:00:00:04"; # TODO update to 26.05 + }; + + # Host path + bindMounts = { + "/var/lib/bitcoind-main" = { + hostPath = "/media/ingens/bitcoin"; + isReadOnly = false; + }; + }; + + config = { lib, pkgs, config, ... }: let + btdPort = 8333; + in { + # Network + networking.interfaces.vb-bitcoind.useDHCP = true; + networking.firewall.allowedTCPPorts = [ btcPort ]; + + # Bitcoin + services.bitcoind."main" = { + enable = true; + port = btcPort; + }; + + system.stateVersion = "25.11"; + }; + }; +} diff --git a/hosts/poweredge/configuration.nix b/hosts/poweredge/configuration.nix index f2e3e09..8ad7350 100644 --- a/hosts/poweredge/configuration.nix +++ b/hosts/poweredge/configuration.nix @@ -1,10 +1,13 @@ { config, lib, pkgs, ... }: { imports = [ - ./ddns-updater.nix + #./ddns-updater.nix ./fileshares.nix ./networking.nix #./notification-mailer.nix # TODO move some of this stuff to archetype - ./wg1.nix + #./gitea.nix + ./jellyfin.nix + ./immich.nix + #./bitcoind.nix ]; # Setup bootloader @@ -18,10 +21,6 @@ home.users.timmy.enable = true; }; zfs.enable = true; - router.enable = true; - }; - collections = { - development.docker.enable = true; }; }; @@ -31,27 +30,12 @@ # Enable smartd services.smartd.enable = true; # TODO move to archetype - # Enable web services - services = { - #_cgit = { - # enable = true; - # hostAddress = "192.168.1.10"; - # localAddress = "192.168.1.11"; - # rootTitle = "PowerEdge local cgit"; - # # TODO add authorizedKeys - #}; - _immich = { - enable = true; - mediaLocationHostPath = "/media/ingens/immich"; - }; - _jellyfin = { - enable = true; - mediaLocationHostPath = "/media/ingens/media"; - }; + # Enable nvidia + hardware.nvidia = { + open = false; # Need for NVENC + package = config.boot.kernelPackages.nvidiaPackages.stable; }; - #services._klipper.enable = true; - # Enable user timmy _users.timmy.enable = true; diff --git a/hosts/poweredge/gitea.nix b/hosts/poweredge/gitea.nix new file mode 100644 index 0000000..c7a4c70 --- /dev/null +++ b/hosts/poweredge/gitea.nix @@ -0,0 +1,32 @@ +{ + containers.gitea = { + autoStart = true; + privateNetwork = true; + extraVeths.vb-gitea = { + hostBridge = "br-lan0"; + #localMacAddress = "02:00:00:00:00:03"; # TODO update to 26.05 + }; + + config = { lib, pkgs, config, ... }: { + # Network + networking.interfaces.vb-gitea.useDHCP = true; + networking.firewall.allowedTCPPorts = [ 80 22 ]; # Caddy + ssh + + # Gitea + services.gitea = { + enable = true; + user = "git"; # So ssh cloning uses git@gitea + }; + + # Reverse proxy + services.caddy = { + enable = true; + virtualHosts.":80".extraConfig = '' + reverse_proxy localhost:3000 + ''; + }; + + system.stateVersion = "25.11"; + }; + }; +} diff --git a/hosts/poweredge/immich.nix b/hosts/poweredge/immich.nix new file mode 100644 index 0000000..a98595e --- /dev/null +++ b/hosts/poweredge/immich.nix @@ -0,0 +1,60 @@ +{ + containers.immich = { + autoStart = true; + privateNetwork = true; + extraVeths.vb-immich = { + hostBridge = "br-lan0"; + #localMacAddress = "02:00:00:00:00:01"; # TODO update to 26.05 + }; + + # Host path + bindMounts = { + "/var/lib/immich" = { + hostPath = "/media/ingens/immich"; + isReadOnly = false; + }; + }; + + # GPU + #allowedDevices = [ + # { node = "/dev/dri/card1"; modifier = "rw"; } + # { node = "/dev/dri/renderD128"; modifier = "rw"; } + #]; + + #bindMounts = { + # "/dev/dri/card1" = { + # hostPath = "/dev/dri/card1"; + # isReadOnly = false; + # }; + # "/dev/dri/renderD128" = { + # hostPath = "/dev/dri/renderD128"; + # isReadOnly = false; + # }; + #}; + + config = { lib, pkgs, config, ... }: { + # Network + networking.interfaces.vb-immich.useDHCP = true; + networking.firewall.allowedTCPPorts = [ 80 ]; # Caddy + + # Immich + services.immich = { + enable = true; + host = "0.0.0.0"; + openFirewall = true; + }; + + environment.systemPackages = with pkgs; [ immich immich-cli ]; + + # Reverse proxy + services.caddy = { + enable = true; + virtualHosts.":80".extraConfig = '' + reverse_proxy localhost:2283 + ''; + }; + + system.stateVersion = "25.11"; + }; + }; +} diff --git a/hosts/poweredge/jellyfin.nix b/hosts/poweredge/jellyfin.nix new file mode 100644 index 0000000..84f3ec0 --- /dev/null +++ b/hosts/poweredge/jellyfin.nix @@ -0,0 +1,68 @@ +{ + containers.jellyfin = { + autoStart = true; + privateNetwork = true; + extraVeths.vb-jellyfin = { + hostBridge = "br-lan0"; + #localMacAddress = "02:00:00:00:00:02"; # TODO update to 26.05 + }; + bindMounts = { + "/media" = { + hostPath = "/media/ingens/media"; + isReadOnly = true; + }; + }; + + # GPU + allowedDevices = [ + { node = "/dev/dri/card1"; modifier = "rw"; } + { node = "/dev/dri/renderD128"; modifier = "rw"; } + ]; + + bindMounts = { + "/dev/dri/card1" = { + hostPath = "/dev/dri/card1"; + isReadOnly = false; + }; + "/dev/dri/renderD128" = { + hostPath = "/dev/dri/renderD128"; + isReadOnly = false; + }; + }; + + config = { lib, config, ... }: { + # Network + networking.interfaces.vb-jellyfin.useDHCP = true; + networking.firewall.allowedTCPPorts = [ 80 ]; # Caddy + + # CUDA + nix.settings = { + substituters = [ "https://cache.flox.dev" ]; + trusted-public-keys = [ "flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs=" ]; + }; + #nixpkgs.config.cudaSupport = true; + users.users.jellyfin.extraGroups = [ "video" "render" ]; + + # Jellyfin + services.jellyfin = { + enable = true; + openFirewall = true; + #hardwareAcceleration = { + # enable = true; + # type = "nvenc"; + # device = "/dev/dri/renderD128"; + #}; + }; + + # Reverse proxy + services.caddy = { + enable = true; + virtualHosts.":80".extraConfig = '' + reverse_proxy localhost:8096 + ''; + }; + + system.stateVersion = "26.05"; + }; + }; +} diff --git a/hosts/poweredge/networking.nix b/hosts/poweredge/networking.nix index 09759ee..965069e 100644 --- a/hosts/poweredge/networking.nix +++ b/hosts/poweredge/networking.nix @@ -1,90 +1,119 @@ -{ +let + hostIp = "192.168.1.10"; +in { config, ... }: { networking = { - enableIPv6 = false; # Label lan and wan interfaces _interfaceLabels = { enable = true; - interfaces = { - lan0 = "50:9a:4c:5d:c3:7a"; - wan0 = "50:9a:4c:5d:c3:7b"; - }; + interfaces.lan0 = "50:9a:4c:5d:c3:7a"; + interfaces.wan0 = "50:9a:4c:5d:c3:7b"; }; - # Set ip addresses + # Create bridged lan interface for all containers + bridges.br-lan0.interfaces = [ "lan0" ]; + # Disable dhcp on router interfaces interfaces = { - lan0.ipv4.addresses = [{ - address = "192.168.1.1"; - prefixLength = 24; - }]; - wan0.useDHCP = true; + veth-router-lan.useDHCP = false; + vb-router-lan0.useDHCP = false; }; - # Firewall rules - firewall = { - interfaces.wan0 = { - allowedUDPPorts = [ 51820 ]; - }; - interfaces.lan0 = { - allowedTCPPorts = [ 2283 80 ]; # FIXME temp - }; + # Configure network + defaultGateway = "10.255.255.1"; # Read explaination for veth-router-lan below + nameservers = [ "192.168.1.1" ]; # DNS will only be available from this ip address THROUGH the default gateway + # br-lan0 will be the interface used for networking on poweredge host + interfaces.br-lan0.ipv4.addresses = [{ + address = hostIp; + prefixLength = 24; + }]; + }; + + # Wireguard office tunnel secret + sops.secrets.wg0-router.sopsFile = ./resources/secrets/wg0-router.yaml; + + # Router container + containers.router = { + autoStart = true; + ephemeral = true; + privateNetwork = true; + # Pass wan0 directly into container since it isn't needed elsewhere + interfaces = [ "wan0" ]; + # Setup router lan0 + # NOTE: Host/container communication is not possible through a hostBridge interface + extraVeths.vb-router-lan0.hostBridge = "br-lan0"; + # Setup virtual host-router bridge interface. + # This is the default gateway for host/container communication since + # communication isn't possible through hostBridge interfaces. + # This is essentially equivalent to connecting the host to the + # container with a virtual ethernet cable on a separate interface. + extraVeths.veth-router-lan = { + hostAddress = "10.255.255.2"; + localAddress = "10.255.255.1"; }; - # Additional advanced rules - # TODO add multi NAT feature to router service - nftables = { - enable = true; - tables = { - # NAT/masquerade wg1 allowing lan0 clients to access wg1 - wg-nat = { - family = "ip"; - content = '' - chain post { - type nat hook postrouting priority srcnat; policy accept; - iifname "lan0" oifname "wg1" masquerade comment "lan0 => wg1" - } - ''; - }; - }; + # Bind wg0-router secret to container + bindMounts."/run/secrets/wg0" = { + hostPath = config.sops.secrets.wg0-router.path; + isReadOnly = true; }; - }; - services._router = { - dnsDhcpConfig = { - localDomain = "home.lan"; - dhcp = { - defaultGateway = "192.168.1.1"; - localhostIp = "192.168.1.1"; - rangeStart = "192.168.1.50"; - rangeEnd = "192.168.1.250"; - # TODO think about moving leases to another file - staticLeases = { - idrac-7N94GK2 = { - macAddress = "50:9a:4c:5d:c3:7c"; - staticIp = "192.168.1.2"; - }; - OpenWrt-Attic = { - macAddress = "34:98:b5:60:5e:be"; - staticIp = "192.168.1.3"; - }; - OpenWrt-Basement = { - macAddress = "8c:3b:ad:35:c7:8c"; - staticIp = "192.168.1.4"; - }; - ArcherC54 = { - macAddress = "12:eb:b6:13:f9:e2"; - staticIp = "192.168.1.5"; - }; - T495 = { - macAddress = "04:33:c2:9d:34:74"; - staticIp = "192.168.1.11"; - }; - optiplex = { - macAddress = "e4:54:e8:bc:ba:05"; - staticIp = "192.168.1.12"; + config = { lib, config, ... }: { + imports = [ + ../../nixos/services/router + ./router-hosts.nix # Contains dhcp config + static leases + overrides + ]; + + networking = { + # Set ip addresses + enableIPv6 = false; + interfaces = { + vb-router-lan0.ipv4.addresses = [{ + address = "192.168.1.1"; + prefixLength = 24; + }]; + wan0.useDHCP = true; + }; + # Setup wireguard + wg-quick.interfaces = { + wg0.configFile = "/run/secrets/wg0"; + }; + # Firewall (port-forwarding) rules + firewall = { + #interfaces.wan0 = { + # allowedTCPPorts = [ 8333 ]; # bitcoin + # allowedUDPPorts = [ 51820 ]; # wg + #}; + }; + # Additional advanced rules + # TODO add multi NAT feature to router service (this is just a normal nat rule) + nftables = { + enable = true; + tables = { + # NAT/masquerade wg0 allowing vb-router-lan0 clients to access wg0 + wg-nat = { + family = "ip"; + content = '' + chain post { + type nat hook postrouting priority srcnat; policy accept; + iifname "vb-router-lan0" oifname "wg0" masquerade comment "vb-router-lan0 => wg0" + iifname "veth-router-lan" oifname "wg0" masquerade comment "veth-router-lan => wg0" + } + ''; + }; }; - X230 = { - macAddress = "84:3a:4b:60:34:c4"; - staticIp = "192.168.1.13"; + }; + }; + + # Setup router + services._router = { + dnsDhcpConfig.enable = true; + routing = { + enable = true; + interfaces = { + lan = [ "vb-router-lan0" "veth-router-lan" ]; + wan = "wan0"; }; }; }; + + system.stateVersion = "25.11"; }; }; + } diff --git a/hosts/poweredge/resources/secrets/wg0-router.yaml b/hosts/poweredge/resources/secrets/wg0-router.yaml new file mode 100644 index 0000000..647039d --- /dev/null +++ b/hosts/poweredge/resources/secrets/wg0-router.yaml @@ -0,0 +1,16 @@ +wg0-router: ENC[AES256_GCM,data:MGgB2vdRHgLlFjqB8miSE4myIGWdZazsvDfNUvYS7fM57NM6fzylHz1zle3nwNIysclPCQt9PSZqAJUkdZ5d0ocMhsnbpL9iKBiTHtqdl0KfDkKctWxi8sr3NqNPkW9uJD26aDA8Ti3OWM3JFIyxUb9KT53nZZLHpwpcygeEbfYMMTpKbUf68gMAClvYDg0mHwxVYbZT6aLqZewORBT1JkEPClone00YXizedWGzMsJ/p6b6mQz/HfbEdfq95EWTKSkHRYLPosXCikrJ6VV+uQt0dNS/Gqe0vfocYQUqcK9dt37n7q40Fh2oJgPwMsTj7lTJiAE87GqmpGuRsfbSF+Fr2pu4RRbm9iulzy13PcdrRPrjSKtM6oh/d13T7Yv8MJQTZDNWWsG9ApCXLqH8mF6pFckEtrWSB0sQQEt9ITkIs82t0kwgGh/fsig0cQ==,iv:AX2lb8By/hL5EWodLqGq8KvymkRyytZSGBpvydvBQcU=,tag:iadygaObGVNzvihxbtQRtw==,type:str] +sops: + age: + - recipient: age1zfvmt2avdlfz0fvchczplc84u7m8vqausm7zytl9s4x9m9yax4cqy30zpz + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxOFFVRFl2MDhiUVRPdnZJ + b3BSZ0pSaG8vR3o3SGlmVENvN3ZObHU3eUc4CmJrdk8rbXpBMWhTZ2hvdlk0VWo1 + ejdnTDR4bFlUUXc4Smd0NEp6b3crZFUKLS0tIFBsQUdRWjZLSDY1ZlFaRDdLOVhs + MFFGY0NSU3NaK2U0U1NndUIyYm54ZWsKZ6q9j1fNaNSzBA0rbZYyUWt3U2V/7/9/ + FZTKd8mH/uCoxvK8unlVZ9uYNADRh2smp7LwK1AWie/6khAIFqVBeg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-06-13T18:52:56Z" + mac: ENC[AES256_GCM,data:s7zE/odQ1AAgAjeUGT1ROe/zGQWz2JP7jh04/sY87gQ8xfgG2PJVlsyW1dZvzHesAf/1UqCaY9rYhZ4xo/GN8JTo2P9QqX38Mg/YNPk+GSpZ4TMGpxBHqb1DOPkDWvE9K43bm35GHluDBA7aOjkqMT9VaQHvYtHS+vLsdiGtyFw=,iv:javBbSBq3qkF25iLZgHthfS/OFDH6DTsnGNmIR/LrN4=,tag:Zs7ckugLHY/cjCWTaImzSg==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.1 diff --git a/hosts/poweredge/resources/secrets/wg1.yaml b/hosts/poweredge/resources/secrets/wg1.yaml deleted file mode 100644 index 6610514..0000000 --- a/hosts/poweredge/resources/secrets/wg1.yaml +++ /dev/null @@ -1,16 +0,0 @@ -wg1: ENC[AES256_GCM,data:1IySjV57HcywgiCZ/ZYbcr4Y9EbLrb6bE4kpG1DmDsLiRVFSfZA1UOoMGosot+7YiuE4xfZNHGSnzDrpE73gi5E9qYlvjhOfyLq06a1lK7Q0Wo/QrH9eSH05h6SA4E8sE0w2aKY/6cWfLaXTP1d7xLJA1OOCy7y+wIXrHQcA/TI5XIxikFSe+tT7rhKz128u6MIGl8VWzCp4RmoN94MAgWp0RoVt0VSHlvNPTbMuTZI0YPN1NgHjcf7KWnit33GXydmAWr+wym/oxxdT77O6wMPcGIsxmMLOPNy3K1sTezGTPSS1CSVniKIIW2HYZepGfaTlKwBFIn7ctmMrBvqmMcHiW+QIPwWbOC8UWHJAGklv3vCa7Q8XDUKlOPNdS0o73jb+BVUJWerwR4ik6NPu/H/lWgIETg1pd/Qv//nGsPeGRIUFKyKxoL/5E67+pA==,iv:d+T6wKhV1i/2kae03VPLMaTFB2yleeDFPm1lrfjvkx8=,tag:h/41zAlfz6oBo8jqz9NW7A==,type:str] -sops: - age: - - recipient: age1zfvmt2avdlfz0fvchczplc84u7m8vqausm7zytl9s4x9m9yax4cqy30zpz - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxOFFVRFl2MDhiUVRPdnZJ - b3BSZ0pSaG8vR3o3SGlmVENvN3ZObHU3eUc4CmJrdk8rbXpBMWhTZ2hvdlk0VWo1 - ejdnTDR4bFlUUXc4Smd0NEp6b3crZFUKLS0tIFBsQUdRWjZLSDY1ZlFaRDdLOVhs - MFFGY0NSU3NaK2U0U1NndUIyYm54ZWsKZ6q9j1fNaNSzBA0rbZYyUWt3U2V/7/9/ - FZTKd8mH/uCoxvK8unlVZ9uYNADRh2smp7LwK1AWie/6khAIFqVBeg== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-31T02:00:52Z" - mac: ENC[AES256_GCM,data:VXBQSegpiLmT5pF0XVB8NTVzhn4QDE2WfVznANVdrXC4BqFYoQXscW+4BcMmwkUqz5MjeKNF4KgRwtpKWVyRXG7EXVEGeA/NdysAxM9eSD4YrQZLqWzG8UKStyFG7jgHw/YA3H94hJ3rYnhsA9Kb3DHEmnQSZskTOmn2ppyUunQ=,iv:/rVWmaXl149Prhv35wBDZN6c+HgQ6PYSb8RIE30t7MI=,tag:SZ7mI9XDsIjhliFyWO14ug==,type:str] - unencrypted_suffix: _unencrypted - version: 3.12.1 diff --git a/hosts/poweredge/router-hosts.nix b/hosts/poweredge/router-hosts.nix new file mode 100644 index 0000000..007d2d7 --- /dev/null +++ b/hosts/poweredge/router-hosts.nix @@ -0,0 +1,71 @@ +let + localDomain = "home.lan"; + dhcp = { + inherit staticLeases; + defaultGateway = "192.168.1.1"; + localhostIp = "192.168.1.1"; + rangeStart = "192.168.1.50"; + rangeEnd = "192.168.1.250"; + }; + staticLeases = { + # Network + idrac-7N94GK2 = { + macAddress = "50:9a:4c:5d:c3:7c"; + staticIp = "192.168.1.2"; + }; + OpenWrt-Attic = { + macAddress = "34:98:b5:60:5e:be"; + staticIp = "192.168.1.3"; + }; + OpenWrt-Basement = { + macAddress = "8c:3b:ad:35:c7:8c"; + staticIp = "192.168.1.4"; + }; + ArcherC54 = { + macAddress = "12:eb:b6:13:f9:e2"; + staticIp = "192.168.1.5"; + }; + # Desktops + T495 = { + macAddress = "04:33:c2:9d:34:74"; + staticIp = "192.168.1.11"; + }; + optiplex = { + macAddress = "e4:54:e8:bc:ba:05"; + staticIp = "192.168.1.12"; + }; + X230 = { + macAddress = "84:3a:4b:60:34:c4"; + staticIp = "192.168.1.13"; + }; + # Services + gnuslashprinter = { + macAddress = "00:23:24:5b:f0:6d"; + staticIp = "192.168.1.40"; + }; + immich = { + macAddress = "02:00:00:00:00:01"; + staticIp = "192.168.1.41"; + }; + jellyfin = { + macAddress = "02:00:00:00:00:02"; + staticIp = "192.168.1.42"; + }; + gitea = { + macAddress = "02:00:00:00:00:03"; + staticIp = "192.168.1.43"; + }; + bitcoind = { + macAddress = "02:00:00:00:00:04"; + staticIp = "192.168.1.44"; + }; + }; + dns.hostOverrides = { + "router.${localDomain}" = "192.168.1.1"; + "poweredge.${localDomain}" = "192.168.1.10"; + }; +in { + services._router.dnsDhcpConfig = { + inherit localDomain dhcp dns; + }; +} diff --git a/hosts/poweredge/transmission.nix b/hosts/poweredge/transmission.nix new file mode 100644 index 0000000..11a673e --- /dev/null +++ b/hosts/poweredge/transmission.nix @@ -0,0 +1,48 @@ +{ + containers.transmission-wg = let + home = "/var/lib/transmission"; + download-dir = "${home}/complete"; + incomplete-dir = "${home}/incomplete"; + wg-conf = "${home}/wg0.conf"; + in { + autoStart = true; + privateNetwork = false; # TODO + enableTun = true; + bindMounts = { + "${download-dir}" = { + hostPath = ""; # FIXME + isReadOnly = false; + }; + "${incomplete-dir}" = { + hostPath = ""; # FIXME + isReadOnly = false; + }; + }; + + config = { lib, config, ... }: { + services.transmission = { + inherit home; + enable = true; + + settings = { + inherit download-dir incomplete-dir; + rpc-bind-address = "0.0.0.0"; + rpc-whitelist = "*"; + rpc-whitelist-enable = false; + }; + }; + + #networking.wg-quick.interfaces = { + # wg0.configFile = wg-conf; + #}; + + # TODO remove (#258793) + systemd.services.transmission.serviceConfig = { + RootDirectoryStartOnly = lib.mkForce null; + RootDirectory = lib.mkForce null; + }; + + system.stateVersion = "25.11"; + }; + }; +} diff --git a/hosts/poweredge/wg1.nix b/hosts/poweredge/wg1.nix deleted file mode 100644 index d94efb6..0000000 --- a/hosts/poweredge/wg1.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ config, pkgs, inputs, ... }: { - sops.secrets.wg1.sopsFile = ./resources/secrets/wg1.yaml; - - networking.wg-quick.interfaces = { - wg1.configFile = config.sops.secrets.wg1.path; - }; -} diff --git a/nixos/default.nix b/nixos/default.nix index 2449a5f..ff7713e 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -7,14 +7,10 @@ ./services/cgit.nix ./services/fileshares.nix ./services/gitea.nix - ./services/immich.nix - ./services/jellyfin.nix ./services/mailer.nix ./services/searxng.nix - ./services/router/dns-dhcp.nix - ./services/router/routing.nix - ./services/router/unbound-blocklist.nix ./services/zfs/zed-mailer.nix + ./services/router #./services/mainsail.nix diff --git a/nixos/services/immich.nix b/nixos/services/immich.nix deleted file mode 100644 index f9b17d5..0000000 --- a/nixos/services/immich.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ lib, pkgs, config, ... }: let - cfg = config.services._immich; -in { - options.services._immich = { - enable = lib.mkEnableOption "enables immich service"; - mediaLocationHostPath = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "host path to the media location"; - default = null; - }; - }; - - config = lib.mkIf cfg.enable { - containers.immich = { - autoStart = true; - privateNetwork = false; - bindMounts = { - "/var/lib/immich" = lib.mkIf (cfg.mediaLocationHostPath != null) { - hostPath = cfg.mediaLocationHostPath; - isReadOnly = false; - }; - }; - - config = { lib, config, ... }: { - services.immich = { - enable = true; - host = "0.0.0.0"; - }; - - environment.systemPackages = with pkgs; [ immich immich-cli ]; - - system.stateVersion = "25.11"; - }; - }; - }; -} diff --git a/nixos/services/jellyfin.nix b/nixos/services/jellyfin.nix deleted file mode 100644 index 8d04278..0000000 --- a/nixos/services/jellyfin.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ lib, pkgs, config, ... }: let - cfg = config.services._jellyfin; -in { - options.services._jellyfin = { - enable = lib.mkEnableOption "enables jellyfin service"; - mediaLocationHostPath = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "host path to the media location"; - default = null; - }; - }; - - config = lib.mkIf cfg.enable { - containers.jellyfin = { - autoStart = true; - privateNetwork = false; - bindMounts = { - "/media" = lib.mkIf (cfg.mediaLocationHostPath != null) { - hostPath = cfg.mediaLocationHostPath; - isReadOnly = true; - }; - }; - - config = { lib, config, ... }: { - services.jellyfin = { - enable = true; - }; - - system.stateVersion = "25.11"; - }; - }; - }; -} diff --git a/nixos/services/router/blocklists.nix b/nixos/services/router/blocklists.nix new file mode 100644 index 0000000..753dd68 --- /dev/null +++ b/nixos/services/router/blocklists.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: let + cfg = config.services._router.dnsDhcpConfig.blocklists; + hageziList = list: [ + "https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/rpz/${list}.txt" + "https://gitlab.com/hagezi/mirror/-/raw/main/dns-blocklists/rpz/${list}.txt" + "https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/rpz/${list}.txt" + ]; + mkHageziLists = lib.listToAttrs ( + map (n: { name = "hagezi_${n}"; value = n; }) cfg.hageziBlocklists + ); +in { + options.services._router.dnsDhcpConfig.blocklists = { + enable = lib.mkEnableOption "enable unbound blocklists"; + hageziBlocklists = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "hagezi blocklists to enable"; + example = [ "pro" "nsfw" ]; + }; + extraBlocklists = lib.mkOption { + type = lib.types.attrsOf (lib.types.listOf lib.types.str); + description = "additional rpz blocklists to enable"; + }; + }; + config = lib.mkIf cfg.enable { + services.unbound = { + _blocklists = { + enable = true; + blocklists = lib.map { + hageziNSFW = hageziList "nsfw"; + hageziPro = hageziList "pro"; + } // cfg.extraBlocklists; + }; + }; + }; +} diff --git a/nixos/services/router/default.nix b/nixos/services/router/default.nix new file mode 100644 index 0000000..6ccb999 --- /dev/null +++ b/nixos/services/router/default.nix @@ -0,0 +1,8 @@ +{ + imports = [ + ./blocklists.nix + ./dns-dhcp.nix + ./routing.nix + ./unbound-blocklist.nix + ]; +} diff --git a/nixos/services/router/dns-dhcp.nix b/nixos/services/router/dns-dhcp.nix index 4c041c2..1839b0f 100644 --- a/nixos/services/router/dns-dhcp.nix +++ b/nixos/services/router/dns-dhcp.nix @@ -27,6 +27,18 @@ in { options.services._router.dnsDhcpConfig = { enable = lib.mkEnableOption "enable pre-configured unbound(outbound) + dnsmasq(local) dns(+dhcp) server"; #enableUnbound = lib.mkEnableOption "enable unbound as outbound dns server"; + dns = { + hostOverrides = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = {}; + example = { + "poweredge.home.lan" = "192.168.1.10"; + "router.home.lan" = "192.168.1.1"; + "example.com" = "192.168.1.100"; + }; + description = "dns overrides for specific hosts"; + }; + }; dhcp = { defaultGateway = lib.mkOption { type = lib.types.str; @@ -162,6 +174,8 @@ in { services.dnsmasq = { enable = true; settings = let + mkDNSHostOverride = host: ip: "${host},${ip}"; + dnsHostOverrides = lib.mapAttrsToList (host: ip: mkDNSHostOverride host ip) cfg.dns.hostOverrides; mkDHCPRange = ipRangeStart: ipRangeEnd: subnetMask: leaseTime: "${ipRangeStart},${ipRangeEnd},${subnetMask},${leaseTime}"; mkDHCPOption = option: value: "option:${option},${value}"; mkDHCPStaticLease = macAddress: hostname: staticIp: "${macAddress},${hostname},${staticIp},infinite"; @@ -178,6 +192,8 @@ in { # DNS Server port = 5353; # Use port 5353 for DNS server since unbound is the main DNS resolver + host-record = dnsHostOverrides; # Setup host overrides for dns + # DHCP Server # TODO config #dhcp-range = mkDHCPRange "192.168.1.50" "192.168.1.150" "255.255.255.0" "12h"; # Enable DHCP on the LAN interface @@ -192,6 +208,8 @@ in { (mkDHCPOption "domain-search" cfg.localDomain) # Add search rule to clients so they can resolve hostnames w/o the local domain suffix ]; + #dhcp-no-override = true; # don't use kernel DHCP helpers that bypass macvlan + # Logging #log-dhcp = true; # Log DHCP events #log-queries = true; # Log DNS queries diff --git a/nixos/services/router/routing.nix b/nixos/services/router/routing.nix index 6682538..9534081 100644 --- a/nixos/services/router/routing.nix +++ b/nixos/services/router/routing.nix @@ -9,11 +9,10 @@ in { default = ""; description = "wan interface"; }; - # TODO allow multiple lan lan = lib.mkOption { - type = lib.types.str; + type = lib.types.listOf lib.types.str; default = ""; - description = "lan interface"; + description = "lan interfaces"; }; }; }; @@ -26,18 +25,18 @@ in { enable = true; backend = "nftables"; # Set explicitly - # Allow lan to access the router - trustedInterfaces = [ cfg.interfaces.lan ]; + # Allow lan interfaces to access the router + trustedInterfaces = cfg.interfaces.lan; - # Allow lan to access the internet - extraForwardRules = '' - iifname "${cfg.interfaces.lan}" oifname "${cfg.interfaces.wan}" accept - ''; + # Allow lan interfaces to access the internet + extraForwardRules = lib.concatMapStrings (lanIf: '' + iifname "${lanIf}" oifname "${cfg.interfaces.wan}" accept + '') cfg.interfaces.lan; }; nat = { enable = lib.mkDefault true; externalInterface = lib.mkDefault cfg.interfaces.wan; - internalInterfaces = lib.mkDefault [ cfg.interfaces.lan ]; + internalInterfaces = lib.mkDefault cfg.interfaces.lan; }; }; }; |
