summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archetypes/profiles/default.nix1
-rw-r--r--archetypes/profiles/router/default.nix37
-rw-r--r--hosts/poweredge/bitcoind.nix35
-rw-r--r--hosts/poweredge/configuration.nix34
-rw-r--r--hosts/poweredge/gitea.nix32
-rw-r--r--hosts/poweredge/immich.nix60
-rw-r--r--hosts/poweredge/jellyfin.nix68
-rw-r--r--hosts/poweredge/networking.nix175
-rw-r--r--hosts/poweredge/resources/secrets/wg0-router.yaml16
-rw-r--r--hosts/poweredge/resources/secrets/wg1.yaml16
-rw-r--r--hosts/poweredge/router-hosts.nix71
-rw-r--r--hosts/poweredge/transmission.nix48
-rw-r--r--hosts/poweredge/wg1.nix7
-rw-r--r--nixos/default.nix6
-rw-r--r--nixos/services/immich.nix36
-rw-r--r--nixos/services/jellyfin.nix33
-rw-r--r--nixos/services/router/blocklists.nix35
-rw-r--r--nixos/services/router/default.nix8
-rw-r--r--nixos/services/router/dns-dhcp.nix18
-rw-r--r--nixos/services/router/routing.nix19
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;
};
};
};