1 { config, pkgs, lib, ... }:
6 cfg = config.services.jellyfin;
11 enable = mkEnableOption (lib.mdDoc "Jellyfin Media Server");
16 description = lib.mdDoc "User account under which Jellyfin runs.";
21 default = pkgs.jellyfin;
22 defaultText = literalExpression "pkgs.jellyfin";
23 description = lib.mdDoc ''
24 Jellyfin package to use.
31 description = lib.mdDoc "Group under which jellyfin runs.";
34 openFirewall = mkOption {
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.
46 config = mkIf cfg.enable {
47 systemd.services.jellyfin = {
48 description = "Jellyfin Media Server";
49 after = [ "network.target" ];
50 wantedBy = [ "multi-user.target" ];
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
58 StateDirectory = "jellyfin";
59 StateDirectoryMode = "0700";
60 CacheDirectory = "jellyfin";
61 CacheDirectoryMode = "0700";
63 WorkingDirectory = "/var/lib/jellyfin";
64 ExecStart = "${cfg.package}/bin/jellyfin --datadir '/var/lib/${StateDirectory}' --cachedir '/var/cache/${CacheDirectory}'";
65 Restart = "on-failure";
67 SuccessExitStatus = ["0" "143"];
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 accelaration
85 PrivateDevices = false;
106 SystemCallErrorNumber = "EPERM";
110 users.users = mkIf (cfg.user == "jellyfin") {
117 users.groups = mkIf (cfg.group == "jellyfin") {
121 networking.firewall = mkIf cfg.openFirewall {
122 # from https://jellyfin.org/docs/general/networking/index.html
123 allowedTCPPorts = [ 8096 8920 ];
124 allowedUDPPorts = [ 1900 7359 ];
129 meta.maintainers = with lib.maintainers; [ minijackson ];