1 { config, pkgs, lib, ... }:
6 cfg = config.services.plex;
10 (mkRemovedOptionModule [ "services" "plex" "managePlugins" ] "Please omit or define the option: `services.plex.extraPlugins' instead.")
15 enable = mkEnableOption "Plex Media Server";
19 default = "/var/lib/plex";
21 The directory where Plex stores its data files.
25 openFirewall = mkOption {
29 Open ports in the firewall for the media server.
37 User account under which Plex runs.
45 Group under which Plex runs.
49 extraPlugins = mkOption {
50 type = types.listOf types.path;
53 A list of paths to extra plugin bundles to install in Plex's plugin
54 directory. Every time the systemd unit for Plex starts up, all of the
55 symlinks in Plex's plugin directory will be cleared and this module
56 will symlink all of the paths specified here to that directory.
58 example = literalExpression ''
61 name = "Audnexus.bundle";
62 path = pkgs.fetchFromGitHub {
64 repo = "Audnexus.bundle";
66 sha256 = "sha256-IWOSz3vYL7zhdHan468xNc6C/eQ2C2BukQlaJNLXh7E=";
73 extraScanners = mkOption {
74 type = types.listOf types.path;
77 A list of paths to extra scanners to install in Plex's scanners
80 Every time the systemd unit for Plex starts up, all of the symlinks
81 in Plex's scanners directory will be cleared and this module will
82 symlink all of the paths specified here to that directory.
84 example = literalExpression ''
88 repo = "Absolute-Series-Scanner";
89 rev = "773a39f502a1204b0b0255903cee4ed02c46fde0";
90 sha256 = "4l+vpiDdC8L/EeJowUgYyB3JPNTZ1sauN8liFAcK+PY=";
96 accelerationDevices = mkOption {
97 type = types.listOf types.str;
99 example = [ "/dev/dri/renderD128" ];
101 A list of device paths to hardware acceleration devices that Plex should
102 have access to. This is useful when transcoding media files.
103 The special value `"*"` will allow all devices.
107 package = mkPackageOption pkgs "plex" {
108 extraDescription = ''
109 Plex subscribers may wish to use their own package here,
110 pointing to subscriber-only server versions.
116 config = mkIf cfg.enable {
117 # Most of this is just copied from the RPM package's systemd service file.
118 systemd.services.plex = {
119 description = "Plex Media Server";
120 after = [ "network.target" ];
121 wantedBy = [ "multi-user.target" ];
128 # Run the pre-start script with full permissions (the "!" prefix) so it
129 # can create the data directory if necessary.
131 preStartScript = pkgs.writeScript "plex-run-prestart" ''
132 #!${pkgs.bash}/bin/bash
134 # Create data directory if it doesn't exist
135 if ! test -d "$PLEX_DATADIR"; then
136 echo "Creating initial Plex data directory in: $PLEX_DATADIR"
137 install -d -m 0755 -o "${cfg.user}" -g "${cfg.group}" "$PLEX_DATADIR"
141 "!${preStartScript}";
143 ExecStart = "${cfg.package}/bin/plexmediaserver";
144 KillSignal = "SIGQUIT";
145 PIDFile = "${cfg.dataDir}/Plex Media Server/plexmediaserver.pid";
146 Restart = "on-failure";
149 NoNewPrivileges = true;
151 PrivateDevices = cfg.accelerationDevices == [];
152 DeviceAllow = mkIf (cfg.accelerationDevices != [] && !lib.elem "*" cfg.accelerationDevices) cfg.accelerationDevices;
153 ProtectSystem = true;
155 ProtectControlGroups = true;
156 ProtectKernelModules = true;
157 ProtectKernelTunables = true;
158 RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK"];
159 # This could be made to work if the namespaces needed were known
160 # RestrictNamespaces = true;
161 RestrictRealtime = true;
162 RestrictSUIDSGID = true;
163 MemoryDenyWriteExecute = true;
164 LockPersonality = true;
168 # Configuration for our FHS userenv script
169 PLEX_DATADIR=cfg.dataDir;
170 PLEX_PLUGINS=concatMapStringsSep ":" builtins.toString cfg.extraPlugins;
171 PLEX_SCANNERS=concatMapStringsSep ":" builtins.toString cfg.extraScanners;
173 # The following variables should be set by the FHS userenv script:
174 # PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR
175 # PLEX_MEDIA_SERVER_HOME
177 # Allow access to GPU acceleration; the Plex LD_LIBRARY_PATH is added
178 # by the FHS userenv script.
179 LD_LIBRARY_PATH="/run/opengl-driver/lib";
181 PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS="6";
182 PLEX_MEDIA_SERVER_TMPDIR="/tmp";
183 PLEX_MEDIA_SERVER_USE_SYSLOG="true";
184 LC_ALL="en_US.UTF-8";
189 networking.firewall = mkIf cfg.openFirewall {
190 allowedTCPPorts = [ 32400 3005 8324 32469 ];
191 allowedUDPPorts = [ 1900 5353 32410 32412 32413 32414 ];
194 users.users = mkIf (cfg.user == "plex") {
197 uid = config.ids.uids.plex;
201 users.groups = mkIf (cfg.group == "plex") {
203 gid = config.ids.gids.plex;