Commit ef2e8d605c96

Vincent Demeester <vincent@sbr.pm>
2025-12-16 13:08:13
feat(aix): Add DNS and TLS proxy for remote media access
- Enable access to media services from parents' location via Aix - Maintain end-to-end encryption with TCP/TLS pass-through to rhea - Route only specific services (Jellyfin, Navidrome, Immich, etc.) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: Vincent Demeester <vincent@sbr.pm>
1 parent bf70e48
Changed files (1)
systems
systems/aix/extra.nix
@@ -1,8 +1,16 @@
 {
+  lib,
   libx,
   globals,
   ...
 }:
+let
+  # Rhea's VPN IP for TLS proxy backend
+  rheaVpnIP = lib.head globals.machines.rhea.net.vpn.ips;
+
+  # Aix's local IP for DNS resolution
+  aixLocalIP = "192.168.1.75";
+in
 {
   imports = [
     ../common/services/samba.nix
@@ -37,5 +45,75 @@
       endpoint = "${globals.net.vpn.endpoint}";
       endpointPublicKey = "${globals.machines.kerkouane.net.vpn.pubkey}";
     };
+
+    # DNS resolver for local network - resolve specific sbr.pm domains to Aix
+    dnsmasq = {
+      enable = true;
+      settings = {
+        # Listen on local network interface
+        interface = "end0";
+        bind-interfaces = true;
+
+        # DNS settings
+        domain-needed = true;
+        bogus-priv = true;
+
+        # Resolve specific media service domains to Aix (which will reverse proxy)
+        address = [
+          "/music.sbr.pm/${aixLocalIP}"
+          "/navidrome.sbr.pm/${aixLocalIP}"
+          "/jellyfin.sbr.pm/${aixLocalIP}"
+          "/podcasts.sbr.pm/${aixLocalIP}"
+          "/audiobookshelf.sbr.pm/${aixLocalIP}"
+          "/immich.sbr.pm/${aixLocalIP}"
+        ];
+
+        # Use upstream DNS for other queries
+        server = [
+          "1.1.1.1"
+          "8.8.8.8"
+        ];
+
+        # Cache settings
+        cache-size = 1000;
+      };
+    };
+
+    # Nginx TCP/TLS pass-through to rhea's Traefik
+    nginx = {
+      enable = true;
+
+      # Enable stream module for TCP/TLS proxying
+      streamConfig = ''
+        # Map SNI hostname to backend
+        # All services go to rhea's Traefik, which routes internally
+        map $ssl_preread_server_name $backend {
+          navidrome.sbr.pm      ${rheaVpnIP}:443;
+          music.sbr.pm          ${rheaVpnIP}:443;
+          jellyfin.sbr.pm       ${rheaVpnIP}:443;
+          audiobookshelf.sbr.pm ${rheaVpnIP}:443;
+          podcasts.sbr.pm       ${rheaVpnIP}:443;
+          immich.sbr.pm         ${rheaVpnIP}:443;
+          default               ${rheaVpnIP}:443;
+        }
+
+        # HTTPS proxy server
+        server {
+          listen 443;
+          listen [::]:443;
+
+          # Read SNI without terminating TLS
+          ssl_preread on;
+
+          # Forward to rhea's Traefik
+          proxy_pass $backend;
+
+          # Connection settings for streaming
+          proxy_connect_timeout 5s;
+          proxy_timeout 24h;
+          proxy_buffer_size 16k;
+        }
+      '';
+    };
   };
 }