python3Packages.orjson: Disable failing tests on 32 bit
[NixPkgs.git] / nixos / modules / services / misc / airsonic.nix
blobb8e9dcaf466314234b3323dd503cfa6db00acbba
1 { config, lib, options, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.airsonic;
7   opt = options.services.airsonic;
8 in {
9   options = {
11     services.airsonic = {
12       enable = mkEnableOption (lib.mdDoc "Airsonic, the Free and Open Source media streaming server (fork of Subsonic and Libresonic)");
14       user = mkOption {
15         type = types.str;
16         default = "airsonic";
17         description = lib.mdDoc "User account under which airsonic runs.";
18       };
20       home = mkOption {
21         type = types.path;
22         default = "/var/lib/airsonic";
23         description = lib.mdDoc ''
24           The directory where Airsonic will create files.
25           Make sure it is writable.
26         '';
27       };
29       virtualHost = mkOption {
30         type = types.nullOr types.str;
31         default = null;
32         description = lib.mdDoc ''
33           Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost.
34         '';
35       };
37       listenAddress = mkOption {
38         type = types.str;
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.
47         '';
48       };
50       port = mkOption {
51         type = types.port;
52         default = 4040;
53         description = lib.mdDoc ''
54           The port on which Airsonic will listen for
55           incoming HTTP traffic. Set to 0 to disable.
56         '';
57       };
59       contextPath = mkOption {
60         type = types.path;
61         default = "/";
62         description = lib.mdDoc ''
63           The context path, i.e., the last part of the Airsonic
64           URL. Typically '/' or '/airsonic'. Default '/'
65         '';
66       };
68       maxMemory = mkOption {
69         type = types.int;
70         default = 100;
71         description = lib.mdDoc ''
72           The memory limit (max Java heap size) in megabytes.
73           Default: 100
74         '';
75       };
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.
85         '';
86       };
88       jre = mkOption {
89         type = types.package;
90         default = pkgs.jre8;
91         defaultText = literalExpression "pkgs.jre8";
92         description = lib.mdDoc ''
93           JRE package to use.
95           Airsonic only supports Java 8, airsonic-advanced requires at least
96           Java 11.
97         '';
98       };
100       war = mkOption {
101         type = types.path;
102         default = "${pkgs.airsonic}/webapps/airsonic.war";
103         defaultText = literalExpression ''"''${pkgs.airsonic}/webapps/airsonic.war"'';
104         description = lib.mdDoc "Airsonic war file to use.";
105       };
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
111           devices.
112         '';
113         default = [
114         ];
115         type = types.listOf types.str;
116         example = [
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]'"
121         ];
122       };
124     };
125   };
127   config = mkIf cfg.enable {
128     systemd.services.airsonic = {
129       description = "Airsonic Media Server";
130       after = [ "network.target" ];
131       wantedBy = [ "multi-user.target" ];
133       preStart = ''
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
139         done
140       '';
141       serviceConfig = {
142         ExecStart = ''
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} \
152           -verbose:gc \
153           -jar ${cfg.war}
154         '';
155         Restart = "always";
156         User = "airsonic";
157         UMask = "0022";
158       };
159     };
161     services.nginx = mkIf (cfg.virtualHost != null) {
162       enable = true;
163       recommendedProxySettings = true;
164       virtualHosts.${cfg.virtualHost} = {
165         locations.${cfg.contextPath}.proxyPass = "http://${cfg.listenAddress}:${toString cfg.port}";
166       };
167     };
169     users.users.airsonic = {
170       description = "Airsonic service user";
171       group = "airsonic";
172       name = cfg.user;
173       home = cfg.home;
174       createHome = true;
175       isSystemUser = true;
176     };
177     users.groups.airsonic = {};
178   };