aboutsummaryrefslogblamecommitdiff
path: root/users/modules/onepassword.nix
blob: d98df2593b4b243a8c7db83ec4b8c6f7bb874436 (plain) (tree)



















































































































































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

with lib;

let
  cfg = config.programs.onepassword;

  generateAgentConfig =
    keys:
    let
      keyToToml =
        key:
        let
          lines =
            [ "[[ssh-keys]]" ]
            ++ optional (key.item != null) ''item = "${key.item}"''
            ++ optional (key.vault != null) ''vault = "${key.vault}"''
            ++ [ ''account = "${key.account}"'' ];
        in
        concatStringsSep "\n" lines;
    in
    concatStringsSep "\n\n" (map keyToToml keys);

  home = config.home.homeDirectory;
  darwinSockPath = "${home}/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock";
  defaultSockPath = ".1password/agent.sock";

in
{
  options.programs.onepassword = {
    enable = mkEnableOption "1Password CLI and SSH agent integration";

    package = mkOption {
      type = types.package;
      default = pkgs._1password-cli;
      description = "The 1Password CLI package to use.";
    };

    socketPath = mkOption {
      type = types.str;
      default = defaultSockPath;
      description = "Relative path from home directory for the SSH agent socket.";
      example = ".1password/agent.sock";
    };

    darwinSocketPath = mkOption {
      type = types.str;
      default = darwinSockPath;
      description = "Full path to the 1Password agent socket on macOS.";
    };

    setSshAuthSock = mkOption {
      type = types.bool;
      default = true;
      description = "Whether to set the SSH_AUTH_SOCK environment variable.";
    };

    configureSshClient = mkOption {
      type = types.bool;
      default = true;
      description = "Whether to configure the SSH client to use 1Password agent.";
    };

    fishIntegration = mkOption {
      type = types.bool;
      default = false;
      description = "Enable fish shell completion for 1Password CLI.";
    };

    sshKeys = mkOption {
      type =
        with types;
        listOf (submodule {
          options = {
            item = mkOption {
              type = nullOr str;
              default = null;
              description = "The name of the SSH key item in 1Password.";
              example = "Git Signing Key";
            };

            vault = mkOption {
              type = nullOr str;
              default = null;
              description = "The vault name where the SSH key is stored (optional).";
              example = "Private";
            };

            account = mkOption {
              type = str;
              default = "my.1password.com";
              description = "The 1Password account identifier.";
              example = "my.1password.com";
            };
          };
        });
      default = [ ];
      description = "SSH keys configuration for 1Password agent. Lists from multiple configurations will be merged.";
      example = [
        { account = "my.1password.com"; }
        {
          item = "Git Signing Key";
          vault = "Work";
          account = "ACME, Inc.";
        }
        {
          item = "Personal SSH Key";
          account = "my.1password.com";
        }
      ];
    };
  };

  config = mkIf cfg.enable {
    home.packages = [ cfg.package ];

    home.sessionVariables = mkIf cfg.setSshAuthSock {
      SSH_AUTH_SOCK = "${home}/${cfg.socketPath}";
    };

    # Create symlink to Darwin socket (macOS specific)
    home.file."${cfg.socketPath}" = mkIf pkgs.stdenv.isDarwin {
      source = config.lib.file.mkOutOfStoreSymlink cfg.darwinSocketPath;
    };

    # Configure SSH client
    programs.ssh = mkIf cfg.configureSshClient {
      extraConfig = "IdentityAgent ~/${cfg.socketPath}";
    };

    # Fish shell integration
    programs.fish = mkIf cfg.fishIntegration {
      interactiveShellInit = ''
        op completion fish | source
      '';
    };

    # Generate SSH agent configuration
    home.file.".config/1Password/ssh/agent.toml" = mkIf (cfg.sshKeys != [ ]) {
      text = generateAgentConfig cfg.sshKeys;
    };
  };
}