summaryrefslogtreecommitdiff
path: root/hosts/poweredge/jellyfin.nix
blob: 2fbdabdb1e6df9c9ad54409a34b6d3382ea87da7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{
	containers.jellyfin = {
		autoStart = true;
		privateNetwork = true;
		hostBridge = "br-lan0";
		localMacAddress = "02:00:00:00:00:02";
		bindMounts = {
			"/media" = {
				hostPath = "/media/ingens/media";
				isReadOnly = true;
			};
		};

		# GPU
		allowedDevices = [
			{ node = "/dev/nvidia0";           modifier = "rw"; }
			{ node = "/dev/nvidiactl";         modifier = "rw"; }
			{ node = "/dev/nvidia-uvm";        modifier = "rw"; }
			{ node = "/dev/nvidia-uvm-tools";  modifier = "rw"; }
			{ node = "/dev/nvidia-modeset";    modifier = "rw"; }
		];

		bindMounts = {
			# NVENC/NVDEC - video transcoding
			"/dev/nvidia0"           = { hostPath = "/dev/nvidia0";           isReadOnly = false; };
			"/dev/nvidiactl"         = { hostPath = "/dev/nvidiactl";         isReadOnly = false; };
			# CUDA - required for ML inference
			"/dev/nvidia-uvm"        = { hostPath = "/dev/nvidia-uvm";        isReadOnly = false; };
			"/dev/nvidia-uvm-tools"  = { hostPath = "/dev/nvidia-uvm-tools";  isReadOnly = false; };
			# Modeset - needed by some driver paths
			"/dev/nvidia-modeset"    = { hostPath = "/dev/nvidia-modeset";    isReadOnly = false; };
		};

		config = { lib, config, pkgs, ... }: {
			# Network
			networking.interfaces.eth0.useDHCP = true;
			networking.firewall.allowedTCPPorts = [ 80 ];  # Caddy

			# Configure nixpkgs for nvidia/cuda
			nixpkgs.config.allowUnfree = true;

			# Jellyfin
			services.jellyfin = {
				enable = true;
				openFirewall = true;

				hardwareAcceleration = {
					enable = true;
					type = "nvenc";
					device = "/dev/nvidia0"; # Required by the module's assertion, unused in encoding.xml for nvenc
				};

				forceEncodingConfig = true;  # Override encoding.xml

				transcoding = {
					enableHardwareEncoding = true;

					hardwareEncodingCodecs = {
						hevc = true;  # Pascal 4th-gen NVENC supports HEVC 8/10-bit encode
						av1  = false;  # NOT supported on Pascal — do not enable
					};

					hardwareDecodingCodecs = {
						h264 = true;
						hevc = true;
						hevc10bit = true;
						vp8 = true;
						vp9 = true;
						mpeg2 = true;
						vc1 = true;
						av1 = false;  # NOT supported on Pascal NVDEC
						hevcRExt10bit = false;  # Range Extensions decode is a newer-gen feature, skip on Pascal
						hevcRExt12bit = false;
					};

					encodingPreset = "medium";
					enableToneMapping = true; # works via CUDA-based tonemap_cuda filter on Pascal+
				};
			};

			# Reverse proxy
			services.caddy = {
				enable = true;
				virtualHosts.":80".extraConfig = ''
					reverse_proxy localhost:8096
				'';
			};

			# NVIDIA
			services.xserver.videoDrivers = [ "nvidia" ];  # xserver.videoDrivers does not imply X
			hardware.graphics.enable = true;
			hardware.nvidia = {
				modesetting.enable = true;  # Required
				nvidiaSettings = false;  # Don't need gui
				open = false;
				package = config.boot.kernelPackages.nvidiaPackages.legacy_580;  # Must match host
			};

			# Packages
			environment.systemPackages = with pkgs; [
				config.hardware.nvidia.package  # nvidia-smi
			];

			system.stateVersion = "26.05";
		};
	};
}