nixpkgs/nixos/modules/services/misc/jellyfin.nix
Linus Heckemann 7eab23d517 jellyfin: fix permissions on state directory
Previously, all configuration and state data was accessible to all
users on the system running jellyfin. This included user passwords in
the Jellyfin database, as well as credentials for LDAP if configured.
The exact set of accessible data depends on system configuration.

Thanks to Sofie Finnes Øvrelid for reporting this issue.

Fixes: CVE-2022-32198

Co-Authored-By: Martin Weinelt <hexa@darmstadt.ccc.de>
2022-06-01 12:31:23 +02:00

126 lines
3.3 KiB
Nix

{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.jellyfin;
in
{
options = {
services.jellyfin = {
enable = mkEnableOption "Jellyfin Media Server";
user = mkOption {
type = types.str;
default = "jellyfin";
description = "User account under which Jellyfin runs.";
};
package = mkOption {
type = types.package;
default = pkgs.jellyfin;
defaultText = literalExpression "pkgs.jellyfin";
description = ''
Jellyfin package to use.
'';
};
group = mkOption {
type = types.str;
default = "jellyfin";
description = "Group under which jellyfin runs.";
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open the default ports in the firewall for the media server. The
HTTP/HTTPS ports can be changed in the Web UI, so this option should
only be used if they are unchanged.
'';
};
};
};
config = mkIf cfg.enable {
systemd.services.jellyfin = {
description = "Jellyfin Media Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = rec {
User = cfg.user;
Group = cfg.group;
StateDirectory = "jellyfin";
StateDirectoryMode = "0700";
CacheDirectory = "jellyfin";
CacheDirectoryMode = "0700";
UMask = "0077";
ExecStart = "${cfg.package}/bin/jellyfin --datadir '/var/lib/${StateDirectory}' --cachedir '/var/cache/${CacheDirectory}'";
Restart = "on-failure";
# Security options:
NoNewPrivileges = true;
AmbientCapabilities = "";
CapabilityBoundingSet = "";
# ProtectClock= adds DeviceAllow=char-rtc r
DeviceAllow = "";
LockPersonality = true;
PrivateTmp = true;
# Disabled to allow Jellyfin to access hw accel devices endpoints
# PrivateDevices = true;
PrivateUsers = true;
# Disabled as it does not allow Jellyfin to interface with CUDA devices
# ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RemoveIPC = true;
RestrictNamespaces = true;
# AF_NETLINK needed because Jellyfin monitors the network connection
RestrictAddressFamilies = [ "AF_NETLINK" "AF_INET" "AF_INET6" "AF_UNIX" ];
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallErrorNumber = "EPERM";
SystemCallFilter = [
"@system-service"
"~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@obsolete" "~@privileged" "~@setuid"
];
};
};
users.users = mkIf (cfg.user == "jellyfin") {
jellyfin = {
group = cfg.group;
isSystemUser = true;
};
};
users.groups = mkIf (cfg.group == "jellyfin") {
jellyfin = {};
};
networking.firewall = mkIf cfg.openFirewall {
# from https://jellyfin.org/docs/general/networking/index.html
allowedTCPPorts = [ 8096 8920 ];
allowedUDPPorts = [ 1900 7359 ];
};
};
meta.maintainers = with lib.maintainers; [ minijackson ];
}