at 22.05-pre 5.2 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.airsonic; 7in { 8 options = { 9 10 services.airsonic = { 11 enable = mkEnableOption "Airsonic, the Free and Open Source media streaming server (fork of Subsonic and Libresonic)"; 12 13 user = mkOption { 14 type = types.str; 15 default = "airsonic"; 16 description = "User account under which airsonic runs."; 17 }; 18 19 home = mkOption { 20 type = types.path; 21 default = "/var/lib/airsonic"; 22 description = '' 23 The directory where Airsonic will create files. 24 Make sure it is writable. 25 ''; 26 }; 27 28 virtualHost = mkOption { 29 type = types.nullOr types.str; 30 default = null; 31 description = '' 32 Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost. 33 ''; 34 }; 35 36 listenAddress = mkOption { 37 type = types.str; 38 default = "127.0.0.1"; 39 description = '' 40 The host name or IP address on which to bind Airsonic. 41 Only relevant if you have multiple network interfaces and want 42 to make Airsonic available on only one of them. The default value 43 will bind Airsonic to all available network interfaces. 44 ''; 45 }; 46 47 port = mkOption { 48 type = types.int; 49 default = 4040; 50 description = '' 51 The port on which Airsonic will listen for 52 incoming HTTP traffic. Set to 0 to disable. 53 ''; 54 }; 55 56 contextPath = mkOption { 57 type = types.path; 58 default = "/"; 59 description = '' 60 The context path, i.e., the last part of the Airsonic 61 URL. Typically '/' or '/airsonic'. Default '/' 62 ''; 63 }; 64 65 maxMemory = mkOption { 66 type = types.int; 67 default = 100; 68 description = '' 69 The memory limit (max Java heap size) in megabytes. 70 Default: 100 71 ''; 72 }; 73 74 transcoders = mkOption { 75 type = types.listOf types.path; 76 default = [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ]; 77 defaultText = literalExpression ''[ "''${pkgs.ffmpeg.bin}/bin/ffmpeg" ]''; 78 description = '' 79 List of paths to transcoder executables that should be accessible 80 from Airsonic. Symlinks will be created to each executable inside 81 ${cfg.home}/transcoders. 82 ''; 83 }; 84 85 jre = mkOption { 86 type = types.package; 87 default = pkgs.jre8; 88 defaultText = literalExpression "pkgs.jre8"; 89 description = '' 90 JRE package to use. 91 92 Airsonic only supports Java 8, airsonic-advanced requires at least 93 Java 11. 94 ''; 95 }; 96 97 war = mkOption { 98 type = types.path; 99 default = "${pkgs.airsonic}/webapps/airsonic.war"; 100 defaultText = literalExpression ''"''${pkgs.airsonic}/webapps/airsonic.war"''; 101 description = "Airsonic war file to use."; 102 }; 103 104 jvmOptions = mkOption { 105 description = '' 106 Extra command line options for the JVM running AirSonic. 107 Useful for sending jukebox output to non-default alsa 108 devices. 109 ''; 110 default = [ 111 ]; 112 type = types.listOf types.str; 113 example = [ 114 "-Djavax.sound.sampled.Clip='#CODEC [plughw:1,0]'" 115 "-Djavax.sound.sampled.Port='#Port CODEC [hw:1]'" 116 "-Djavax.sound.sampled.SourceDataLine='#CODEC [plughw:1,0]'" 117 "-Djavax.sound.sampled.TargetDataLine='#CODEC [plughw:1,0]'" 118 ]; 119 }; 120 121 }; 122 }; 123 124 config = mkIf cfg.enable { 125 systemd.services.airsonic = { 126 description = "Airsonic Media Server"; 127 after = [ "network.target" ]; 128 wantedBy = [ "multi-user.target" ]; 129 130 preStart = '' 131 # Install transcoders. 132 rm -rf ${cfg.home}/transcode 133 mkdir -p ${cfg.home}/transcode 134 for exe in ${toString cfg.transcoders}; do 135 ln -sf "$exe" ${cfg.home}/transcode 136 done 137 ''; 138 serviceConfig = { 139 ExecStart = '' 140 ${cfg.jre}/bin/java -Xmx${toString cfg.maxMemory}m \ 141 -Dairsonic.home=${cfg.home} \ 142 -Dserver.address=${cfg.listenAddress} \ 143 -Dserver.port=${toString cfg.port} \ 144 -Dairsonic.contextPath=${cfg.contextPath} \ 145 -Djava.awt.headless=true \ 146 ${optionalString (cfg.virtualHost != null) 147 "-Dserver.use-forward-headers=true"} \ 148 ${toString cfg.jvmOptions} \ 149 -verbose:gc \ 150 -jar ${cfg.war} 151 ''; 152 Restart = "always"; 153 User = "airsonic"; 154 UMask = "0022"; 155 }; 156 }; 157 158 services.nginx = mkIf (cfg.virtualHost != null) { 159 enable = true; 160 recommendedProxySettings = true; 161 virtualHosts.${cfg.virtualHost} = { 162 locations.${cfg.contextPath}.proxyPass = "http://${cfg.listenAddress}:${toString cfg.port}"; 163 }; 164 }; 165 166 users.users.airsonic = { 167 description = "Airsonic service user"; 168 group = "airsonic"; 169 name = cfg.user; 170 home = cfg.home; 171 createHome = true; 172 isSystemUser = true; 173 }; 174 users.groups.airsonic = {}; 175 }; 176}