1 { config, lib, options, pkgs, ... }:
6 cfg = config.services.airsonic;
7 opt = options.services.airsonic;
12 enable = mkEnableOption (lib.mdDoc "Airsonic, the Free and Open Source media streaming server (fork of Subsonic and Libresonic)");
17 description = lib.mdDoc "User account under which airsonic runs.";
22 default = "/var/lib/airsonic";
23 description = lib.mdDoc ''
24 The directory where Airsonic will create files.
25 Make sure it is writable.
29 virtualHost = mkOption {
30 type = types.nullOr types.str;
32 description = lib.mdDoc ''
33 Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost.
37 listenAddress = mkOption {
39 default = "127.0.0.1";
40 description = lib.mdDoc ''
41 The host name or IP address on which to bind Airsonic.
42 The default value is appropriate for first launch, when the
43 default credentials are easy to guess. It is also appropriate
44 if you intend to use the virtualhost option in the service
45 module. In other cases, you may want to change this to a
46 specific IP or 0.0.0.0 to listen on all interfaces.
53 description = lib.mdDoc ''
54 The port on which Airsonic will listen for
55 incoming HTTP traffic. Set to 0 to disable.
59 contextPath = mkOption {
62 description = lib.mdDoc ''
63 The context path, i.e., the last part of the Airsonic
64 URL. Typically '/' or '/airsonic'. Default '/'
68 maxMemory = mkOption {
71 description = lib.mdDoc ''
72 The memory limit (max Java heap size) in megabytes.
77 transcoders = mkOption {
78 type = types.listOf types.path;
79 default = [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ];
80 defaultText = literalExpression ''[ "''${pkgs.ffmpeg.bin}/bin/ffmpeg" ]'';
81 description = lib.mdDoc ''
82 List of paths to transcoder executables that should be accessible
83 from Airsonic. Symlinks will be created to each executable inside
84 ''${config.${opt.home}}/transcoders.
91 defaultText = literalExpression "pkgs.jre8";
92 description = lib.mdDoc ''
95 Airsonic only supports Java 8, airsonic-advanced requires at least
102 default = "${pkgs.airsonic}/webapps/airsonic.war";
103 defaultText = literalExpression ''"''${pkgs.airsonic}/webapps/airsonic.war"'';
104 description = lib.mdDoc "Airsonic war file to use.";
107 jvmOptions = mkOption {
108 description = lib.mdDoc ''
109 Extra command line options for the JVM running AirSonic.
110 Useful for sending jukebox output to non-default alsa
115 type = types.listOf types.str;
117 "-Djavax.sound.sampled.Clip='#CODEC [plughw:1,0]'"
118 "-Djavax.sound.sampled.Port='#Port CODEC [hw:1]'"
119 "-Djavax.sound.sampled.SourceDataLine='#CODEC [plughw:1,0]'"
120 "-Djavax.sound.sampled.TargetDataLine='#CODEC [plughw:1,0]'"
127 config = mkIf cfg.enable {
128 systemd.services.airsonic = {
129 description = "Airsonic Media Server";
130 after = [ "network.target" ];
131 wantedBy = [ "multi-user.target" ];
134 # Install transcoders.
135 rm -rf ${cfg.home}/transcode
136 mkdir -p ${cfg.home}/transcode
137 for exe in ${toString cfg.transcoders}; do
138 ln -sf "$exe" ${cfg.home}/transcode
143 ${cfg.jre}/bin/java -Xmx${toString cfg.maxMemory}m \
144 -Dairsonic.home=${cfg.home} \
145 -Dserver.address=${cfg.listenAddress} \
146 -Dserver.port=${toString cfg.port} \
147 -Dairsonic.contextPath=${cfg.contextPath} \
148 -Djava.awt.headless=true \
149 ${optionalString (cfg.virtualHost != null)
150 "-Dserver.use-forward-headers=true"} \
151 ${toString cfg.jvmOptions} \
161 services.nginx = mkIf (cfg.virtualHost != null) {
163 recommendedProxySettings = true;
164 virtualHosts.${cfg.virtualHost} = {
165 locations.${cfg.contextPath}.proxyPass = "http://${cfg.listenAddress}:${toString cfg.port}";
169 users.users.airsonic = {
170 description = "Airsonic service user";
177 users.groups.airsonic = {};