{ pkgs, service_configs, config, ... }: { systemd.services."jellyfin-qbittorrent-monitor" = { description = "Monitor Jellyfin streaming and control qBittorrent rate limits"; after = [ "network.target" "jellyfin.service" "qbittorrent.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; ExecStart = pkgs.writeShellScript "jellyfin-monitor-start" '' export JELLYFIN_API_KEY=$(cat $CREDENTIALS_DIRECTORY/jellyfin-api-key) exec ${ pkgs.python3.withPackages (ps: with ps; [ requests ]) }/bin/python ${./jellyfin-qbittorrent-monitor.py} ''; Restart = "always"; RestartSec = "10s"; # Security hardening DynamicUser = true; NoNewPrivileges = true; ProtectSystem = "strict"; ProtectHome = true; ProtectKernelTunables = true; ProtectKernelModules = true; ProtectControlGroups = true; MemoryDenyWriteExecute = true; RestrictRealtime = true; RestrictSUIDSGID = true; RemoveIPC = true; # Load credentials from agenix secrets LoadCredential = "jellyfin-api-key:${config.age.secrets.jellyfin-api-key.path}"; }; environment = { JELLYFIN_URL = "http://localhost:${builtins.toString service_configs.ports.jellyfin}"; QBITTORRENT_URL = "http://${config.vpnNamespaces.wg.namespaceAddress}:${builtins.toString service_configs.ports.torrent}"; CHECK_INTERVAL = "30"; # Bandwidth budget configuration TOTAL_BANDWIDTH_BUDGET = "30000000"; # 30 Mbps in bits per second SERVICE_BUFFER = "5000000"; # 5 Mbps reserved for other services (bps) DEFAULT_STREAM_BITRATE = "10000000"; # 10 Mbps fallback when bitrate unknown (bps) MIN_TORRENT_SPEED = "100"; # KB/s - below this, pause torrents instead STREAM_BITRATE_HEADROOM = "1.1"; # multiplier per stream for bitrate fluctuations }; }; }