6 Commits

Author SHA1 Message Date
3b71f4b1fd dedupe
All checks were successful
Check Flake / check-flake (push) Successful in 6m4s
2026-02-26 19:42:38 -08:00
dc3c2194ab use port 8080 instead
All checks were successful
Check Flake / check-flake (push) Successful in 3m21s
2026-02-26 00:26:49 -08:00
39009cbc18 use container hostname alias for script
All checks were successful
Check Flake / check-flake (push) Successful in 3m17s
2026-02-26 00:17:47 -08:00
3365a1652c restore port option 2026-02-26 00:16:39 -08:00
6466406975 fix transmission port forwarding
All checks were successful
Check Flake / check-flake (push) Successful in 3m25s
2026-02-26 00:08:40 -08:00
4eb0401263 disable services which don't work in nixos containers
All checks were successful
Check Flake / check-flake (push) Successful in 3m17s
2026-02-25 23:37:26 -08:00
6 changed files with 48 additions and 33 deletions

View File

@@ -96,7 +96,7 @@
{ groups = [ "wheel" ]; persist = true; }
];
nix.gc.automatic = true;
nix.gc.automatic = !config.boot.isContainer;
security.acme.acceptTerms = true;
security.acme.defaults.email = "zuckerberg@neet.dev";

View File

@@ -52,8 +52,13 @@ let
type = types.nullOr (types.submodule {
options = {
port = mkOption {
type = types.port;
description = "Target port to forward PIA-assigned port to";
type = types.nullOr types.port;
default = null;
description = ''
Target port to forward to. If null, forwards to the same PIA-assigned port.
PIA-assigned ports below 10000 are rejected to avoid accidentally
forwarding traffic to other services.
'';
};
protocol = mkOption {
type = types.enum [ "tcp" "udp" "both" ];

View File

@@ -135,6 +135,17 @@ in
echo "Loaded server info from $serverFile: $WG_HOSTNAME ($WG_SERVER_IP:$WG_SERVER_PORT)"
}
# Reset WG interface and tear down NAT/forwarding rules.
# Called on startup (clear stale state) and on exit via trap.
cleanupVpn() {
local interfaceName=$1
wg set "$interfaceName" listen-port 0 2>/dev/null || true
ip -4 address flush dev "$interfaceName" 2>/dev/null || true
ip route del default dev "$interfaceName" 2>/dev/null || true
iptables -t nat -F 2>/dev/null || true
iptables -F FORWARD 2>/dev/null || true
}
connectToServer() {
local wgFile=$1
local interfaceName=$2

View File

@@ -24,15 +24,16 @@ let
let
fwd = forwardingContainer.receiveForwardedPort;
targetIp = forwardingContainer.ip;
targetPort = toString fwd.port;
dnatTarget = if fwd.port != null then "${targetIp}:${toString fwd.port}" else targetIp;
targetPort = if fwd.port != null then toString fwd.port else "$PORT";
tcpRules = optionalString (fwd.protocol == "tcp" || fwd.protocol == "both") ''
echo "Setting up TCP DNAT: port $PORT ${targetIp}:${targetPort}"
iptables -t nat -A PREROUTING -i ${cfg.interfaceName} -p tcp --dport $PORT -j DNAT --to ${targetIp}:${targetPort}
iptables -t nat -A PREROUTING -i ${cfg.interfaceName} -p tcp --dport $PORT -j DNAT --to ${dnatTarget}
iptables -A FORWARD -i ${cfg.interfaceName} -d ${targetIp} -p tcp --dport ${targetPort} -j ACCEPT
'';
udpRules = optionalString (fwd.protocol == "udp" || fwd.protocol == "both") ''
echo "Setting up UDP DNAT: port $PORT ${targetIp}:${targetPort}"
iptables -t nat -A PREROUTING -i ${cfg.interfaceName} -p udp --dport $PORT -j DNAT --to ${targetIp}:${targetPort}
iptables -t nat -A PREROUTING -i ${cfg.interfaceName} -p udp --dport $PORT -j DNAT --to ${dnatTarget}
iptables -A FORWARD -i ${cfg.interfaceName} -d ${targetIp} -p udp --dport ${targetPort} -j ACCEPT
'';
onPortForwarded = optionalString (forwardingContainer.onPortForwarded != null) ''
@@ -43,9 +44,13 @@ let
'';
in
''
if [ "$PORT" -lt 10000 ]; then
echo "ERROR: PIA assigned low port $PORT (< 10000), refusing to set up DNAT" >&2
else
${tcpRules}
${udpRules}
${onPortForwarded}
fi
''
);
in
@@ -136,12 +141,8 @@ in
set -euo pipefail
${scripts.scriptCommon}
# Clean up stale state from previous attempts
wg set ${cfg.interfaceName} listen-port 0 2>/dev/null || true
ip -4 address flush dev ${cfg.interfaceName} 2>/dev/null || true
ip route del default dev ${cfg.interfaceName} 2>/dev/null || true
iptables -t nat -F 2>/dev/null || true
iptables -F FORWARD 2>/dev/null || true
trap 'cleanupVpn ${cfg.interfaceName}' EXIT
cleanupVpn ${cfg.interfaceName}
proxy="${proxy}"
@@ -195,16 +196,6 @@ in
exec sleep infinity
'';
preStop = ''
echo "Tearing down PIA VPN..."
ip -4 address flush dev ${cfg.interfaceName} 2>/dev/null || true
ip route del default dev ${cfg.interfaceName} 2>/dev/null || true
iptables -t nat -F POSTROUTING 2>/dev/null || true
iptables -F FORWARD 2>/dev/null || true
${optionalString portForwarding ''
iptables -t nat -F PREROUTING 2>/dev/null || true
''}
'';
};
# Port refresh timer (every 10 min) — keeps PIA port forwarding alive

View File

@@ -133,8 +133,15 @@ let
};
in
{
config = mkIf (cfg.enable && vmWorkspaces != { }) {
config = mkMerge [
(mkIf (cfg.enable && vmWorkspaces != { }) {
# Convert VM workspace configs to microvm.nix format
microvm.vms = mapAttrs mkVmConfig vmWorkspaces;
};
})
# microvm.nixosModules.host enables KSM, but /sys is read-only in containers
(mkIf config.boot.isContainer {
hardware.ksm.enable = false;
})
];
}

View File

@@ -63,17 +63,17 @@
ip = "10.100.0.10";
mounts."/var/lib".hostPath = "/var/lib";
mounts."/data/samba/Public".hostPath = "/data/samba/Public";
receiveForwardedPort = { port = 51413; protocol = "both"; };
receiveForwardedPort = { protocol = "both"; };
onPortForwarded = ''
# Notify Transmission of the PIA-assigned peer port via RPC
for i in $(seq 1 30); do
curlout=$(curl -s "http://$TARGET_IP:9091/transmission/rpc" 2>/dev/null) && break
curlout=$(curl -s "http://transmission.containers:8080/transmission/rpc" 2>/dev/null) && break
sleep 2
done
regex='X-Transmission-Session-Id: (\w*)'
if [[ $curlout =~ $regex ]]; then
sessionId=''${BASH_REMATCH[1]}
curl -s "http://$TARGET_IP:9091/transmission/rpc" \
curl -s "http://transmission.containers:8080/transmission/rpc" \
-d "{\"method\":\"session-set\",\"arguments\":{\"peer-port\":$PORT}}" \
-H "X-Transmission-Session-Id: $sessionId"
fi
@@ -91,6 +91,7 @@
"incomplete-dir-enabled" = true;
"rpc-enabled" = true;
"rpc-port" = 8080;
"rpc-bind-address" = "0.0.0.0";
"rpc-whitelist" = "127.0.0.1,10.100.*.*,192.168.*.*";
"rpc-host-whitelist-enabled" = false;
@@ -231,7 +232,7 @@
(mkVirtualHost "lidarr.s0.neet.dev" "http://servarr.containers:8686")
(mkVirtualHost "sonarr.s0.neet.dev" "http://servarr.containers:8989")
(mkVirtualHost "prowlarr.s0.neet.dev" "http://servarr.containers:9696")
(mkVirtualHost "transmission.s0.neet.dev" "http://transmission.containers:9091")
(mkVirtualHost "transmission.s0.neet.dev" "http://transmission.containers:8080")
(mkVirtualHost "unifi.s0.neet.dev" "https://localhost:8443")
(mkVirtualHost "music.s0.neet.dev" "http://localhost:4533")
(mkVirtualHost "jellyfin.s0.neet.dev" "http://localhost:8096")