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}