1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 name = "roon-server";
7 cfg = config.services.roon-server;
8in {
9 options = {
10 services.roon-server = {
11 enable = mkEnableOption (lib.mdDoc "Roon Server");
12 openFirewall = mkOption {
13 type = types.bool;
14 default = false;
15 description = lib.mdDoc ''
16 Open ports in the firewall for the server.
17 '';
18 };
19 user = mkOption {
20 type = types.str;
21 default = "roon-server";
22 description = lib.mdDoc ''
23 User to run the Roon Server as.
24 '';
25 };
26 group = mkOption {
27 type = types.str;
28 default = "roon-server";
29 description = lib.mdDoc ''
30 Group to run the Roon Server as.
31 '';
32 };
33 };
34 };
35
36 config = mkIf cfg.enable {
37 systemd.services.roon-server = {
38 after = [ "network.target" ];
39 description = "Roon Server";
40 wantedBy = [ "multi-user.target" ];
41
42 environment.ROON_DATAROOT = "/var/lib/${name}";
43 environment.ROON_ID_DIR = "/var/lib/${name}";
44
45 serviceConfig = {
46 ExecStart = "${pkgs.roon-server}/bin/RoonServer";
47 LimitNOFILE = 8192;
48 User = cfg.user;
49 Group = cfg.group;
50 StateDirectory = name;
51 };
52 };
53
54 networking.firewall = mkIf cfg.openFirewall {
55 allowedTCPPortRanges = [
56 { from = 9100; to = 9200; }
57 { from = 9330; to = 9339; }
58 { from = 30000; to = 30010; }
59 ];
60 allowedUDPPorts = [ 9003 ];
61 extraCommands = optionalString (!config.networking.nftables.enable) ''
62 ## IGMP / Broadcast ##
63 iptables -A INPUT -s 224.0.0.0/4 -j ACCEPT
64 iptables -A INPUT -d 224.0.0.0/4 -j ACCEPT
65 iptables -A INPUT -s 240.0.0.0/5 -j ACCEPT
66 iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
67 iptables -A INPUT -m pkttype --pkt-type broadcast -j ACCEPT
68 '';
69 extraInputRules = optionalString config.networking.nftables.enable ''
70 ip saddr { 224.0.0.0/4, 240.0.0.0/5 } accept
71 ip daddr 224.0.0.0/4 accept
72 pkttype { multicast, broadcast } accept
73 '';
74 };
75
76
77 users.groups.${cfg.group} = {};
78 users.users.${cfg.user} =
79 if cfg.user == "roon-server" then {
80 isSystemUser = true;
81 description = "Roon Server user";
82 group = cfg.group;
83 extraGroups = [ "audio" ];
84 }
85 else {};
86 };
87}