1# Module for MiniDLNA, a simple DLNA server.
2{ config, lib, pkgs, ... }:
3
4with lib;
5
6let
7 cfg = config.services.minidlna;
8 port = 8200;
9in
10
11{
12 ###### interface
13 options = {
14 services.minidlna.enable = mkOption {
15 type = types.bool;
16 default = false;
17 description =
18 ''
19 Whether to enable MiniDLNA, a simple DLNA server. It serves
20 media files such as video and music to DLNA client devices
21 such as televisions and media players.
22 '';
23 };
24
25 services.minidlna.mediaDirs = mkOption {
26 type = types.listOf types.str;
27 default = [];
28 example = [ "/data/media" "V,/home/alice/video" ];
29 description =
30 ''
31 Directories to be scanned for media files. The prefixes
32 <literal>A,</literal>, <literal>V,</literal> and
33 <literal>P,</literal> restrict a directory to audio, video
34 or image files. The directories must be accessible to the
35 <literal>minidlna</literal> user account.
36 '';
37 };
38
39 services.minidlna.loglevel = mkOption {
40 type = types.str;
41 default = "warn";
42 example = "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn";
43 description =
44 ''
45 Defines the type of messages that should be logged, and down to
46 which level of importance they should be considered.
47
48 The possible types are “artwork”, “database”, “general”, “http”,
49 “inotify”, “metadata”, “scanner”, “ssdp” and “tivo”.
50
51 The levels are “off”, “fatal”, “error”, “warn”, “info” and
52 “debug”, listed here in order of decreasing importance. “off”
53 turns off logging messages entirely, “fatal” logs the most
54 critical messages only, and so on down to “debug” that logs every
55 single messages.
56
57 The types are comma-separated, followed by an equal sign (‘=’),
58 followed by a level that applies to the preceding types. This can
59 be repeated, separating each of these constructs with a comma.
60
61 Defaults to “general,artwork,database,inotify,scanner,metadata,
62 http,ssdp,tivo=warn” which logs every type of message at the
63 “warn” level.
64 '';
65 };
66
67 services.minidlna.config = mkOption {
68 type = types.lines;
69 description = "The contents of MiniDLNA's configuration file.";
70 };
71 };
72
73 ###### implementation
74 config = mkIf cfg.enable {
75 services.minidlna.config =
76 ''
77 port=${toString port}
78 friendly_name=${config.networking.hostName} MiniDLNA
79 db_dir=/var/cache/minidlna
80 log_level=${cfg.loglevel}
81 inotify=yes
82 ${concatMapStrings (dir: ''
83 media_dir=${dir}
84 '') cfg.mediaDirs}
85 '';
86
87 users.users.minidlna = {
88 description = "MiniDLNA daemon user";
89 group = "minidlna";
90 uid = config.ids.uids.minidlna;
91 };
92
93 users.groups.minidlna.gid = config.ids.gids.minidlna;
94
95 systemd.services.minidlna =
96 { description = "MiniDLNA Server";
97
98 wantedBy = [ "multi-user.target" ];
99 after = [ "network.target" "local-fs.target" ];
100
101 preStart =
102 ''
103 mkdir -p /var/cache/minidlna
104 chown -R minidlna:minidlna /var/cache/minidlna
105 '';
106
107 serviceConfig =
108 { User = "minidlna";
109 Group = "minidlna";
110 PermissionsStartOnly = true;
111 RuntimeDirectory = "minidlna";
112 PIDFile = "/run/minidlna/pid";
113 ExecStart =
114 "${pkgs.minidlna}/sbin/minidlnad -S -P /run/minidlna/pid" +
115 " -f ${pkgs.writeText "minidlna.conf" cfg.config}";
116 };
117 };
118 };
119}