{ ... }: { _class = "clan.service"; manifest.name = "jukebox"; manifest.description = "mpd server, library on removable disks"; manifest.categories = [ "System" ]; roles.default = { 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; musicDirectory = settings.baseDir; network.listenAddress = "any"; extraConfig = '' audio_output { type "pulse" name "jukebox" server "localhost" } ''; }; networking.firewall.interfaces = lib.genAttrs settings.binds (_: { allowedTCPPorts = [config.services.mpd.network.port]; }); environment.systemPackages = [pkgs.mpc]; }; }; }; }