{ ... }:
{
  _class = "clan.service";
  manifest.name = "jukebox";
  manifest.description = "mpd server, library on removable disks";
  manifest.readme = "mpd server, library on removable disks";
  manifest.categories = [ "System" ];

  roles.default = {
    description = "a default server role";
    interface =
      { lib, ... }:
      {
        options = {
          baseDir = lib.mkOption {
            type = lib.types.str;
            default = "/mnt/jukebox";
          };
          binds = lib.mkOption {
            type = with lib.types; listOf str;
            default = [ ];
          };
          disks = lib.mkOption {
            type =
              with lib.types;
              attrsOf (
                submodule (
                  { name, ... }:
                  {
                    options = {
                      name = lib.mkOption {
                        type = str;
                        default = name;
                      };
                      uuid = lib.mkOption {
                        type = str;
                      };
                      mountOptions = lib.mkOption {
                        type = listOf str;
                        default = [ ];
                      };
                    };
                  }
                )
              );
            default = { };
            description = "disks comprising library";
          };
        };
      };
    perInstance =
      {
        settings,
        ...
      }:
      {
        nixosModule =
          {
            config,
            lib,
            pkgs,
            ...
          }:
          {
            services.pulseaudio.enable = true;

            # workaround cookie permissions
            services.pulseaudio.tcp.enable = true;
            services.pulseaudio.tcp.anonymousClients = {
              allowedIpRanges = [ "127.0.0.1" ];
              allowAll = true;
            };

            systemd.tmpfiles.rules = [
              "d ${settings.baseDir} 0755 root root"
            ];

            fileSystems =
              let
                disk2fs =
                  {
                    name,
                    uuid,
                    mountOptions,
                    ...
                  }:
                  lib.nameValuePair "${settings.baseDir}/${name}" {
                    device = "/dev/disk/by-uuid/${uuid}";
                    fsType = "auto";
                    options = [
                      "noauto"
                      "nofail"
                    ]
                    ++ mountOptions;
                  };
              in
              lib.listToAttrs (lib.mapAttrsToList (_: disk2fs) settings.disks);

            services.udev.extraRules =
              let
                translate-prefix = path: (lib.removePrefix "-" (lib.replaceStrings [ "/" ] [ "-" ] path));
                mount-name = name: "${translate-prefix settings.baseDir}-${name}.mount";
                disk2rule =
                  { name, uuid, ... }:
                  lib.concatStringsSep ", " [
                    ''ACTION=="add"''
                    ''SUBSYSTEM=="block"''
                    ''ENV{DEVLINKS}=="*/dev/disk/by-uuid/${uuid}*"''
                    ''ENV{SYSTEMD_WANTS}="${mount-name name}"''
                  ];
              in
              lib.concatMapStringsSep "\n" disk2rule (lib.attrValues settings.disks);

            services.mpd = {
              enable = true;
              openFirewall = true;
              settings = {
                bind_to_address = "any";
                music_directory = settings.baseDir;
                audio_output = [
                  {
                    type = "pulse";
                    name = "jukebox";
                    server = "localhost";
                  }
                ];
              };
            };

            networking.firewall.interfaces = lib.genAttrs settings.binds (_: {
              allowedTCPPorts = [ config.services.mpd.settings.port ];
            });

            environment.systemPackages = [ pkgs.mpc ];
          };
      };
  };
}
