NixDaemon

NixOS pentest workstation as one flake — IceBreaker's successor
git clone https://git.daemon-sec.xyz/NixDaemon.git
Log | Files | Refs | README

passage.nix (3135B)


      1 # modules/home/passage.nix — `passage`: a password store, keyed by the age key
      2 # the flake already has.
      3 #
      4 #   passage init            not needed; the recipients come from the environment
      5 #   passage insert web/gitlab
      6 #   passage show   web/gitlab          passage -c web/gitlab   (clipboard, 45s)
      7 #   passage generate web/newsite 32
      8 #   passage ls  /  passage find gitlab  /  passage grep token
      9 #   passage git init && passage git remote add ...
     10 #
     11 # Why passage and not pass: `pass` is GnuPG, which means the agent, pinentry
     12 # and a keyring. passage is the same tool reimplemented on age, and this
     13 # machine already keeps an age key for sops-nix. One key, one backup.
     14 #
     15 # Why it reuses ~/.config/sops/age/keys.txt rather than its own identity:
     16 # that file already decrypts every secret the flake has, so pointing passage
     17 # at it adds no exposure that is not already there, and -- more importantly --
     18 # no SECOND 189-byte file whose loss is unrecoverable. The alternative, a
     19 # dedicated passphrase-protected identity, is in the vault note; it is a real
     20 # improvement in compartmentalisation and a real increase in what you must
     21 # back up. Switch by changing PASSAGE_IDENTITIES_FILE below.
     22 #
     23 # This is deliberately NOT where machine secrets live. Anything the system or a
     24 # service needs at activation belongs in secrets/secrets.yaml via sops-nix
     25 # (modules/home/sops.nix) -- passage needs an interactive shell and your
     26 # clipboard, which activation has neither of. passage is for the logins you
     27 # type, sops for the values the machine reads.
     28 { ... }:
     29 {
     30   flake.homeModules.passage =
     31   { config, pkgs, ... }:
     32   let
     33     ageKey = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
     34     # The public half of that key. Public by definition -- it is already
     35     # committed in ~/NixDaemon/.sops.yaml as the only recipient. Kept here as a
     36     # literal for the same reason gpg.nix pins a fingerprint: so a wrong key
     37     # cannot be picked up silently from a file that happens to be on disk.
     38     recipient = "age1pu5wcvqqh92xr6ces8zmj4xvs52v7yfm4jsfcxm3z82a32u9n97qesldfv";
     39   in
     40   {
     41     home.packages = [ pkgs.passage ];
     42 
     43     home.sessionVariables = {
     44       # Defaults are ~/.passage/store and ~/.passage/identities; both are set
     45       # explicitly so the store can move without surprises.
     46       PASSAGE_DIR = "${config.xdg.dataHome}/passage/store";
     47       PASSAGE_IDENTITIES_FILE = ageKey;
     48 
     49       # Recipients as an environment variable rather than a .age-recipients
     50       # file in the store: it keeps the store a plain directory of .age files
     51       # with nothing to commit by accident, and makes the recipient part of the
     52       # flake rather than per-checkout state. For per-subdirectory recipients
     53       # (sharing one folder with someone else) drop a .age-recipients in that
     54       # folder instead -- passage walks up from the entry to find one, and a
     55       # file found that way wins over this.
     56       PASSAGE_RECIPIENTS = recipient;
     57 
     58       # pass-compatible knobs passage still honours.
     59       PASSWORD_STORE_CLIP_TIME = "45"; # seconds before the clipboard is wiped
     60       PASSWORD_STORE_GENERATED_LENGTH = "25";
     61     };
     62   }
     63   ;
     64 }