at 25.11-pre 4.1 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 12 cfg = config.services.shairport-sync; 13 configFormat = pkgs.formats.libconfig { }; 14 configFile = configFormat.generate "shairport-sync.conf" cfg.settings; 15in 16 17{ 18 19 ###### interface 20 21 options = { 22 23 services.shairport-sync = { 24 25 enable = mkOption { 26 type = types.bool; 27 default = false; 28 description = '' 29 Enable the shairport-sync daemon. 30 31 Running with a local system-wide or remote pulseaudio server 32 is recommended. 33 ''; 34 }; 35 36 package = lib.options.mkPackageOption pkgs "shairport-sync" { }; 37 38 settings = mkOption { 39 type = configFormat.type; 40 default = { 41 general.output_backend = "pa"; 42 diagnostics.log_verbosity = 1; 43 }; 44 example = { 45 general = { 46 name = "NixOS Shairport"; 47 output_backend = "pw"; 48 }; 49 metadata = { 50 enabled = "yes"; 51 include_cover_art = "yes"; 52 cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; 53 pipe_name = "/tmp/shairport-sync-metadata"; 54 pipe_timeout = 5000; 55 }; 56 mqtt = { 57 enabled = "yes"; 58 hostname = "mqtt.server.domain.example"; 59 port = 1883; 60 publish_parsed = "yes"; 61 publish_cover = "yes"; 62 }; 63 }; 64 description = '' 65 Configuration options for Shairport-Sync. 66 67 See the example [shairport-sync.conf][example-file] for possible options. 68 69 [example-file]: https://github.com/mikebrady/shairport-sync/blob/master/scripts/shairport-sync.conf 70 ''; 71 }; 72 73 arguments = mkOption { 74 type = types.str; 75 default = ""; 76 description = '' 77 Arguments to pass to the daemon. Defaults to a local pulseaudio 78 server. 79 ''; 80 }; 81 82 openFirewall = mkOption { 83 type = types.bool; 84 default = false; 85 description = '' 86 Whether to automatically open ports in the firewall. 87 ''; 88 }; 89 90 user = mkOption { 91 type = types.str; 92 default = "shairport"; 93 description = '' 94 User account name under which to run shairport-sync. The account 95 will be created. 96 ''; 97 }; 98 99 group = mkOption { 100 type = types.str; 101 default = "shairport"; 102 description = '' 103 Group account name under which to run shairport-sync. The account 104 will be created. 105 ''; 106 }; 107 108 }; 109 110 }; 111 112 ###### implementation 113 114 config = mkIf config.services.shairport-sync.enable { 115 116 services.avahi.enable = true; 117 services.avahi.publish.enable = true; 118 services.avahi.publish.userServices = true; 119 120 services.shairport-sync.settings = { 121 general.output_backend = lib.mkDefault "pa"; 122 diagnostics.log_verbosity = lib.mkDefault 1; 123 }; 124 125 users = { 126 users.${cfg.user} = { 127 description = "Shairport user"; 128 isSystemUser = true; 129 createHome = true; 130 home = "/var/lib/shairport-sync"; 131 group = cfg.group; 132 extraGroups = [ 133 "audio" 134 ] ++ optional (config.services.pulseaudio.enable || config.services.pipewire.pulse.enable) "pulse"; 135 }; 136 groups.${cfg.group} = { }; 137 }; 138 139 networking.firewall = mkIf cfg.openFirewall { 140 allowedTCPPorts = [ 5000 ]; 141 allowedUDPPortRanges = [ 142 { 143 from = 6001; 144 to = 6011; 145 } 146 ]; 147 }; 148 149 systemd.services.shairport-sync = { 150 description = "shairport-sync"; 151 after = [ 152 "network.target" 153 "avahi-daemon.service" 154 ]; 155 wantedBy = [ "multi-user.target" ]; 156 serviceConfig = { 157 User = cfg.user; 158 Group = cfg.group; 159 ExecStart = "${lib.getExe cfg.package} ${cfg.arguments}"; 160 Restart = "on-failure"; 161 RuntimeDirectory = "shairport-sync"; 162 }; 163 }; 164 165 environment = { 166 systemPackages = [ cfg.package ]; 167 etc."shairport-sync.conf".source = configFile; 168 }; 169 }; 170 171}