declared network.nix

This commit is contained in:
Danilo Reyes
2026-04-02 00:22:39 -06:00
parent 78c37081d7
commit 29a88a9b05
17 changed files with 390 additions and 359 deletions

View File

@@ -2,6 +2,7 @@
{
imports = [
./hardware-configuration.nix
./network.nix
../../config/base.nix
../../config/stylix.nix
];
@@ -31,13 +32,7 @@
(buildMachine "workstation" 8 40)
(buildMachine "server" 6 17)
];
networking = {
hostName = "miniserver";
firewall = {
allowedTCPPorts = [ 2049 ];
allowedUDPPorts = [ 2049 ];
};
};
networking.hostName = "miniserver";
services = {
btrfs.autoScrub = {
enable = true;

View File

@@ -0,0 +1,6 @@
_: {
networking.firewall = {
allowedTCPPorts = [ 2049 ];
allowedUDPPorts = [ 2049 ];
};
}

View File

@@ -7,16 +7,12 @@
}:
let
lidarrMbGapId = 968;
qbittorrentRouteTable = 200;
qbitUser = config.services.qbittorrent.user;
serverInterface = config.my.interfaces.server;
wgInterface = "wg0";
wgServerIp = config.my.ips.wg-server;
in
{
imports = [
inputs.lidarr-mb-gap.nixosModules.lidarr-mb-gap
./hardware-configuration.nix
./network.nix
../../config/base.nix
../../config/stylix.nix
];
@@ -29,19 +25,6 @@ in
"nixminiserver"
];
};
network.firewall = {
enabledServicePorts = true;
additionalPorts = [
2049
config.my.ports.syncthingGui
config.my.ports.syncthingRelay
config.my.ports.sonarqube
config.my.ports.synapseSsl
config.my.ports.tdarr
config.my.ports.mediaMap
config.my.ports.qbittorrent
];
};
};
nix.buildMachines = [
{
@@ -73,114 +56,7 @@ in
path = "${usr.home}/.ssh/ed25519_lidarr-mb-gap";
};
};
networking = {
hostName = "server";
iproute2.rttablesExtraConfig = ''
${toString qbittorrentRouteTable} qbittorrent
'';
wireguard.interfaces.${wgInterface} = lib.mkIf config.my.secureHost {
allowedIPsAsRoutes = false;
ips = [ "${wgServerIp}/32" ];
privateKeyFile = config.sops.secrets."server/private".path;
peers = [
{
publicKey = "dFbiSekBwnZomarcS31o5+w6imHjMPNCipkfc2fZ3GY=";
endpoint = "${config.my.ips.vps}:51820";
allowedIPs = [
"0.0.0.0/0"
"${config.my.ips.wg-vps}/32"
config.my.subnets.wg-homelab
config.my.subnets.wg-friends
config.my.subnets.wg-guests
];
persistentKeepalive = 25;
}
];
};
firewall = {
allowedUDPPorts = config.networking.firewall.allowedTCPPorts;
interfaces.${wgInterface}.allowedTCPPorts = [ config.my.servers.nextcloud.port ];
};
};
systemd.services = {
qbittorrent-vpn-routing = lib.mkIf (config.my.secureHost && config.services.qbittorrent.enable) {
description = "Route qBittorrent user traffic through the VPS WireGuard tunnel";
before = [ "qbittorrent.service" ];
wantedBy = [ "multi-user.target" ];
after = [
"network-online.target"
"wireguard-${wgInterface}.service"
];
wants = [
"network-online.target"
"wireguard-${wgInterface}.service"
];
path = with pkgs; [
coreutils
gnugrep
iproute2
shadow
];
script = ''
qbit_uid="$(id -u ${qbitUser})"
for _ in $(seq 1 30); do
if ip -4 addr show dev ${wgInterface} >/dev/null 2>&1; then
break
fi
sleep 1
done
if ! ip -4 addr show dev ${wgInterface} >/dev/null 2>&1; then
echo "${wgInterface} is not available"
exit 1
fi
ip -4 route replace ${config.my.subnets.wg-homelab} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace ${config.my.subnets.wg-friends} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace ${config.my.subnets.wg-guests} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-homelab} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-friends} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-guests} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} 10.88.0.0/16 dev podman0 src 10.88.0.1
ip -4 route replace table ${toString qbittorrentRouteTable} 192.168.100.0/24 dev ${serverInterface} src ${config.my.ips.server}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.ips.vps}/32 via ${config.my.ips.router} dev ${serverInterface} src ${config.my.ips.server}
ip -4 route replace table ${toString qbittorrentRouteTable} default via ${config.my.ips.wg-vps} dev ${wgInterface} src ${wgServerIp}
while ip -4 rule show | grep -q "uidrange ''${qbit_uid}-''${qbit_uid} lookup ${toString qbittorrentRouteTable}"; do
ip -4 rule del uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable}
done
while ip -4 rule show | grep -q 'from ${wgServerIp} lookup ${toString qbittorrentRouteTable}'; do
ip -4 rule del from ${wgServerIp}/32 lookup ${toString qbittorrentRouteTable}
done
ip -4 rule add from ${wgServerIp}/32 lookup ${toString qbittorrentRouteTable} priority 9999
ip -4 rule add uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable} priority 10000
'';
preStop = ''
qbit_uid="$(id -u ${qbitUser})"
while ip -4 rule show | grep -q 'from ${wgServerIp} lookup ${toString qbittorrentRouteTable}'; do
ip -4 rule del from ${wgServerIp}/32 lookup ${toString qbittorrentRouteTable} || true
done
while ip -4 rule show | grep -q "uidrange ''${qbit_uid}-''${qbit_uid} lookup ${toString qbittorrentRouteTable}"; do
ip -4 rule del uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable} || true
done
ip -4 route del ${config.my.subnets.wg-homelab} dev ${wgInterface} || true
ip -4 route del ${config.my.subnets.wg-friends} dev ${wgInterface} || true
ip -4 route del ${config.my.subnets.wg-guests} dev ${wgInterface} || true
ip -4 route flush table ${toString qbittorrentRouteTable} || true
'';
serviceConfig = {
RemainAfterExit = true;
Type = "oneshot";
};
};
};
networking.hostName = "server";
users = {
groups.lidarr-mb-gap.gid = lidarrMbGapId;
users = {

135
hosts/server/network.nix Normal file
View File

@@ -0,0 +1,135 @@
{
config,
lib,
pkgs,
...
}:
let
qbittorrentRouteTable = 200;
qbitUser = config.services.qbittorrent.user;
serverInterface = config.my.interfaces.server;
wgInterface = "wg0";
wgServerIp = config.my.ips.wg-server;
in
{
my.network.firewall = {
enabledServicePorts = true;
additionalPorts = [
2049
config.my.ports.syncthingGui
config.my.ports.syncthingRelay
config.my.ports.sonarqube
config.my.ports.synapseSsl
config.my.ports.tdarr
config.my.ports.mediaMap
config.my.ports.qbittorrent
];
};
networking = {
iproute2.rttablesExtraConfig = ''
${toString qbittorrentRouteTable} qbittorrent
'';
wireguard.interfaces.${wgInterface} = lib.mkIf config.my.secureHost {
allowedIPsAsRoutes = false;
ips = [ "${wgServerIp}/32" ];
privateKeyFile = config.sops.secrets."server/private".path;
peers = [
{
publicKey = "dFbiSekBwnZomarcS31o5+w6imHjMPNCipkfc2fZ3GY=";
endpoint = "${config.my.ips.vps}:51820";
allowedIPs = [
"0.0.0.0/0"
"${config.my.ips.wg-vps}/32"
config.my.subnets.wg-homelab
config.my.subnets.wg-friends
config.my.subnets.wg-guests
];
persistentKeepalive = 25;
}
];
};
firewall = {
allowedUDPPorts = config.networking.firewall.allowedTCPPorts;
interfaces.${wgInterface}.allowedTCPPorts = [ config.my.servers.nextcloud.port ];
};
};
systemd.services.qbittorrent-vpn-routing =
lib.mkIf (config.my.secureHost && config.services.qbittorrent.enable)
{
description = "Route qBittorrent user traffic through the VPS WireGuard tunnel";
before = [ "qbittorrent.service" ];
wantedBy = [ "multi-user.target" ];
after = [
"network-online.target"
"wireguard-${wgInterface}.service"
];
wants = [
"network-online.target"
"wireguard-${wgInterface}.service"
];
path = with pkgs; [
coreutils
gnugrep
iproute2
shadow
];
script = ''
qbit_uid="$(id -u ${qbitUser})"
for _ in $(seq 1 30); do
if ip -4 addr show dev ${wgInterface} >/dev/null 2>&1; then
break
fi
sleep 1
done
if ! ip -4 addr show dev ${wgInterface} >/dev/null 2>&1; then
echo "${wgInterface} is not available"
exit 1
fi
ip -4 route replace ${config.my.subnets.wg-homelab} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace ${config.my.subnets.wg-friends} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace ${config.my.subnets.wg-guests} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-homelab} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-friends} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-guests} dev ${wgInterface} src ${wgServerIp}
ip -4 route replace table ${toString qbittorrentRouteTable} 10.88.0.0/16 dev podman0 src 10.88.0.1
ip -4 route replace table ${toString qbittorrentRouteTable} 192.168.100.0/24 dev ${serverInterface} src ${config.my.ips.server}
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.ips.vps}/32 via ${config.my.ips.router} dev ${serverInterface} src ${config.my.ips.server}
ip -4 route replace table ${toString qbittorrentRouteTable} default via ${config.my.ips.wg-vps} dev ${wgInterface} src ${wgServerIp}
while ip -4 rule show | grep -q "uidrange ''${qbit_uid}-''${qbit_uid} lookup ${toString qbittorrentRouteTable}"; do
ip -4 rule del uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable}
done
while ip -4 rule show | grep -q 'from ${wgServerIp} lookup ${toString qbittorrentRouteTable}'; do
ip -4 rule del from ${wgServerIp}/32 lookup ${toString qbittorrentRouteTable}
done
ip -4 rule add from ${wgServerIp}/32 lookup ${toString qbittorrentRouteTable} priority 9999
ip -4 rule add uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable} priority 10000
'';
preStop = ''
qbit_uid="$(id -u ${qbitUser})"
while ip -4 rule show | grep -q 'from ${wgServerIp} lookup ${toString qbittorrentRouteTable}'; do
ip -4 rule del from ${wgServerIp}/32 lookup ${toString qbittorrentRouteTable} || true
done
while ip -4 rule show | grep -q "uidrange ''${qbit_uid}-''${qbit_uid} lookup ${toString qbittorrentRouteTable}"; do
ip -4 rule del uidrange "''${qbit_uid}-''${qbit_uid}" lookup ${toString qbittorrentRouteTable} || true
done
ip -4 route del ${config.my.subnets.wg-homelab} dev ${wgInterface} || true
ip -4 route del ${config.my.subnets.wg-friends} dev ${wgInterface} || true
ip -4 route del ${config.my.subnets.wg-guests} dev ${wgInterface} || true
ip -4 route flush table ${toString qbittorrentRouteTable} || true
'';
serviceConfig = {
RemainAfterExit = true;
Type = "oneshot";
};
};
}

View File

@@ -5,87 +5,10 @@
inputs,
...
}:
let
externalInterface = config.my.interfaces.${config.networking.hostName};
wgInterface = "wg0";
ips = {
homeServer = config.my.ips.wg-server;
wgWorkstation = config.my.ips.wg-workstation;
wgFriend1 = config.my.ips.wg-friend1;
wgFriend6 = config.my.ips.wg-friend6;
wgGuest1 = config.my.ips.wg-guest1;
wgGuest2 = config.my.ips.wg-guest2;
};
subnets = {
wgFriends = config.my.subnets.wg-friends;
wgGuests = config.my.subnets.wg-guests;
wgHomelab = config.my.subnets.wg-homelab;
};
ports = {
inherit (config.my.ports)
giteaSsh
qbittorrent
ssh
wg
;
web = [
80
443
];
syncthing = config.my.ports.syncthingRelay;
synapseFederation = config.my.ports.synapseSsl;
};
portsStr = {
syncthing = toString ports.syncthing;
synapseFederation = toString ports.synapseFederation;
synapseClient = toString config.my.servers.synapse.port;
syncplay = toString config.my.servers.syncplay.port;
synctube = toString config.my.servers.synctube.port;
stash = toString config.my.servers.stash.port;
jellyfin = toString config.my.servers.jellyfin.port;
audiobookshelf = toString config.my.servers.audiobookshelf.port;
kavita = toString config.my.servers.kavita.port;
openWebui = toString config.my.ports.openWebui;
sillytavern = toString config.my.ports.sillytavern;
ollama = toString config.my.ports.ollama;
comfyui = toString config.my.ports.comfyui;
};
forwardedPorts = [
{
comment = "snat ssh forward";
port = ports.giteaSsh;
proto = "tcp";
}
{
comment = "snat qbittorrent tcp forward";
port = ports.qbittorrent;
proto = "tcp";
}
{
comment = "snat qbittorrent udp forward";
port = ports.qbittorrent;
proto = "udp";
}
];
mkForwardPort =
{ port, proto, ... }:
{
sourcePort = port;
inherit proto;
destination = "${ips.homeServer}:${toString port}";
};
mkSnatRule =
{
comment,
port,
proto,
...
}:
''iifname "${externalInterface}" oifname "${wgInterface}" ip daddr ${ips.homeServer}/32 ${proto} dport ${toString port} masquerade comment "${comment}"'';
in
{
imports = [
./hardware-configuration.nix
./network.nix
./nginx-nextcloud.nix
../../config/base.nix
];
@@ -128,72 +51,10 @@ in
keyFile = "/var/lib/sops-nix/key.txt";
sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
};
networking = {
hostName = "vps";
nat = {
inherit externalInterface;
enable = true;
internalInterfaces = [ wgInterface ];
forwardPorts = map mkForwardPort forwardedPorts;
};
nftables = {
enable = true;
tables.vps-snat = {
family = "ip";
content = ''
chain postrouting {
type nat hook postrouting priority srcnat;
iifname "${wgInterface}" oifname "${externalInterface}" ip saddr ${subnets.wgHomelab} masquerade comment "snat homelab egress"
${lib.concatStringsSep "\n " (map mkSnatRule forwardedPorts)}
}
'';
};
};
firewall = {
enable = true;
filterForward = true;
checkReversePath = "loose";
allowedTCPPorts = [
ports.ssh
ports.qbittorrent
]
++ ports.web;
allowedUDPPorts = [
ports.wg
ports.qbittorrent
];
extraForwardRules = ''
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.syncthing} accept
iifname "${wgInterface}" ip saddr ${ips.homeServer}/32 ip daddr ${subnets.wgFriends} tcp dport ${portsStr.syncthing} accept
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 tcp dport { ${portsStr.synapseClient}, ${portsStr.synapseFederation}, ${portsStr.syncplay}, ${portsStr.synctube} } accept
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 icmp type echo-request accept
iifname "${wgInterface}" ip saddr ${ips.wgFriend1}/32 ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.stash} accept
iifname "${wgInterface}" ip saddr ${ips.wgFriend6}/32 ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.stash} accept
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} ip daddr ${ips.homeServer}/32 tcp dport { ${portsStr.stash}, ${portsStr.jellyfin}, ${portsStr.audiobookshelf}, ${portsStr.kavita} } accept
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} ip daddr ${ips.homeServer}/32 icmp type echo-request accept
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} ip daddr ${ips.homeServer}/32 accept
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} ip daddr ${ips.wgWorkstation}/32 tcp dport { ${portsStr.openWebui}, ${portsStr.sillytavern}, ${portsStr.ollama}, ${portsStr.comfyui} } accept
iifname "${wgInterface}" ip saddr ${ips.wgWorkstation}/32 ip daddr ${subnets.wgHomelab} tcp sport { ${portsStr.openWebui}, ${portsStr.sillytavern}, ${portsStr.ollama}, ${portsStr.comfyui} } accept
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} oifname "${externalInterface}" accept
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} oifname "${externalInterface}" accept
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} oifname "${externalInterface}" accept
ip saddr ${subnets.wgFriends} ip daddr ${subnets.wgHomelab} drop
ip saddr ${subnets.wgHomelab} ip daddr ${subnets.wgFriends} drop
ip saddr ${subnets.wgGuests} ip daddr ${subnets.wgHomelab} drop
ip saddr ${subnets.wgHomelab} ip daddr ${subnets.wgGuests} drop
ip saddr ${subnets.wgGuests} ip daddr ${subnets.wgFriends} drop
ip saddr ${subnets.wgFriends} ip daddr ${subnets.wgGuests} drop
'';
};
};
networking.hostName = "vps";
services = {
smartd.enable = lib.mkForce false;
openssh.ports = [ ports.ssh ];
openssh.ports = [ config.my.ports.ssh ];
};
users = {
groups = {

145
hosts/vps/network.nix Normal file
View File

@@ -0,0 +1,145 @@
{
config,
lib,
...
}:
let
externalInterface = config.my.interfaces.${config.networking.hostName};
wgInterface = "wg0";
ips = {
homeServer = config.my.ips.wg-server;
wgWorkstation = config.my.ips.wg-workstation;
wgFriend1 = config.my.ips.wg-friend1;
wgFriend6 = config.my.ips.wg-friend6;
};
subnets = {
wgFriends = config.my.subnets.wg-friends;
wgGuests = config.my.subnets.wg-guests;
wgHomelab = config.my.subnets.wg-homelab;
};
ports = {
inherit (config.my.ports)
giteaSsh
qbittorrent
ssh
wg
;
web = [
80
443
];
syncthing = config.my.ports.syncthingRelay;
synapseFederation = config.my.ports.synapseSsl;
};
portsStr = {
syncthing = toString config.my.ports.syncthingRelay;
synapseFederation = toString config.my.ports.synapseSsl;
synapseClient = toString config.my.servers.synapse.port;
syncplay = toString config.my.servers.syncplay.port;
synctube = toString config.my.servers.synctube.port;
stash = toString config.my.servers.stash.port;
jellyfin = toString config.my.servers.jellyfin.port;
audiobookshelf = toString config.my.servers.audiobookshelf.port;
kavita = toString config.my.servers.kavita.port;
openWebui = toString config.my.ports.openWebui;
sillytavern = toString config.my.ports.sillytavern;
ollama = toString config.my.ports.ollama;
comfyui = toString config.my.ports.comfyui;
};
forwardedPorts = [
{
comment = "snat ssh forward";
port = ports.giteaSsh;
proto = "tcp";
}
{
comment = "snat qbittorrent tcp forward";
port = ports.qbittorrent;
proto = "tcp";
}
{
comment = "snat qbittorrent udp forward";
port = ports.qbittorrent;
proto = "udp";
}
];
mkForwardPort =
{ port, proto, ... }:
{
sourcePort = port;
inherit proto;
destination = "${ips.homeServer}:${toString port}";
};
mkSnatRule =
{
comment,
port,
proto,
...
}:
''iifname "${externalInterface}" oifname "${wgInterface}" ip daddr ${ips.homeServer}/32 ${proto} dport ${toString port} masquerade comment "${comment}"'';
in
{
networking = {
nat = {
inherit externalInterface;
enable = true;
internalInterfaces = [ wgInterface ];
forwardPorts = map mkForwardPort forwardedPorts;
};
nftables = {
enable = true;
tables.vps-snat = {
family = "ip";
content = ''
chain postrouting {
type nat hook postrouting priority srcnat;
iifname "${wgInterface}" oifname "${externalInterface}" ip saddr ${subnets.wgHomelab} masquerade comment "snat homelab egress"
${lib.concatStringsSep "\n " (map mkSnatRule forwardedPorts)}
}
'';
};
};
firewall = {
enable = true;
filterForward = true;
checkReversePath = "loose";
allowedTCPPorts = [
ports.ssh
ports.qbittorrent
]
++ ports.web;
allowedUDPPorts = [
ports.wg
ports.qbittorrent
];
extraForwardRules = ''
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.syncthing} accept
iifname "${wgInterface}" ip saddr ${ips.homeServer}/32 ip daddr ${subnets.wgFriends} tcp dport ${portsStr.syncthing} accept
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 tcp dport { ${portsStr.synapseClient}, ${portsStr.synapseFederation}, ${portsStr.syncplay}, ${portsStr.synctube} } accept
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 icmp type echo-request accept
iifname "${wgInterface}" ip saddr ${ips.wgFriend1}/32 ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.stash} accept
iifname "${wgInterface}" ip saddr ${ips.wgFriend6}/32 ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.stash} accept
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} ip daddr ${ips.homeServer}/32 tcp dport { ${portsStr.stash}, ${portsStr.jellyfin}, ${portsStr.audiobookshelf}, ${portsStr.kavita} } accept
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} ip daddr ${ips.homeServer}/32 icmp type echo-request accept
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} ip daddr ${ips.homeServer}/32 accept
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} ip daddr ${ips.wgWorkstation}/32 tcp dport { ${portsStr.openWebui}, ${portsStr.sillytavern}, ${portsStr.ollama}, ${portsStr.comfyui} } accept
iifname "${wgInterface}" ip saddr ${ips.wgWorkstation}/32 ip daddr ${subnets.wgHomelab} tcp sport { ${portsStr.openWebui}, ${portsStr.sillytavern}, ${portsStr.ollama}, ${portsStr.comfyui} } accept
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} oifname "${externalInterface}" accept
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} oifname "${externalInterface}" accept
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} oifname "${externalInterface}" accept
ip saddr ${subnets.wgFriends} ip daddr ${subnets.wgHomelab} drop
ip saddr ${subnets.wgHomelab} ip daddr ${subnets.wgFriends} drop
ip saddr ${subnets.wgGuests} ip daddr ${subnets.wgHomelab} drop
ip saddr ${subnets.wgHomelab} ip daddr ${subnets.wgGuests} drop
ip saddr ${subnets.wgGuests} ip daddr ${subnets.wgFriends} drop
ip saddr ${subnets.wgFriends} ip daddr ${subnets.wgGuests} drop
'';
};
};
}

View File

@@ -20,6 +20,7 @@ in
{
imports = [
./hardware-configuration.nix
./network.nix
../../config/base.nix
../../config/stylix.nix
../../environments/gnome.nix
@@ -55,51 +56,7 @@ in
settings.term = "xterm-256color";
};
};
networking = {
hostName = "workstation";
wireguard.interfaces.wg0 = lib.mkIf config.my.secureHost {
ips = [ "${config.my.ips.wg-workstation}/32" ];
privateKeyFile = config.sops.secrets."workstation/private".path;
peers = [
{
publicKey = "dFbiSekBwnZomarcS31o5+w6imHjMPNCipkfc2fZ3GY=";
endpoint = "${config.my.ips.vps}:51820";
persistentKeepalive = 25;
allowedIPs = [
"${config.my.ips.wg-vps}/32"
config.my.subnets.wg-homelab
];
}
];
};
firewall = {
allowedTCPPorts = [
config.my.ports.nsUsbloader
config.my.ports.syncthingGui
];
allowedTCPPortRanges = [
{
from = 1714;
to = 1764;
}
];
interfaces.wg0.allowedTCPPorts = [
config.services.ollama.port
config.services.open-webui.port
config.services.sillytavern.port
config.my.ports.comfyui
];
};
nftables.tables.wg-local-redirect = {
family = "ip";
content = ''
chain prerouting {
type nat hook prerouting priority dstnat;
iifname "wg0" ip daddr ${config.my.ips.wg-workstation}/32 tcp dport ${toString config.my.ports.sillytavern} redirect to :${toString config.my.ports.sillytavern}
}
'';
};
};
networking.hostName = "workstation";
users = {
groups.ai = { };
users.jawz.packages = [

View File

@@ -0,0 +1,55 @@
{
config,
lib,
...
}:
let
wgInterface = "wg0";
wgWorkstationIp = config.my.ips.wg-workstation;
in
{
networking = {
wireguard.interfaces.${wgInterface} = lib.mkIf config.my.secureHost {
ips = [ "${wgWorkstationIp}/32" ];
privateKeyFile = config.sops.secrets."workstation/private".path;
peers = [
{
publicKey = "dFbiSekBwnZomarcS31o5+w6imHjMPNCipkfc2fZ3GY=";
endpoint = "${config.my.ips.vps}:51820";
persistentKeepalive = 25;
allowedIPs = [
"${config.my.ips.wg-vps}/32"
config.my.subnets.wg-homelab
];
}
];
};
firewall = {
allowedTCPPorts = [
config.my.ports.nsUsbloader
config.my.ports.syncthingGui
];
allowedTCPPortRanges = [
{
from = 1714;
to = 1764;
}
];
interfaces.${wgInterface}.allowedTCPPorts = [
config.services.ollama.port
config.services.open-webui.port
config.services.sillytavern.port
config.my.ports.comfyui
];
};
nftables.tables.wg-local-redirect = {
family = "ip";
content = ''
chain prerouting {
type nat hook prerouting priority dstnat;
iifname "${wgInterface}" ip daddr ${wgWorkstationIp}/32 tcp dport ${toString config.my.ports.sillytavern} redirect to :${toString config.my.ports.sillytavern}
}
'';
};
};
}