diff --git a/README.org b/README.org index e30949a..cb379fd 100755 --- a/README.org +++ b/README.org @@ -26,7 +26,7 @@ In order of descending preference, user programs should be configured by... doge ** Repo structure -*** =Hosts/= +*** =hosts/= Each directory =hosts/«HOST»= is expected to configure a single specific device, where =«HOST»= is the device's exact hostname. Said directory =«HOST»= should have at least the following structure: @@ -107,6 +107,8 @@ On boot, ... - =/persist/vault/«user»= :: Persistent files belonging to specific users. This differs from the persistent home directories in that files are not necessarily linked anywhere. +- =/persist/private-keys= :: The private key counterparts to the keys listed in this repository's own =public-keys= directory. + ** Deferring Emacs packages Nearly all configuration of Emacs packages happens under the ~use-package~ macro. ~use-package~ has various keywords with special syntax for common tasks, such as instrumenting hooks, setting keybindings, and customising variables. You may be surprised to learn that these are not /just/ syntactic sugar }:) (I was). diff --git a/hosts/deertopia/configuration.nix b/hosts/deertopia/configuration.nix index 91bca03..05cee97 100755 --- a/hosts/deertopia/configuration.nix +++ b/hosts/deertopia/configuration.nix @@ -34,7 +34,7 @@ sops = { enable = true; - keyFile = "/persist/vault/root/deertopia-key"; + keyFile = "/persist/private-keys/age/deertopia"; }; # git-annex = { diff --git a/modules/home/gpg.nix b/modules/home/gpg.nix new file mode 100755 index 0000000..f5b1793 --- /dev/null +++ b/modules/home/gpg.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, ... }: + +let cfg = config.sydnix.gpg; + mutableSymlink = config.lib.file.mkOutOfStoreSymlink; +in { + options = { + sydnix.gpg = { + enable = lib.mkEnableOption "GnuPG"; + }; + }; + + config = lib.mkIf cfg.enable { + programs.gpg = { + enable = true; + }; + + services.gpg-agent = { + enable = true; + enableSshSupport = true; + enableBashIntegration = config.programs.bash.enable; + extraConfig = + "allow-loopback-pinentry" + + lib.optionalString + config.programs.emacs.enable "\nallow-emacs-pinentry"; + }; + + home.file."private-keys/gpg/crumb".source = + mutableSymlink "/persist/private-keys/gpg/${config.home.username}"; + }; +} diff --git a/modules/home/sops.nix b/modules/home/sops.nix index 00a6dab..f2e7b70 100755 --- a/modules/home/sops.nix +++ b/modules/home/sops.nix @@ -19,6 +19,10 @@ in { }; config = mkIf cfg.enable { + home.packages = [ + pkgs.sops + ]; + sops = { age.keyFile = cfg.keyFile; defaultSopsFile = ../../users/${config.home.username}/secrets.yaml; diff --git a/modules/nixos/sops.nix b/modules/nixos/sops.nix index 8821bd0..d75ae30 100755 --- a/modules/nixos/sops.nix +++ b/modules/nixos/sops.nix @@ -10,7 +10,6 @@ in { keyFile = mkOption { description = "Path to an Age key file."; type = types.path; - default = "/persist/sydnix-key"; }; secrets = mkOption { description = "Secrets passed directly to sops-nix."; diff --git a/public-keys/age/crumb.pub b/public-keys/age/crumb.pub new file mode 100644 index 0000000..7b69cdc --- /dev/null +++ b/public-keys/age/crumb.pub @@ -0,0 +1 @@ +age1qayk0d0f765v57pedm7mtau6qkmv8rh6jtaqm40g5g9armaty4jqc0v0y2 diff --git a/public-keys/age/deertopia.pub b/public-keys/age/deertopia.pub new file mode 100644 index 0000000..8dc93b2 --- /dev/null +++ b/public-keys/age/deertopia.pub @@ -0,0 +1 @@ +age10fqh0td67alzpyjyhdex5ncj9thvaty506r0t63vs2nz4ldafgaqadl8mg diff --git a/public-keys/age/sydnix.pub b/public-keys/age/sydnix.pub new file mode 100644 index 0000000..40fe424 --- /dev/null +++ b/public-keys/age/sydnix.pub @@ -0,0 +1 @@ +age1k0ey4mzp4rhk5j2v8wmemucsnu0jdhnakpt2vnvmmkftuh944y7sdeur6x diff --git a/public-keys/crumb.pub b/public-keys/crumb.pub new file mode 100644 index 0000000..7b69cdc --- /dev/null +++ b/public-keys/crumb.pub @@ -0,0 +1 @@ +age1qayk0d0f765v57pedm7mtau6qkmv8rh6jtaqm40g5g9armaty4jqc0v0y2 diff --git a/secrets.yaml b/secrets.yaml index 4ab7125..8b790fe 100755 --- a/secrets.yaml +++ b/secrets.yaml @@ -1,7 +1,7 @@ -nextcloud-admin: ENC[AES256_GCM,data:MfHTZw5Co7DdY6uYT7e4ydoVPg==,iv:KqK/UaDpiEM5MnR86peGZ4iLfhC5JK4IOdI2T7RDZNg=,tag:Tpx2FdYavXud4OLcT7drTQ==,type:str] -bepasty-secret-key: ENC[AES256_GCM,data:JmR425LSZP0/kVQAkLfAettWyQmRpLF9CiZOfcnzr4Hdp8TP8doSKqv7+ggJfP2cKa3C9JHUXcKjEjZ5g0wllQ==,iv:XUg3ii7sJ8BScA1aA+AAoocV4CYn3pMQ2aMjrfZeQM0=,tag:uKMwnDxJFhHatpjLfJV73Q==,type:str] -slskd-credentials: ENC[AES256_GCM,data:CpZ0JpsO5De0E1eaNWBFEEHwzNkJTrDxVr+/tl0xuXaHx2BA2lkMNlsBs5mYr1fcLHsp+hIu1/jXVYYb08aPbKbzas1Le04/N0g3ADcHqIF7q5chU2/gkFnkRdcjgJaBtTmNbstx3Fh0Qe9w9iTEAGBXRmlDlpZO7wmycQBYRAdo6PnpidyBiJlqIWkXUCn+F9bdeCO7nRph9Ajqe/gxsl0nvAeIF/YAA2HlnxW9spxwyLYELkasLfQqebwdxOx4vbNjAPnUCE00Dw==,iv:XgqKguTc8Gx63j72ylttrooNeKOool9PU/jH3gEKjHI=,tag:0yeeNThfUgnyKDA5nUQDNA==,type:str] -bepasty-secret-config: ENC[AES256_GCM,data:GQVZhuGYoDt4HSwX4HuRnn896SsNgDZ0loaAF2xbqyppSK0jEn0EFsOafREVxSibpm3v/oVwJ+WMZSegqGHSeFbD/EgHaOvHMfEjes74ayh2ZkHB7IrfxFGTUSJNDrscvvl8xLGkJR7c0fj25axtJw==,iv:8JAGAftFK+n4G7BbdphdUf10D3B0ianXbmqfWV78QeQ=,tag:7Hgu39+KW7ifHIfy3rh71w==,type:str] +nextcloud-admin: ENC[AES256_GCM,data:K1KogDUmyAEm9JMlZ2SmYgekgA==,iv:GOlNIrxDCTSA1z763a5S0t3GDJZwMayGT1qzhPfzOus=,tag:zeuY48G9BED3o8O2mYU4QQ==,type:str] +bepasty-secret-key: ENC[AES256_GCM,data:N+5keSslQDj1v0t4yOZw+fcxoIPslsb2J1jI8jYX0+nR9exoUdjJJJPsVVjm83+ej6wguzMJgy1/eIufFmau8Q==,iv:Ye3HB2WsF+zrqK8aYDn3BsVKdhl9hNbL1HSZBCEYlSY=,tag:u4jD83/ExzS867QR9k7ObA==,type:str] +slskd-credentials: ENC[AES256_GCM,data:n3KmG6igp7+BmnHafW0dXp7uKEV/JY54VR/IQf7pV1k/60zDuFIrR3Bp0YL9sBTfT10qJNCd9GJXvdg46bLBoHc6Rr/Y+vHjLIIQZEX3wDfa1C9JCXmAh2Igyx3GCCOvntjYhVy2A/2JxIcvpSPC1Hua74oCbYXZ0hI3aeyu00LTVlpNZUz1JrVj2xgMFMltRL7Xt8hfSBFmG3W8j3kXBJIDxSIOxeYt8K/itBnzBtBOuWw9DqXVHy9F8Pmq2muUhiXGkEr6GWUJhg==,iv:w8p4yygdJv31VcICWFzyJoN47j5ax6N6PdPNM2JVcr8=,tag:lcWtdoiGPBw1uMkyzA3RMw==,type:str] +bepasty-secret-config: ENC[AES256_GCM,data:QPJBVW272ixtybIk3xmEa1R3qZ09WGpx4kyf2FFwjHLn1f1bNGzvcDfnFMzDiZjI0DvGPA26PzaKe7U0HX3ihX70IhohFqbr3XaGb7Gcr50RV1bkWV1G9ji+V5fFn/xdIkLmHaRISZFfDWdHBnzDaA==,iv:YQ+fcNvdXBTrc20TBBC4EIb4jwYV6AKJaTWJIcPa7A8=,tag:4P/L5FVmf7/bjINoArpMsg==,type:str] sops: kms: [] gcp_kms: [] @@ -11,14 +11,23 @@ sops: - recipient: age10fqh0td67alzpyjyhdex5ncj9thvaty506r0t63vs2nz4ldafgaqadl8mg enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3V2VVcGl5WlJTKzZpRG9p - WitQdXNpZGUzUkwxdzRrUzIwZm5ZK0g2WFdnCmxQdU5vaVc0elZpN3lQbDZ2Uldn - R0xHMTFKeDJVUUxKcUkxN2Uva0UwcGMKLS0tIDNJRzBUbTFPaXJHWGdvdHYyYnlS - aXZvL3RJRUtkOXR5OTFxcC9saXhGYVUKymDTIoxeHgJiM0rly5Zbp8kYoIUmmsWL - CMfXunhtA+u/vjDUHjyj41TTFbZMVl8FUzqMYoMxhIH6dQw8u1HKBA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHZTBFTVNZb3pYdFBaRlJY + TEFDV1FPQjhxNlN6bEFKWHpMRDAweHd1dkhRCmIzM1Rra1Avb25LRlk0bHZBWUxP + YWg1RVZZWmhrWDJkTnlPNzcyN2NsMG8KLS0tIEhPT0NpeWpQamVMRngvbGdyamZk + UDk0OUVtSUlCWHNVRjdVZ2ZBamRhL0kK/TxMdgRjf77c+zJAA3UH+Y3BUhn1gsr5 + bwjpnzY3y1SxboHS7HArPi3GH5rl2erGRruU95Er+o2NLkG9VarVCQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-02-09T21:23:22Z" - mac: ENC[AES256_GCM,data:VXgb0W0RpGO29lSFswN1iSWO6LmlnweVfmguzR+xUaVDngKWdrKwT/Eb3PDS4NVs0T9b0Mcu0CzFDAwxregQu8J74AqWPvD75CiGLnvDozznwgr4ZW2HtEY030jlUpnkooCVpDHh2UPdMzQBYiUCPWaBuTRfpEUyE/MQMzG8rY0=,iv:GPzbbMvJVZkizTHxWibtnO9DbJVt0YJFGHDEVW4d10M=,tag:NBYysUHb3OLqaQbCwZbJOA==,type:str] + - recipient: age1k0ey4mzp4rhk5j2v8wmemucsnu0jdhnakpt2vnvmmkftuh944y7sdeur6x + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKaG1WQStsS2o1OUVWZnhi + YmxiS3kvbGRBQmJGRUl1NWE5TmkzeTZjeFNjCmZWRmo1L0VoZlY5cUdHYitONUxo + YlNWbFdQemdsTjdVeXlFdlRHVTRxSGsKLS0tIEozQ0tSWjBJYnVsRElBaGlEWGNU + TXFLY2l0UHJ3Z0NGZjVpbTQ2UC8yaTQKA7wTmW9Ha6T2KmCr/nkXdizgv8+V6SAp + ZhDO+uDQ1evIh2wLWMOXNJ3d/zplLCOTzR2xkqBIUp5V7MXj45RUIA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-02-18T22:44:54Z" + mac: ENC[AES256_GCM,data:fDEXURw1rS57WOHVDr2aIc61/i8+pYsfk2okhBcTbOHIunN8A//naGI3YbEhAI/Z3W3RHajzP0uKrxgjW60vktrnVn25VTH70kp8jp/9LX1cs/Prar4RJZZmkaRSS2WqrZ059vIc4YSg1TA065C7NyaYthlvhagNGWV88cf5I1Q=,iv:8WJK7ROXfIrFAM+/0CI6RT21wIGQuEYlxEdYuHkh5vg=,tag:leZU2qBG4Og4EthUSP+FsQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.4 diff --git a/users/crumb/default.nix b/users/crumb/default.nix index ccaa7dd..dd458ec 100755 --- a/users/crumb/default.nix +++ b/users/crumb/default.nix @@ -21,9 +21,10 @@ xdg.enable = true; sydnix = { + gpg.enable = true; sops = { enable = true; - keyFile = "/persist/vault/${config.home.username}/keys/melbourne"; + keyFile = "/persist/private-keys/age/${config.home.username}"; }; }; diff --git a/users/crumb/files.nix b/users/crumb/files.nix index 8cd532a..adba67d 100755 --- a/users/crumb/files.nix +++ b/users/crumb/files.nix @@ -2,12 +2,6 @@ let mutableSymlink = config.lib.file.mkOutOfStoreSymlink; in lib.mkMerge [ - { - # TODO: Move to programs/age.nix. - xdg.configFile."sops/age/keys.txt".source = - mutableSymlink "/persist/vault/${config.home.username}/keys/melbourne"; - } - { ### Some basic impermanence setup. diff --git a/users/crumb/programs/age.nix b/users/crumb/programs/age.nix index 8b4f5f3..cfe034b 100755 --- a/users/crumb/programs/age.nix +++ b/users/crumb/programs/age.nix @@ -1,8 +1,18 @@ { config, lib, pkgs, ... }: -{ +let mutableSymlink = config.lib.file.mkOutOfStoreSymlink; +in { home.packages = [ # Rage supports pinentry while Age does not. pkgs.rage ]; + + # Private keys must be mutable symlinks since we don't want the key inside the + # world-readable store. + home.file."private-keys/age/crumb.age".source = + mutableSymlink "/persist/private-keys/age/${config.home.username}.age"; + + home.file."public-keys/age/crumb.pub".source = + ../../../public-keys/age/${config.home.username}.pub; } + diff --git a/users/crumb/programs/emacs/modules/syd-age.el b/users/crumb/programs/emacs/modules/syd-age.el index c708ba8..b63f905 100755 --- a/users/crumb/programs/emacs/modules/syd-age.el +++ b/users/crumb/programs/emacs/modules/syd-age.el @@ -4,9 +4,7 @@ :hook (on-first-file . age-file-enable) :custom ((age-program "rage") - (age-default-identity (format "/persist/vault/%s/keys/melbourne" - user-login-name)) - (age-default-recipient (format "/persist/vault/%s/keys/melbourne.pub" - user-login-name)))) + (age-default-identity "~/private-keys/age/crumb.age") + (age-default-recipient "~/public-keys/age/crumb.pub"))) (provide 'syd-age) diff --git a/users/crumb/programs/emacs/modules/syd-ui.el b/users/crumb/programs/emacs/modules/syd-ui.el index b39d724..991d215 100755 --- a/users/crumb/programs/emacs/modules/syd-ui.el +++ b/users/crumb/programs/emacs/modules/syd-ui.el @@ -64,6 +64,9 @@ :custom ((display-line-numbers-type 'relative) ;; Always ask "y/n"; never "yes/no". (use-short-answers t) + ;; I don't like that `grep' asks me to save unsaved files. It makes + ;; me think it's about to kill my buffers. + (grep-save-buffers nil) ;; The default value is `ask', meaning that Emacs will ask for ;; confirmation any time you follow a symlink to a file under version ;; control. The documentation claims this is "dangerous, and