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