{ pkgs, config, python3Packages, ... }: let shairport-sync = pkgs.shairport-sync.overrideAttrs (_: { configureFlags = [ "--with-alsa" "--with-pipe" "--with-pa" "--with-stdout" "--with-avahi" "--with-ssl=openssl" "--with-soxr" # "--with-mqtt-client" "--without-configfiles" "--sysconfdir=/etc" "--with-metadata" ]; # buildInputs = [ # pkgs.openssl # pkgs.avahi # pkgs.popt # pkgs.libconfig # pkgs.mosquitto # pkgs.alsa-lib # pkgs.libpulseaudio # pkgs.pipewire # pkgs.libjack2 # pkgs.soxr # ]; }); in { environment.etc = { # Creates /etc/nanorc shairport = { text = '' whatever you want to put in the file goes here. metadata = { enabled = "yes"; // set this to yes to get Shairport Sync to solicit metadata from the source and to pass it on via a pipe include_cover_art = "yes"; // set to "yes" to get Shairport Sync to solicit cover art from the source and pass it via the pipe. You must also set "enabled" to "yes". cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; // artwork will be stored in this directory if the dbus or MPRIS interfaces are enabled or if the MQTT client is in use. Set it to "" to prevent caching, which may be useful on some systems pipe_name = "/tmp/shairport-sync-metadata"; pipe_timeout = 5000; // wait for this number of milliseconds for a blocked pipe to unblock before giving up }; mqtt = { enabled = "yes"; // set this to yes to enable the mqtt-metadata-service hostname = "127.0.0.1"; // Hostname of the MQTT Broker port = 1883; // Port on the MQTT Broker to connect to username = "espresense"; //set this to a string to your username in order to enable username authentication password = "insecure-password"; //set this to a string you your password in order to enable username & password authentication topic = "shairport"; //MQTT topic where this instance of shairport-sync should publish. If not set, the general.name value is used. // publish_raw = "no"; //whether to publish all available metadata under the codes given in the 'metadata' docs. publish_parsed = "yes"; //whether to publish a small (but useful) subset of metadata under human-understandable topics publish_cover = "yes"; //whether to publish the cover over mqtt in binary form. This may lead to a bit of load on the broker // enable_remote = "no"; //whether to remote control via MQTT. RC is available under `topic`/remote. }; ''; # The UNIX file mode bits mode = "0440"; }; }; services.snapserver = { enable = true; codec = "flac"; http.docRoot = "${pkgs.snapcast}/share/snapserver/snapweb"; streams.mopidy = { type = "pipe"; location = "/run/snapserver/mopidy"; }; streams.airplay = { type = "airplay"; location = "${shairport-sync}/bin/shairport-sync"; query = { devicename = "Multi Room"; port = "5000"; params = "--mdns=avahi"; }; }; streams.mixed = { type = "meta"; location = "/airplay/mopidy"; }; }; services.avahi.enable = true; services.avahi.publish.enable = true; services.avahi.publish.userServices = true; # services.shairport-sync = { # enable = true; # arguments = "-v -o=pipe -- pipe:name=/run/snapserver/airplay"; # }; services.nginx.virtualHosts."snapcast.cloonar.com" = { forceSSL = true; enableACME = true; acmeRoot = null; extraConfig = '' proxy_buffering off; ''; locations."/".extraConfig = '' proxy_pass http://127.0.0.1:1780; proxy_set_header Host $host; proxy_redirect http:// https://; proxy_http_version 1.1; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; ''; }; networking.firewall.allowedTCPPorts = [ 80 # http 443 # https 1704 # snapcast 1705 # snapcast 5000 # airplay 5353 # airplay ]; networking.firewall.allowedUDPPorts = [ 5000 # airplay 5353 # airplay ]; networking.firewall.allowedUDPPortRanges = [ { from = 6001; to = 6011; } # airplay ]; }