From f7384470de0df8e7b82596ae53c86abf2001ab2f Mon Sep 17 00:00:00 2001 From: sohalt Date: Thu, 24 Dec 2020 00:04:10 +0100 Subject: [PATCH 1/2] nixos/mpd: support passwords in separate files This allows to use files containing only the mpd password without the permissions, making it easier for other programs connecting to mpd to read the password from the same password file. --- nixos/modules/services/audio/mpd.nix | 63 ++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix index e09e4861646c..818177f15f7a 100644 --- a/nixos/modules/services/audio/mpd.nix +++ b/nixos/modules/services/audio/mpd.nix @@ -10,6 +10,14 @@ let gid = config.ids.gids.mpd; cfg = config.services.mpd; + credentialsPlaceholder = (creds: + let + placeholders = (imap0 + (i: c: ''password "{{password-${toString i}}}@${concatStringsSep "," c.permissions}"'') + creds); + in + concatStringsSep "\n" placeholders); + mpdConf = pkgs.writeText "mpd.conf" '' # This file was automatically generated by NixOS. Edit mpd's configuration # via NixOS' configuration.nix, as this file will be rewritten upon mpd's @@ -32,6 +40,8 @@ let } ''} + ${credentialsPlaceholder cfg.credentials} + ${cfg.extraConfig} ''; @@ -152,6 +162,37 @@ in { ''; }; + credentials = mkOption { + type = types.listOf (types.submodule { + options = { + passwordFile = mkOption { + type = types.path; + description = '' + Path to file containing the password. + ''; + }; + permissions = let + perms = ["read" "add" "control" "admin"]; + in mkOption { + type = types.listOf (types.enum perms); + default = [ "read" ]; + description = '' + List of permissions that are granted with this password. + Permissions can be "${concatStringsSep "\", \"" perms}". + ''; + }; + }; + }); + description = '' + Credentials and permissions for accessing the mpd server. + ''; + default = []; + example = [ + {passwordFile = "/var/lib/secrets/mpd_readonly_password"; permissions = [ "read" ];} + {passwordFile = "/var/lib/secrets/mpd_admin_password"; permissions = ["read" "add" "control" "admin"];} + ]; + }; + credentialsFile = mkOption { type = types.path; description = '' @@ -201,12 +242,16 @@ in { serviceConfig = mkMerge [ { User = "${cfg.user}"; - ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon /etc/mpd.conf"; - ExecStartPre = pkgs.writeScript "mpd-start-pre" '' - #!${pkgs.runtimeShell} - set -euo pipefail - cat ${mpdConf} ${cfg.credentialsFile} > /etc/mpd.conf + ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon /run/mpd/mpd.conf"; + ExecStartPre = pkgs.writeShellScript "mpd-start-pre" '' + set -xeuo pipefail + umask 077 + cat ${mpdConf} ${cfg.credentialsFile} > /run/mpd/mpd.conf + ${pkgs.replace}/bin/replace-literal -fe ${ + concatStringsSep " -a " (imap0 (i: c: "\"{{password-${toString i}}}\" \"$(cat ${c.passwordFile})\"") cfg.credentials) + } /run/mpd/mpd.conf ''; + RuntimeDirectory = "mpd"; Type = "notify"; LimitRTPRIO = 50; LimitRTTIME = "infinity"; @@ -230,14 +275,6 @@ in { }) ]; }; - environment.etc."mpd.conf" = { - mode = "0640"; - group = cfg.group; - user = cfg.user; - # To be modified by the service' ExecStartPre - text = '' - ''; - }; users.users = optionalAttrs (cfg.user == name) { ${name} = { From dcbfdf1a71de390bbdcd88dbc95d6bc03ad50a6f Mon Sep 17 00:00:00 2001 From: sohalt Date: Sat, 26 Dec 2020 17:53:01 +0100 Subject: [PATCH 2/2] nixos/mpd: remove credentialsFile in favor of credentials option --- nixos/modules/services/audio/mpd.nix | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix index 818177f15f7a..c8e5045f6dc2 100644 --- a/nixos/modules/services/audio/mpd.nix +++ b/nixos/modules/services/audio/mpd.nix @@ -193,18 +193,6 @@ in { ]; }; - credentialsFile = mkOption { - type = types.path; - description = '' - Path to a file to be merged with the settings during the service startup. - Useful to merge a file which is better kept out of the Nix store - because it contains sensible data like MPD's password. Example may look like this: - password "myMpdPassword@read,add,control,admin" - ''; - default = "/dev/null"; - example = "/var/lib/secrets/mpd.conf"; - }; - fluidsynth = mkOption { type = types.bool; default = false; @@ -244,9 +232,8 @@ in { User = "${cfg.user}"; ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon /run/mpd/mpd.conf"; ExecStartPre = pkgs.writeShellScript "mpd-start-pre" '' - set -xeuo pipefail - umask 077 - cat ${mpdConf} ${cfg.credentialsFile} > /run/mpd/mpd.conf + set -euo pipefail + install -m 600 ${mpdConf} /run/mpd/mpd.conf ${pkgs.replace}/bin/replace-literal -fe ${ concatStringsSep " -a " (imap0 (i: c: "\"{{password-${toString i}}}\" \"$(cat ${c.passwordFile})\"") cfg.credentials) } /run/mpd/mpd.conf