Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to use agenix.homeManagerModules.default on Darwin to manage an SSH-key? #260

Open
pimvh opened this issue May 11, 2024 · 2 comments
Open

Comments

@pimvh
Copy link

pimvh commented May 11, 2024

Hi there! Thanks for this great project! I have been happily using this for a while, and it works great, both for Linux and Darwin.

I have been fighting a while with using the home-manager module on darwin of this project to manage secret files (SSH key in my case) within my home folder, and cannot figure it out (system-wide using nix-darwin works great!).

I have looked at related issues, like

Attempt 1: just using path as 'normal'

By doing the following in home-manager

    programs.ssh = {
      enable = true;
      extraOptionOverrides = { };

      matchBlocks = {
        "github.com" = {
          user = "git";
          identityFile = config.age.secrets.githubKey.path;
        };

and this with agenix:

{ config, ... }: {
  age = {
    secrets = {
      ...

      githubKey = {
        file = ./github.age;
      };
      
      ...

    };

    identityPaths = [ "..." ];
  };
}

I get the following result:

Host github.com
  User git
  IdentityFile $(getconf DARWIN_USER_TEMP_DIR)/agenix/githubStubSshKey

Usage of env variables is supported in ~/.ssh/config by using ${VAR} syntax, but DARWIN_USER_TEMP_DIR is not exposed as a normal env variable to the user (only via getconf), which is different from the linux behaviour

source: https://github.com/ryantm/agenix/blob/8d37c5bdeade12b6479c85acd133063ab53187a0/modules/age-home.nix#L148C15-L148C22

Attempt 2: workaround using DAGS

As i noticed the darwin part of home-manager relies on shell, I have tried using a DAG, but now getconf is not available as a command in the build context (this currently only works on home-manager unstable, run is only available there).

home.activation.linkSshKeys = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
  run ln -s $VERBOSE_ARG ${config.pimvh.homeDirectory}/.ssh/github "${config.age.secrets.githubStubSshKey.path}"
'';

I am unsure whether either I am using agenix incorrectly, or have an incorrect idea on how I am supposed to achieve this. I think not using getconf might also be able to solve this issue for me, but that might have a security impact. I have been unable to find docs on why this is different across Darwin/Linux.

Could you point me in the right direction? :)

I would be happy to contribute to docs, when I figure out the proper solution.

@pimvh pimvh changed the title Using agenix.homeManagerModules.default on Darwin how to use agenix.homeManagerModules.default on Darwin to manage an SSH-key? May 11, 2024
@pimvh
Copy link
Author

pimvh commented May 29, 2024

I managed to fix this by doing the following voodoo, which works, but might not be the greatest solution to ever exist:

...
    home.sessionVariables = lib.mkIf config.pimvh.isNixDarwin {
      # getconf wants to append \n to the config var, which is why we need this voodoo
      DARWIN_USER_TEMP_DIR = with pkgs; ''$(${pkgs.coreutils}/bin/printf '%s' "$(${lib.getExe getconf} DARWIN_USER_TEMP_DIR)" | ${pkgs.coreutils}/bin/tr -d "\n")'';
    };

    home.file.".ssh/github.pub".source = "${self}/dotfiles/.ssh/github_${config.pimvh.hostname}.pub";

    programs.ssh =
      let
        turnAgenixPathToSshCompatible = x:
          if config.pimvh.isNixDarwin then
          # turn $(getconf $DARWIN_USER_TEMP_DIR)/<< PATH >>
          # into ${ENV_VAR}/<< PATH >>
            "\${DARWIN_USER_TEMP_DIR}${lib.concatStrings (lib.strings.match ".*\)(.*)" (builtins.toString x))}"
          else
          # turn $XDG_RUNTIME_DIR/<< PATH >>
          # into ${ENV_VAR}/<< PATH >>
            "\${XDG_RUNTIME_DIR}${lib.concatStrings (lib.strings.match ".[A-Z_]+\(.*\)" (builtins.toString x))}"
        ;
      in
      {
        enable = true;
        addKeysToAgent = "yes";
        # UseKeychain does not work with non-system versions of ssh
        # Which we have to rely on due to yubikey not being supported, see modules/darwin/yubikey.nix

        # extraConfig = lib.mkIf config.pimvh.isNixDarwin ''
        #   UseKeychain yes
        # '';

        matchBlocks = {
          "github.com" = {
            user = "git";
            identityFile = turnAgenixPathToSshCompatible config.age.secrets.githubKey.path;
          };
...

I can generalize and contribute (part of) this to home-manager, but I am not sure whether it would be a good fit.

@n8henrie
Copy link
Collaborator

n8henrie commented Jun 1, 2024

This getconf DARWIN_USER_TEMP_DIR business seems like a pain, and I'm not sure why we're doing it that way.

On my system it evaluates the same as $TMPDIR, though I imagine we don't have access to this variable either.

$ test $(getconf DARWIN_USER_TEMP_DIR) = $TMPDIR && echo yup
yup

I see zero references to DARWIN_USER_TEMP_DIR in all of nixpkgs or home-manager, so it doesn't seem that anybody else is doing anything this way.

I'm sure there has been prior discussion on this. Seems like it should ideally be a directory that does not persist across reboots and obviously needs to be one with user permissions for creating files (which seems to rule out /run on MacOS).

I don't think stuff in ~/Library/Caches is cleared on reboot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants