feat: add lms

This commit is contained in:
2025-05-24 10:11:18 +02:00
parent 348d8e1d03
commit 8def0af08f
3 changed files with 120 additions and 2 deletions

View File

@@ -35,7 +35,7 @@
# ./modules/vscode-server.nix # Add VS Code Server microvm # ./modules/vscode-server.nix # Add VS Code Server microvm
./modules/ai-mailer.nix ./modules/ai-mailer.nix
./modules/wazuh.nix # ./modules/wazuh.nix
# web # web
./modules/web ./modules/web
@@ -54,7 +54,8 @@
./modules/deconz.nix ./modules/deconz.nix
# ./modules/mopidy.nix # ./modules/mopidy.nix
# ./modules/mosquitto.nix # ./modules/mosquitto.nix
./modules/snapserver.nix # ./modules/snapserver.nix
./modules/lms.nix
# gaming # gaming
# ./modules/palworld.nix # ./modules/palworld.nix

View File

@@ -8,6 +8,18 @@
"cloonar-fw" = { "cloonar-fw" = {
family = "inet"; family = "inet";
content = '' 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 { chain output {
type filter hook output priority 100; policy accept; type filter hook output priority 100; policy accept;
} }
@@ -22,6 +34,7 @@
type filter hook input priority filter; policy drop; type filter hook input priority filter; policy drop;
iifname "lo" accept comment "trusted interfaces" iifname "lo" accept comment "trusted interfaces"
iifname "lan" counter accept comment "Spice" 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 } 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 tcp flags syn / fin,syn,rst,ack log prefix "refused connection: " level info
} }
@@ -40,6 +53,8 @@
# Accept mDNS for avahi reflection # 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 tcp dport { llmnr } counter accept
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 udp dport { mdns, 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 # Allow all returning traffic
ct state { established, related } counter accept ct state { established, related } counter accept
@@ -80,10 +95,24 @@
# multimedia airplay # multimedia airplay
iifname "multimedia" oifname { "lan" } counter accept iifname "multimedia" oifname { "lan" } counter accept
iifname "multimedia" oifname "server" tcp dport { 1704, 1705 } 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 iifname "lan" oifname "server" udp dport { 5000, 5353, 6001 - 6011 } counter accept
# avahi # avahi
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 oifname { "lan" } counter accept 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 LANServer"
iifname "server" oifname "lan" udp sport 5353 ip saddr 224.0.0.251 counter accept comment "mDNS response ServerLAN"
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 # 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 udp dport { 5683 } counter accept
iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 tcp dport { 1883 } counter accept iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 tcp dport { 1883 } counter accept

88
hosts/fw/modules/lms.nix Normal file
View File

@@ -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";
};
};
}