From 8def0af08f630a39c228775eecc27f0838ece6fb Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Sat, 24 May 2025 10:11:18 +0200 Subject: [PATCH] feat: add lms --- hosts/fw/configuration.nix | 5 +- hosts/fw/modules/firewall.nix | 29 ++++++++++++ hosts/fw/modules/lms.nix | 88 +++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 hosts/fw/modules/lms.nix diff --git a/hosts/fw/configuration.nix b/hosts/fw/configuration.nix index 92a6498..0401028 100644 --- a/hosts/fw/configuration.nix +++ b/hosts/fw/configuration.nix @@ -35,7 +35,7 @@ # ./modules/vscode-server.nix # Add VS Code Server microvm ./modules/ai-mailer.nix - ./modules/wazuh.nix + # ./modules/wazuh.nix # web ./modules/web @@ -54,7 +54,8 @@ ./modules/deconz.nix # ./modules/mopidy.nix # ./modules/mosquitto.nix - ./modules/snapserver.nix + # ./modules/snapserver.nix + ./modules/lms.nix # gaming # ./modules/palworld.nix diff --git a/hosts/fw/modules/firewall.nix b/hosts/fw/modules/firewall.nix index b2277c5..22bc6a1 100644 --- a/hosts/fw/modules/firewall.nix +++ b/hosts/fw/modules/firewall.nix @@ -8,6 +8,18 @@ "cloonar-fw" = { family = "inet"; content = '' + chain snap-qos-raw { + type filter hook prerouting priority raw; policy accept; + tcp dport 1704 counter mark set 10 comment "Mark Snapcast traffic" + tcp dport 3483 counter mark set 10 comment "Mark Squezelite traffic" + udp dport 3483 counter mark set 10 comment "Mark Squezelite traffic" + } + + chain snap-qos-mangle { + type filter hook postrouting priority mangle + 10; policy accept; + mark 10 counter ip dscp set cs3 comment "Tag Snapcast with CS3" + } + chain output { type filter hook output priority 100; policy accept; } @@ -22,6 +34,7 @@ type filter hook input priority filter; policy drop; iifname "lo" accept comment "trusted interfaces" iifname "lan" counter accept comment "Spice" + iifname { "server", "vserver", "vm-*", "lan", "wg_cloonar" } counter accept comment "allow trusted to router" ct state vmap { invalid : drop, established : accept, related : accept, new : jump input-allow, untracked : jump input-allow } tcp flags syn / fin,syn,rst,ack log prefix "refused connection: " level info } @@ -40,6 +53,8 @@ # Accept mDNS for avahi reflection iifname "server" ip saddr ${config.networkPrefix}.97.20/32 tcp dport { llmnr } counter accept iifname "server" ip saddr ${config.networkPrefix}.97.20/32 udp dport { mdns, llmnr } counter accept + iifname "server" udp dport 5353 ip daddr 224.0.0.251 counter accept comment "Avahi mDNS" + iifname "lan" udp dport 5353 ip daddr 224.0.0.251 counter accept comment "Avahi mDNS" # Allow all returning traffic ct state { established, related } counter accept @@ -80,10 +95,24 @@ # multimedia airplay iifname "multimedia" oifname { "lan" } counter accept iifname "multimedia" oifname "server" tcp dport { 1704, 1705 } counter accept + iifname "multimedia" oifname "server" tcp dport { 3483, 9000 } counter accept + iifname "multimedia" oifname "server" udp dport { 3483 } counter accept + iifname "multimedia" oifname "server" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" iifname "lan" oifname "server" udp dport { 5000, 5353, 6001 - 6011 } counter accept # avahi iifname "server" ip saddr ${config.networkPrefix}.97.20/32 oifname { "lan" } counter accept + # Allow Chromecast + iifname "lan" oifname "server" udp dport 5353 ip daddr 224.0.0.251 counter accept comment "mDNS query LAN→Server" + iifname "server" oifname "lan" udp sport 5353 ip saddr 224.0.0.251 counter accept comment "mDNS response Server→LAN" + iifname "lan" oifname "server" tcp dport 9881 counter accept comment "chromecast" + + # SSDP / UPnP discovery if needed + iifname { "lan", "server" } oifname { "server", "lan" } \ + udp dport 1900 ip daddr 239.255.255.250 counter accept comment "SSDP query" + iifname { "lan", "server" } oifname { "server", "lan" } \ + udp sport 1900 ip saddr 239.255.255.250 counter accept comment "SSDP response" + # smart home coap iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 udp dport { 5683 } counter accept iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 tcp dport { 1883 } counter accept diff --git a/hosts/fw/modules/lms.nix b/hosts/fw/modules/lms.nix new file mode 100644 index 0000000..2de58cc --- /dev/null +++ b/hosts/fw/modules/lms.nix @@ -0,0 +1,88 @@ +{ pkgs, config, lib, python3Packages, ... }: + +let + lmsDomain = "lms.cloonar.com"; + networkPrefix = config.networkPrefix; +in +{ + security.acme.certs."${lmsDomain}" = { + group = "nginx"; + }; + + sops.secrets.lms-spotify = { }; + + containers.lms = { + autoStart = true; + ephemeral = false; + privateNetwork = true; + hostBridge = "server"; + + hostAddress = "${networkPrefix}.97.2"; + localAddress = "${networkPrefix}.97.21/24"; + + extraFlags = [ "--capability=CAP_NET_ADMIN" ]; + + bindMounts = { + "/var/lib/acme/lms/" = { + hostPath = config.security.acme.certs.${lmsDomain}.directory; + isReadOnly = true; + }; + "/run/secrets/lms-spotify" = { + hostPath = config.sops.secrets.lms-spotify.path; + }; + }; + + config = { pkgs, lib, config, ... }: + let + in + { + networking = { + hostName = "lms"; + useHostResolvConf = false; + defaultGateway = { + address = "${networkPrefix}.97.1"; + interface = "eth0"; + }; + nameservers = [ "${networkPrefix}.97.1" ]; + firewall.enable = false; + }; + + environment.systemPackages = with pkgs; [ + slimserver # Logitech/Lyrion Media Server + ]; + + services.slimserver = { + enable = true; + package = pkgs.slimserver; + }; + + # make LMS discoverable via mDNS/Avahi + services.avahi = { + enable = true; + publish.enable = true; + publish.userServices = true; + }; + + services.nginx.enable = true; + services.nginx.virtualHosts."${lmsDomain}" = { + sslCertificate = "/var/lib/acme/lms/fullchain.pem"; + sslCertificateKey = "/var/lib/acme/lms/key.pem"; + sslTrustedCertificate = "/var/lib/acme/lms/chain.pem"; + forceSSL = true; + extraConfig = "proxy_buffering off;"; + + locations."/".extraConfig = '' + proxy_pass http://127.0.0.1:9000/; + proxy_set_header Host $host; + proxy_redirect http:// https://; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + ''; + }; + + system.stateVersion = "23.05"; + }; + }; +}