agenix icon indicating copy to clipboard operation
agenix copied to clipboard

home-manager integration?

Open Radvendii opened this issue 3 years ago • 27 comments

Is it possible to use agenix from inside a home-manager module? I don't see anything talking about this, so I'm guessing it's not possible, but I figured I'd check.

I realize I can use an agenix secret from inside a home-manager module by just accessing the /run/secrets/blah file, but I'd like to keep the file generation (i.e. age.secrets.blah.file = "${self}/secrets/blah";) close to the point of use, rather than off in it's own NixOS module.

Radvendii avatar Jul 05 '21 00:07 Radvendii

I don't think it will work by default. We'll need to update the module to work with it. This is definitely in scope for this project.

ryantm avatar Jul 05 '21 10:07 ryantm

A few of us came to a similar conclusion a while ago: https://github.com/divnix/devos/discussions/319. Thanks for actually opening the issue here.

Pacman99 avatar Jul 22 '21 20:07 Pacman99

This seems to have been attempted: https://github.com/jordanisaacs/homeage

I wonder if it would be possible / desireable to merge that into agenix, or better to leave it separate.

Radvendii avatar Nov 08 '21 15:11 Radvendii

Because both project try to achieve the same result except different build environments, these should at some point be merged. Ping @jordanisaacs for your opinion on that.

Gerschtli avatar Nov 08 '21 17:11 Gerschtli

The reason I wrote mine separately as I see my project being primarily a module for home-manager. My vision for homeage doesn't involve a CLI (interested only in the module) and its on pace to become more intimately tied to home-manager. So while both are similar, I see them as fitting different use cases: agenix for the system and CLI, homeage for declarative use with home-manager

jordanisaacs avatar Nov 08 '21 19:11 jordanisaacs

I think it would create a more consistent experience if the modules for NixOS and home-manager work the same (from a UX point of view). I agree, that agenix currently only supports system configuration, but a home-manager integration is possible. Also I think there are many common logic parts or scripts (like module options, the shell script for linking/copying, the cleanup logic, etc.) that could be shared between NixOS and home-manager implementation. That would improve the quality of both project because the actual logic only needs to be written once.

And the CLI seems to be replaced by agenix-cli in the future anyway.

Opinions @jordanisaacs @ryantm?

Gerschtli avatar Nov 11 '21 17:11 Gerschtli

Would be nice if agenix would work with home-manager as well. Just for the sake of uniformity in the config.

Nebucatnetzer avatar Nov 04 '22 17:11 Nebucatnetzer

This can probably be closed because of #180 ?

aouerf avatar Jun 25 '23 16:06 aouerf

I have seen that as well but how do you use it?On 25 Jun 2023, at 18:45, Ahmad Ouerfelli @.***> wrote: This can probably be closed because of #180 ?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>

Nebucatnetzer avatar Jun 25 '23 17:06 Nebucatnetzer

Yeah, I think it's reasonable to keep this open pending docs. I've used it already, so I can probably write it up today or tomorrow.

sellout avatar Jun 25 '23 19:06 sellout

That would be great!On 25 Jun 2023, at 21:09, Greg Pfeil @.***> wrote: Yeah, I think it's reasonable to keep this open pending docs. I've used it already, so I can probably write it up today or tomorrow.

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>

Nebucatnetzer avatar Jun 25 '23 21:06 Nebucatnetzer

any updates on this? Struggling to get it to work, tried adding agenix.homeManagerModules.age in my home-manager config to ìmports` but it keeps erroring out with "infinite recursion encountered" :/

Brawl345 avatar Jul 12 '23 12:07 Brawl345

Sorry, I apologize for not getting to this yet. I’ve only used it via flakes, where you do

    {
      homeConfigurations = {
        "user@host" = inputs.home-manager.lib.homeManagerConfiguration {
          modules = [
            inputs.agenix.homeManagerModules.age # ← the important bit
          ];
        };
      };
    };

for a non-flake config (like it sounds like you have, @Brawl345), I think you should instead do something like

{
  imports = [ <agenix/modules/age-home.nix> ];
}

that assumes you’re using nix channels, but the instructions here should translate from NixOS to home-manager with a few substitutions:

  • configuration.nix → home.nix
  • age.nix -> age-home.nix
  • nixosModules -> homeManagerModules

@Nebucatnetzer @Brawl345 – let me know if this short explanation solved your issues, so I know if my writeup will be correct.

sellout avatar Jul 13 '23 05:07 sellout

I use flakes with nix-darwin and home-manager as a nix-darwin module. I had some mistake in my (spaghetti) config and now everything works! Here is a minimal flake:

{
  description = "sample";

  inputs = {
    nixpkgs = {
      url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    };

    darwin = {
      url = "github:lnl7/nix-darwin/master";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    agenix = {
      url = "github:ryantm/agenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, darwin, home-manager, agenix, ... } @ inputs:
    {
      darwinConfigurations = {
        someuser = darwin.lib.darwinSystem {
          system = "aarch64-darwin";
          specialArgs = { inherit inputs; };
          modules = [
            agenix.darwinModules.default
            home-manager.darwinModules.home-manager
            {
              home-manager.useGlobalPkgs = true;
              home-manager.useUserPackages = true;
              home-manager.users.someuser = { config, pkgs, ... }: {
                programs.home-manager.enable = true;
                home.stateVersion = "22.11";
                manual.manpages.enable = false;
                manual.html.enable = false;
                manual.json.enable = false;
                programs.bash.enable = true;

                imports = [
                  agenix.homeManagerModules.default
                ];

                age.identityPaths = [ "/Users/someuser/.ssh/id_default_ed25519" ];
                age.secrets.secret1.file = ./secrets/secret1.age;
                home.sessionVariables = {
                  SECRET_VALUE = ''
                    $(${pkgs.coreutils}/bin/cat ${config.age.secrets.secret1.path})
                  '';
                };
              };
            }
          ];
        };
      };
    };
}

The age.identityPaths is very important or else nothing gets decrypted and you won't get an error. On NixOS it uses config.services.openssh.hostKeys.

Brawl345 avatar Jul 13 '23 18:07 Brawl345

I reckon with the examples by @sellout and @Brawl345 I should be able to integrate it.

Nebucatnetzer avatar Jul 14 '23 08:07 Nebucatnetzer

Hm I'm a bit confused. When I do offlineimap -o I get cat: '$XDG_RUNTIME_DIR/agenix/personalEmailKey': No such file or directory but when I run the command manually I see the password. The config is basically the same just with the new module. Here is a diff of the new config: https://git.2li.ch/Nebucatnetzer/nixos/pulls/3/files

Nebucatnetzer avatar Jul 17 '23 19:07 Nebucatnetzer

Hi, and thank you for this awesome package. So I see the same error as @Nebucatnetzer. It seems that age.secrets.github_token.file = ./secrets/github_token.age; results in ${config.age.secrets.github_token.path} being evaluated to /agenix/github_token

Since it results in the log /agenix/github_token: No such file or directory during switch.

(I use a flake).

/agenix/ folder does not exists on my computer. What is the folder supposed to be when using Home Manager Agenix Module? Thank you

[EDIT] Also when I update the secret I don't see any new generation in /run/agenix.d. I though I would see a new generation, but I am no expert in this package.

ldicarlo avatar Sep 08 '23 20:09 ldicarlo

I managed to do it. I think there are 2 problems:

  • in my case it seems that $XDG_RUNTIME_DIR was not interpolated as my home folder and was empty, so the secrets would be looked for in /agenix/ instead of / run/user/1000/agenix but i did not fix neither understand rightly this problem.
  • I think the user systemd service agenix.service was run only once and then not reran. Because once I did run it again then the secrets were updated and it worked.

Currently on a non-darwin system, this is what I have (and work):

  • (nowhere agenix.nixosModules.default )
  • In my home configuration (home-manager.users.luca) :

imports =
    [
      inputs.agenix.homeManagerModules.default
    ];
 age.secrets.secret1.file = ./secrets/sec1.age;

home.packages = [ 
    (pkgs.writeShellScriptBin "echo-secret" ''
      ${pkgs.coreutils}/bin/cat ${config.age.secrets.secret1.path}
    '')
];

secrets.nix with basic info like in the tutorial.

[EDIT] Just to confirm, each time I run agenix -e ... and then nixos-rebuild switch ... I still need to run systemctl --user start agenix.service after.

ldicarlo avatar Sep 09 '23 20:09 ldicarlo

I can’t remember it from the top of my head but I think there is a way to force a restart of a service after a rebuild. Might be a useful workaround for this. I hadn’t had time yet to try a second time but I hope to be able to test it soon.

Nebucatnetzer avatar Sep 18 '23 08:09 Nebucatnetzer

I'm having a similar issue with Home Manager+Agenix, and the $XDG_RUNTIME_DIR.

I'm basically storing my Taskwarrior sync CA/certificate/key, and credentials in Age-encrypted files.

My home manager configuration is fairly simple. The secrets can be decrypted, but the produced file for Taskwarrior keeps the $XDG_RUNTIME_DIR path in the config. This is invalid for Taskwarrior, and I'm a little unsure of how to proceed. I think this is something that could be extended in Agenix to have an output with the full, expanded path to the decrypted secret.

I really like Agenix, and I'm happy with it thus far. I just don't want to use solutions involving cat or builtin.readFile for the security risks involved there.

My configuration extract for Taskwarrior is listed below, as well as the produced configuration by Home Manager:

    taskwarrior = {
      enable = true;
      config = {
        confirmation = false;
        report = {
          minimal.filter = "status:pending";
          active.columns = [ "id" "start" "entry.age" "priority" "project" "due" "description" ];
          active.labels = [ "ID" "Started" "Age" "Priority" "Project" "Due" "Description" ];
        };
        taskd = {
          certificate = config.age.secrets.taskwarrior_sync_cert.path;
          key = config.age.secrets.taskwarrior_sync_key.path;
          ca = config.age.secrets.taskwarrior_sync_ca.path;
          server = "inthe.am:53589";
          credentials = config.age.secrets.taskwarrior_sync_cred.path;
        };
      };
    };
  };
data.location=/home/dzrodriguez/.local/share/task


confirmation=false
report.active.columns=id,start,entry.age,priority,project,due,description
report.active.labels=ID,Started,Age,Priority,Project,Due,Description
report.minimal.filter=status:pending
taskd.ca=$XDG_RUNTIME_DIR/agenix/taskwarrior_sync_ca
taskd.certificate=$XDG_RUNTIME_DIR/agenix/taskwarrior_sync_cert
taskd.credentials=$XDG_RUNTIME_DIR/agenix/taskwarrior_sync_cred
taskd.key=$XDG_RUNTIME_DIR/agenix/taskwarrior_sync_key
taskd.server=inthe.am:53589

shymega avatar Sep 18 '23 18:09 shymega

I can’t remember it from the top of my head but I think there is a way to force a restart of a service after a rebuild. Might be a useful workaround for this. I hadn’t had time yet to try a second time but I hope to be able to test it soon.

That would be really useful to know. If you do remember, maybe a PR to the documentation would be great!

shymega avatar Sep 18 '23 18:09 shymega

Maybe extending home.activation helps. https://nix-community.github.io/home-manager/options.html#opt-home.activation IIRC what I was using was the userActivationScript from NixOS. Doesn't sound like the most optimal solution however.

Nebucatnetzer avatar Sep 20 '23 12:09 Nebucatnetzer

I solved the issue of restarting the service on my system by adding this line: systemd.user.startServices = "sd-switch"; to my home-manager config.

This changes the general behavior when it comes to starting/stopping services after switching generations. That means it might cause some weird side effects. The default is "suggest" which prints some suggestions as to which services should be restarted manually. "sd-switch" uses a 3rd-party app to start/stop the required services (requires a user dbus session). It seems this is going to become the default at some point. See the systemd home-manager module.

Deadbyrd12 avatar Sep 21 '23 08:09 Deadbyrd12

I'm currently using the following workaround for machines which do not have a dbus session (and therefore can't use systemd user units):

# In home-manager.users.your-name-here
home.activation.agenix = lib.hm.dag.entryAnywhere config.systemd.user.services.agenix.Service.ExecStart;

It's a bit of a hack as agenix doesn't expose the user activation script anywhere, but it appears to work well enough. It seems to me like agenix might be better off using an activation script with home-manager too (like it already does with the system-wide version, as suggested by @Nebucatnetzer), instead of systemd/launchd as it currently uses.

jackwilsdon avatar Feb 05 '24 02:02 jackwilsdon

The above only seems to work at boot if you change the secretsDir and secretsMountPoint to be outside of $XDG_RUNTIME_DIR, as this isn't set (and the directory likely doesn't even exist) at boot:

# In home-manager.users.your-name-here
age = {
  secretsDir = "${config.home.homeDirectory}/.agenix/agenix";
  secretsMountPoint = "${config.home.homeDirectory}/.agenix/agenix.d";
};

jackwilsdon avatar Feb 05 '24 12:02 jackwilsdon