silx: 2.1.1 -> 2.1.2 (#361612)
[NixPkgs.git] / nixos / modules / services / misc / plex.nix
blobd1524aaae2a3724082adcc061954f5a5622c8891
1 { config, pkgs, lib, ... }:
2 let
3   cfg = config.services.plex;
4 in
6   imports = [
7     (lib.mkRemovedOptionModule [ "services" "plex" "managePlugins" ] "Please omit or define the option: `services.plex.extraPlugins' instead.")
8   ];
10   options = {
11     services.plex = {
12       enable = lib.mkEnableOption "Plex Media Server";
14       dataDir = lib.mkOption {
15         type = lib.types.str;
16         default = "/var/lib/plex";
17         description = ''
18           The directory where Plex stores its data files.
19         '';
20       };
22       openFirewall = lib.mkOption {
23         type = lib.types.bool;
24         default = false;
25         description = ''
26           Open ports in the firewall for the media server.
27         '';
28       };
30       user = lib.mkOption {
31         type = lib.types.str;
32         default = "plex";
33         description = ''
34           User account under which Plex runs.
35         '';
36       };
38       group = lib.mkOption {
39         type = lib.types.str;
40         default = "plex";
41         description = ''
42           Group under which Plex runs.
43         '';
44       };
46       extraPlugins = lib.mkOption {
47         type = lib.types.listOf lib.types.path;
48         default = [];
49         description = ''
50           A list of paths to extra plugin bundles to install in Plex's plugin
51           directory. Every time the systemd unit for Plex starts up, all of the
52           symlinks in Plex's plugin directory will be cleared and this module
53           will symlink all of the paths specified here to that directory.
54         '';
55         example = lib.literalExpression ''
56           [
57             (builtins.path {
58               name = "Audnexus.bundle";
59               path = pkgs.fetchFromGitHub {
60                 owner = "djdembeck";
61                 repo = "Audnexus.bundle";
62                 rev = "v0.2.8";
63                 sha256 = "sha256-IWOSz3vYL7zhdHan468xNc6C/eQ2C2BukQlaJNLXh7E=";
64               };
65             })
66           ]
67         '';
68       };
70       extraScanners = lib.mkOption {
71         type = lib.types.listOf lib.types.path;
72         default = [];
73         description = ''
74           A list of paths to extra scanners to install in Plex's scanners
75           directory.
77           Every time the systemd unit for Plex starts up, all of the symlinks
78           in Plex's scanners directory will be cleared and this module will
79           symlink all of the paths specified here to that directory.
80         '';
81         example = lib.literalExpression ''
82           [
83             (fetchFromGitHub {
84               owner = "ZeroQI";
85               repo = "Absolute-Series-Scanner";
86               rev = "773a39f502a1204b0b0255903cee4ed02c46fde0";
87               sha256 = "4l+vpiDdC8L/EeJowUgYyB3JPNTZ1sauN8liFAcK+PY=";
88             })
89           ]
90         '';
91       };
93       accelerationDevices = lib.mkOption {
94         type = lib.types.listOf lib.types.str;
95         default = ["*"];
96         example = [ "/dev/dri/renderD128" ];
97         description = ''
98           A list of device paths to hardware acceleration devices that Plex should
99           have access to. This is useful when transcoding media files.
100           The special value `"*"` will allow all devices.
101         '';
102       };
104       package = lib.mkPackageOption pkgs "plex" {
105         extraDescription = ''
106           Plex subscribers may wish to use their own package here,
107           pointing to subscriber-only server versions.
108         '';
109       };
110     };
111   };
113   config = lib.mkIf cfg.enable {
114     # Most of this is just copied from the RPM package's systemd service file.
115     systemd.services.plex = {
116       description = "Plex Media Server";
117       after = [ "network.target" ];
118       wantedBy = [ "multi-user.target" ];
120       serviceConfig = {
121         Type = "simple";
122         User = cfg.user;
123         Group = cfg.group;
125         # Run the pre-start script with full permissions (the "!" prefix) so it
126         # can create the data directory if necessary.
127         ExecStartPre = let
128           preStartScript = pkgs.writeScript "plex-run-prestart" ''
129             #!${pkgs.bash}/bin/bash
131             # Create data directory if it doesn't exist
132             if ! test -d "$PLEX_DATADIR"; then
133               echo "Creating initial Plex data directory in: $PLEX_DATADIR"
134               install -d -m 0755 -o "${cfg.user}" -g "${cfg.group}" "$PLEX_DATADIR"
135             fi
136          '';
137         in
138           "!${preStartScript}";
140         ExecStart = "${cfg.package}/bin/plexmediaserver";
141         KillSignal = "SIGQUIT";
142         PIDFile = "${cfg.dataDir}/Plex Media Server/plexmediaserver.pid";
143         Restart = "on-failure";
145         # Hardening
146         NoNewPrivileges = true;
147         PrivateTmp = true;
148         PrivateDevices = cfg.accelerationDevices == [];
149         DeviceAllow = lib.mkIf (cfg.accelerationDevices != [] && !lib.elem "*" cfg.accelerationDevices) cfg.accelerationDevices;
150         ProtectSystem = true;
151         ProtectHome = true;
152         ProtectControlGroups = true;
153         ProtectKernelModules = true;
154         ProtectKernelTunables = true;
155         RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK"];
156         # This could be made to work if the namespaces needed were known
157         # RestrictNamespaces = true;
158         RestrictRealtime = true;
159         RestrictSUIDSGID = true;
160         MemoryDenyWriteExecute = true;
161         LockPersonality = true;
162       };
164       environment = {
165         # Configuration for our FHS userenv script
166         PLEX_DATADIR=cfg.dataDir;
167         PLEX_PLUGINS=lib.concatMapStringsSep ":" builtins.toString cfg.extraPlugins;
168         PLEX_SCANNERS=lib.concatMapStringsSep ":" builtins.toString cfg.extraScanners;
170         # The following variables should be set by the FHS userenv script:
171         #   PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR
172         #   PLEX_MEDIA_SERVER_HOME
174         # Allow access to GPU acceleration; the Plex LD_LIBRARY_PATH is added
175         # by the FHS userenv script.
176         LD_LIBRARY_PATH="/run/opengl-driver/lib";
178         PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS="6";
179         PLEX_MEDIA_SERVER_TMPDIR="/tmp";
180         PLEX_MEDIA_SERVER_USE_SYSLOG="true";
181         LC_ALL="en_US.UTF-8";
182         LANG="en_US.UTF-8";
183       };
184     };
186     networking.firewall = lib.mkIf cfg.openFirewall {
187       allowedTCPPorts = [ 32400 3005 8324 32469 ];
188       allowedUDPPorts = [ 1900 5353 32410 32412 32413 32414 ];
189     };
191     users.users = lib.mkIf (cfg.user == "plex") {
192       plex = {
193         group = cfg.group;
194         uid = config.ids.uids.plex;
195       };
196     };
198     users.groups = lib.mkIf (cfg.group == "plex") {
199       plex = {
200         gid = config.ids.gids.plex;
201       };
202     };
203   };