Agenix encrypted password in mysql initialScript

Hi,

I was hoping to use agenix to encrypt a password used in mysql initialScript.
I wrote this

{ lib, config, pkgs, ... }:

let
  inherit (config.networking) hostName;
  cfg = config.mod-mysql;
  pwd = config.age.secrets."${hostName}.mysql.pwd".path;
in
{
  
  ###
  options = {
    mod-mysql = {
      enable = lib.mkEnableOption "MySQL.";
    };
  };

  ###
  config = lib.mkIf cfg.enable {
    services.mysql = {
      enable = true;
      package = pkgs.mariadb;
      initialScript = pkgs.writeText "mysql-init.sql" ''
        CREATE USER IF NOT EXISTS '${hostName}'@'localhost' IDENTIFIED BY '${pwd}';
        GRANT ALL PRIVILEGES ON *.* TO '${hostName}'@'localhost';
        FLUSH PRIVILEGES;
      '';
    };
  };
}

But the password that I get is /run/agenix/.... and not the decrypted password

Is there a way to use agenix with an sql script ?

I’ve found a solution that works, but is this the right way to do it?

I used system.activationScripts instead of services.mysql.initialScript

    system.activationScripts = {
      mysql = {
        text = ''
          ${config.services.mysql.package}/bin/mysql -u root -e "CREATE USER IF NOT EXISTS '${hostName}'@'localhost' IDENTIFIED BY '$(cat ${pwd})';"
          ${config.services.mysql.package}/bin/mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO '${hostName}'@'localhost';"
          ${config.services.mysql.package}/bin/mysql -u root -e "FLUSH PRIVILEGES;"
        '';
        deps = [ "mysql" ];
      };
    };
1 Like

Right, the decrypted secret isn’t available at the time the script is created, just the file path of where it will be decrypted to.

I just tried to define the script with system.services.mysql.postStart, but it doesn’t work as expected.

    systemd.services.mysql.postStart = ''
      ( echo "CREATE USER IF NOT EXISTS '${hostName}'@'localhost' IDENTIFIED BY  '$(cat ${pwd})';"
        echo "GRANT ALL PRIVILEGES ON *.* TO '${hostName}'@'localhost';"
        echo "FLUSH PRIVILEGES;"
      ) | ${config.services.mysql.package}/bin/mysql -N
    '';

the user is created but there’s no password.

Resulting script after build on the server is

( echo "CREATE USER IF NOT EXISTS 'hydrogen'@'localhost' IDENTIFIED BY '$(cat /run/agenix/hydrogen.mysql.pwd)';"
  echo "GRANT ALL PRIVILEGES ON *.* TO 'hydrogen'@'localhost';"
  echo "FLUSH PRIVILEGES;"
) | /nix/store/92i38gv0fl2ri98ih9avy4pynspk7r33-mariadb-server-10.11.6/bin/mysql -N

If I launch this resulting script in the terminal it works fine, the user is created with a password.

Any ideas on how to solve this ?

Got it !
Needed to change the owner of the secrets file to "mysql"

    age.secrets."${hostName}.mysql.pwd" = {
      file = ./secrets/mysql.pwd;
      owner = "mysql";
    };
2 Likes