1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.subsonic;
7 homeDir = "/var/subsonic";
8
9in
10{
11 options = {
12 services.subsonic = {
13 enable = mkEnableOption "Subsonic daemon";
14
15 home = mkOption {
16 type = types.path;
17 default = "${homeDir}";
18 description = ''
19 The directory where Subsonic will create files.
20 Make sure it is writable.
21 '';
22 };
23
24 listenAddress = mkOption {
25 type = types.string;
26 default = "0.0.0.0";
27 description = ''
28 The host name or IP address on which to bind Subsonic.
29 Only relevant if you have multiple network interfaces and want
30 to make Subsonic available on only one of them. The default value
31 will bind Subsonic to all available network interfaces.
32 '';
33 };
34
35 port = mkOption {
36 type = types.int;
37 default = 4040;
38 description = ''
39 The port on which Subsonic will listen for
40 incoming HTTP traffic. Set to 0 to disable.
41 '';
42 };
43
44 httpsPort = mkOption {
45 type = types.int;
46 default = 0;
47 description = ''
48 The port on which Subsonic will listen for
49 incoming HTTPS traffic. Set to 0 to disable.
50 '';
51 };
52
53 contextPath = mkOption {
54 type = types.path;
55 default = "/";
56 description = ''
57 The context path, i.e., the last part of the Subsonic
58 URL. Typically '/' or '/subsonic'. Default '/'
59 '';
60 };
61
62 maxMemory = mkOption {
63 type = types.int;
64 default = 100;
65 description = ''
66 The memory limit (max Java heap size) in megabytes.
67 Default: 100
68 '';
69 };
70
71 defaultMusicFolder = mkOption {
72 type = types.path;
73 default = "/var/music";
74 description = ''
75 Configure Subsonic to use this folder for music. This option
76 only has effect the first time Subsonic is started.
77 '';
78 };
79
80 defaultPodcastFolder = mkOption {
81 type = types.path;
82 default = "/var/music/Podcast";
83 description = ''
84 Configure Subsonic to use this folder for Podcasts. This option
85 only has effect the first time Subsonic is started.
86 '';
87 };
88
89 defaultPlaylistFolder = mkOption {
90 type = types.path;
91 default = "/var/playlists";
92 description = ''
93 Configure Subsonic to use this folder for playlists. This option
94 only has effect the first time Subsonic is started.
95 '';
96 };
97
98 transcoders = mkOption {
99 type = types.listOf types.path;
100 default = [ "${pkgs.ffmpeg}/bin/ffmpeg" ];
101 description = ''
102 List of paths to transcoder executables that should be accessible
103 from Subsonic. Symlinks will be created to each executable inside
104 ${cfg.home}/transcoders.
105 '';
106 };
107 };
108 };
109
110 config = mkIf cfg.enable {
111 systemd.services.subsonic = {
112 description = "Personal media streamer";
113 after = [ "local-fs.target" "network.target" ];
114 wantedBy = [ "multi-user.target" ];
115 serviceConfig = {
116 ExecStart = ''
117 ${pkgs.jre}/bin/java -Xmx${toString cfg.maxMemory}m \
118 -Dsubsonic.home=${cfg.home} \
119 -Dsubsonic.host=${cfg.listenAddress} \
120 -Dsubsonic.port=${toString cfg.port} \
121 -Dsubsonic.httpsPort=${toString cfg.httpsPort} \
122 -Dsubsonic.contextPath=${cfg.contextPath} \
123 -Dsubsonic.defaultMusicFolder=${cfg.defaultMusicFolder} \
124 -Dsubsonic.defaultPodcastFolder=${cfg.defaultPodcastFolder} \
125 -Dsubsonic.defaultPlaylistFolder=${cfg.defaultPlaylistFolder} \
126 -Djava.awt.headless=true \
127 -verbose:gc \
128 -jar ${pkgs.subsonic}/subsonic-booter-jar-with-dependencies.jar
129 '';
130 # Install transcoders.
131 ExecStartPre = ''
132 ${pkgs.coreutils}/bin/rm -rf ${cfg.home}/transcode ; \
133 ${pkgs.coreutils}/bin/mkdir -p ${cfg.home}/transcode ; \
134 ${pkgs.bash}/bin/bash -c ' \
135 for exe in "$@"; do \
136 ${pkgs.coreutils}/bin/ln -sf "$exe" ${cfg.home}/transcode; \
137 done' IGNORED_FIRST_ARG ${toString cfg.transcoders}
138 '';
139 # Needed for Subsonic to find subsonic.war.
140 WorkingDirectory = "${pkgs.subsonic}";
141 Restart = "always";
142 User = "subsonic";
143 UMask = "0022";
144 };
145 };
146
147 users.extraUsers.subsonic = {
148 description = "Subsonic daemon user";
149 home = homeDir;
150 createHome = true;
151 group = "subsonic";
152 uid = config.ids.uids.subsonic;
153 };
154
155 users.extraGroups.subsonic.gid = config.ids.gids.subsonic;
156 };
157}