1{ config, pkgs, lib, ... }:
2
3with lib;
4
5let
6 cfg = config.services.plex;
7 plex = pkgs.plex;
8in
9{
10 options = {
11 services.plex = {
12 enable = mkEnableOption "Plex Media Server";
13
14 # FIXME: In order for this config option to work, symlinks in the Plex
15 # package in the Nix store have to be changed to point to this directory.
16 dataDir = mkOption {
17 type = types.str;
18 default = "/var/lib/plex";
19 description = "The directory where Plex stores its data files.";
20 };
21
22 user = mkOption {
23 type = types.str;
24 default = "plex";
25 description = "User account under which Plex runs.";
26 };
27
28 group = mkOption {
29 type = types.str;
30 default = "plex";
31 description = "Group under which Plex runs.";
32 };
33
34
35 managePlugins = mkOption {
36 type = types.bool;
37 default = true;
38 description = ''
39 If set to true, this option will cause all of the symlinks in Plex's
40 plugin directory to be removed and symlinks for paths specified in
41 <option>extraPlugins</option> to be added.
42 '';
43 };
44
45 extraPlugins = mkOption {
46 type = types.listOf types.path;
47 default = [];
48 description = ''
49 A list of paths to extra plugin bundles to install in Plex's plugin
50 directory. Every time the systemd unit for Plex starts up, all of the
51 symlinks in Plex's plugin directory will be cleared and this module
52 will symlink all of the paths specified here to that directory. If
53 this behavior is undesired, set <option>managePlugins</option> to
54 false.
55 '';
56 };
57 };
58 };
59
60 config = mkIf cfg.enable {
61 # Most of this is just copied from the RPM package's systemd service file.
62 systemd.services.plex = {
63 description = "Plex Media Server";
64 after = [ "network.target" ];
65 wantedBy = [ "multi-user.target" ];
66 preStart = ''
67 test -d "${cfg.dataDir}" || {
68 echo "Creating initial Plex data directory in \"${cfg.dataDir}\"."
69 mkdir -p "${cfg.dataDir}"
70 chown -R ${cfg.user}:${cfg.group} "${cfg.dataDir}"
71 }
72
73 # Copy the database skeleton files to /var/lib/plex/.skeleton
74 # See the the Nix expression for Plex's package for more information on
75 # why this is done.
76 test -d "${cfg.dataDir}/.skeleton" || mkdir "${cfg.dataDir}/.skeleton"
77 for db in "com.plexapp.plugins.library.db"; do
78 cp "${plex}/usr/lib/plexmediaserver/Resources/base_$db" "${cfg.dataDir}/.skeleton/$db"
79 chmod u+w "${cfg.dataDir}/.skeleton/$db"
80 chown ${cfg.user}:${cfg.group} "${cfg.dataDir}/.skeleton/$db"
81 done
82
83 # If managePlugins is enabled, setup symlinks for plugins.
84 ${optionalString cfg.managePlugins ''
85 echo "Preparing plugin directory."
86 PLUGINDIR="${cfg.dataDir}/Plex Media Server/Plug-ins"
87 test -d "$PLUGINDIR" || {
88 mkdir -p "$PLUGINDIR";
89 chown ${cfg.user}:${cfg.group} "$PLUGINDIR";
90 }
91
92 echo "Removing old symlinks."
93 # First, remove all of the symlinks in the directory.
94 for f in `ls "$PLUGINDIR/"`; do
95 if [[ -L "$PLUGINDIR/$f" ]]; then
96 echo "Removing plugin symlink $PLUGINDIR/$f."
97 rm "$PLUGINDIR/$f"
98 fi
99 done
100
101 echo "Symlinking plugins."
102 for path in ${toString cfg.extraPlugins}; do
103 dest="$PLUGINDIR/$(basename $path)"
104 if [[ ! -d "$path" ]]; then
105 echo "Error symlinking plugin from $path: no such directory."
106 elif [[ -d "$dest" || -L "$dest" ]]; then
107 echo "Error symlinking plugin from $path to $dest: file or directory already exists."
108 else
109 echo "Symlinking plugin at $path..."
110 ln -s "$path" "$dest"
111 fi
112 done
113 ''}
114 '';
115 serviceConfig = {
116 Type = "simple";
117 User = cfg.user;
118 Group = cfg.group;
119 PermissionsStartOnly = "true";
120 ExecStart = "/bin/sh -c '${plex}/usr/lib/plexmediaserver/Plex\\ Media\\ Server'";
121 };
122 environment = {
123 PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=cfg.dataDir;
124 PLEX_MEDIA_SERVER_HOME="${plex}/usr/lib/plexmediaserver";
125 PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS="6";
126 PLEX_MEDIA_SERVER_TMPDIR="/tmp";
127 LD_LIBRARY_PATH="${plex}/usr/lib/plexmediaserver";
128 LC_ALL="en_US.UTF-8";
129 LANG="en_US.UTF-8";
130 };
131 };
132
133 users.extraUsers = mkIf (cfg.user == "plex") {
134 plex = {
135 group = cfg.group;
136 uid = config.ids.uids.plex;
137 };
138 };
139
140 users.extraGroups = mkIf (cfg.group == "plex") {
141 plex = {
142 gid = config.ids.gids.plex;
143 };
144 };
145 };
146}