at 23.11-pre 3.8 kB view raw
1{ config, pkgs, lib, ... }: 2 3with lib; 4 5let 6 cfg = config.services.jellyfin; 7in 8{ 9 options = { 10 services.jellyfin = { 11 enable = mkEnableOption (lib.mdDoc "Jellyfin Media Server"); 12 13 user = mkOption { 14 type = types.str; 15 default = "jellyfin"; 16 description = lib.mdDoc "User account under which Jellyfin runs."; 17 }; 18 19 package = mkOption { 20 type = types.package; 21 default = pkgs.jellyfin; 22 defaultText = literalExpression "pkgs.jellyfin"; 23 description = lib.mdDoc '' 24 Jellyfin package to use. 25 ''; 26 }; 27 28 group = mkOption { 29 type = types.str; 30 default = "jellyfin"; 31 description = lib.mdDoc "Group under which jellyfin runs."; 32 }; 33 34 openFirewall = mkOption { 35 type = types.bool; 36 default = false; 37 description = lib.mdDoc '' 38 Open the default ports in the firewall for the media server. The 39 HTTP/HTTPS ports can be changed in the Web UI, so this option should 40 only be used if they are unchanged. 41 ''; 42 }; 43 }; 44 }; 45 46 config = mkIf cfg.enable { 47 systemd.services.jellyfin = { 48 description = "Jellyfin Media Server"; 49 after = [ "network.target" ]; 50 wantedBy = [ "multi-user.target" ]; 51 52 # This is mostly follows: https://github.com/jellyfin/jellyfin/blob/master/fedora/jellyfin.service 53 # Upstream also disable some hardenings when running in LXC, we do the same with the isContainer option 54 serviceConfig = rec { 55 Type = "simple"; 56 User = cfg.user; 57 Group = cfg.group; 58 StateDirectory = "jellyfin"; 59 StateDirectoryMode = "0700"; 60 CacheDirectory = "jellyfin"; 61 CacheDirectoryMode = "0700"; 62 UMask = "0077"; 63 WorkingDirectory = "/var/lib/jellyfin"; 64 ExecStart = "${cfg.package}/bin/jellyfin --datadir '/var/lib/${StateDirectory}' --cachedir '/var/cache/${CacheDirectory}'"; 65 Restart = "on-failure"; 66 TimeoutSec = 15; 67 SuccessExitStatus = ["0" "143"]; 68 69 # Security options: 70 NoNewPrivileges = true; 71 SystemCallArchitectures = "native"; 72 # AF_NETLINK needed because Jellyfin monitors the network connection 73 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK" ]; 74 RestrictNamespaces = !config.boot.isContainer; 75 RestrictRealtime = true; 76 RestrictSUIDSGID = true; 77 ProtectControlGroups = !config.boot.isContainer; 78 ProtectHostname = true; 79 ProtectKernelLogs = !config.boot.isContainer; 80 ProtectKernelModules = !config.boot.isContainer; 81 ProtectKernelTunables = !config.boot.isContainer; 82 LockPersonality = true; 83 PrivateTmp = !config.boot.isContainer; 84 # needed for hardware acceleration 85 PrivateDevices = false; 86 PrivateUsers = true; 87 RemoveIPC = true; 88 89 SystemCallFilter = [ 90 "~@clock" 91 "~@aio" 92 "~@chown" 93 "~@cpu-emulation" 94 "~@debug" 95 "~@keyring" 96 "~@memlock" 97 "~@module" 98 "~@mount" 99 "~@obsolete" 100 "~@privileged" 101 "~@raw-io" 102 "~@reboot" 103 "~@setuid" 104 "~@swap" 105 ]; 106 SystemCallErrorNumber = "EPERM"; 107 }; 108 }; 109 110 users.users = mkIf (cfg.user == "jellyfin") { 111 jellyfin = { 112 group = cfg.group; 113 isSystemUser = true; 114 }; 115 }; 116 117 users.groups = mkIf (cfg.group == "jellyfin") { 118 jellyfin = {}; 119 }; 120 121 networking.firewall = mkIf cfg.openFirewall { 122 # from https://jellyfin.org/docs/general/networking/index.html 123 allowedTCPPorts = [ 8096 8920 ]; 124 allowedUDPPorts = [ 1900 7359 ]; 125 }; 126 127 }; 128 129 meta.maintainers = with lib.maintainers; [ minijackson ]; 130}