Commit c3e9701

HPCesia <me@hpcesia.com>
2026-06-21 10:01:32
Add GnuPG for desktop
1 parent cfd4a1e
Changed files (5)
modules
modules/desktop/gnupg.nix
@@ -0,0 +1,106 @@
+{
+  den.aspects.desktop.gnupg = {
+    persistHome = {config, ...}: {
+      directories = [
+        {
+          directory = config.programs.gpg.homedir;
+          mode = "0700";
+        }
+      ];
+    };
+
+    nixos = {pkgs, ...}: {
+      programs.gnupg.agent = {
+        enable = true;
+        pinentryPackage = pkgs.pinentry-gnome3;
+        enableSSHSupport = false;
+        settings.default-cache-ttl = 4 * 60 * 60; # 4 hours
+      };
+    };
+
+    homeManager = {
+      user,
+      config,
+      ...
+    }: {
+      programs.gpg = {
+        enable = true;
+        homedir = "${config.home.homeDirectory}/.gnupg";
+
+        mutableTrust = false;
+        mutableKeys = false;
+
+        publicKeys = map (key:
+          {
+            trust = "ultimate";
+          }
+          // (
+            if (builtins.isPath key)
+            then {
+              source = key;
+            }
+            else {
+              text = key;
+            }
+          ))
+        user.identity.gpgKeys;
+
+        # This configuration is based on the tutorial below, it allows for a robust setup
+        # https://blog.eleven-labs.com/en/openpgp-almost-perfect-key-pair-part-1
+        # ~/.gnupg/gpg.conf
+        settings = {
+          # Get rid of the copyright notice
+          no-greeting = true;
+
+          # --- Avoid information leaked --- #
+          # Disable inclusion of the version string in ASCII armored output
+          no-emit-version = true;
+          # Do not write comment packets
+          no-comments = false;
+          # Export the smallest key possible
+          # This removes all signatures except the most recent self-signature on each user ID
+          export-options = "export-minimal";
+
+          # Display long key IDs
+          keyid-format = "0xlong";
+          # List all keys (or the specified ones) along with their fingerprints
+          with-fingerprint = true;
+
+          # Display the calculated validity of user IDs during key listings
+          list-options = "show-uid-validity";
+          verify-options = "show-uid-validity show-keyserver-urls";
+
+          # Select the strongest cipher
+          personal-cipher-preferences = "AES256";
+          # Select the strongest digest
+          personal-digest-preferences = "SHA512";
+          # This preference list is used for new keys and becomes the default for "setpref" in the edit menu
+          default-preference-list = "SHA512 SHA384 SHA256 RIPEMD160 AES256 TWOFISH BLOWFISH ZLIB BZIP2 ZIP Uncompressed";
+
+          # Use the strongest cipher algorithm
+          cipher-algo = "AES256";
+          # Use the strongest digest algorithm
+          digest-algo = "SHA512";
+          # Message digest algorithm used when signing a key
+          cert-digest-algo = "SHA512";
+          # Use RFC-1950 ZLIB compression
+          compress-algo = "ZLIB";
+
+          # Disable weak algorithm
+          disable-cipher-algo = "3DES";
+          # Treat the specified digest algorithm as weak
+          weak-digest = "SHA1";
+
+          # The cipher algorithm for symmetric encryption for symmetric encryption with a passphrase
+          s2k-cipher-algo = "AES256";
+          # The digest algorithm used to mangle the passphrases for symmetric encryption
+          s2k-digest-algo = "SHA512";
+          # Selects how passphrases for symmetric encryption are mangled
+          s2k-mode = "3";
+          # Specify how many times the passphrases mangling for symmetric encryption is repeated
+          s2k-count = "65011712";
+        };
+      };
+    };
+  };
+}
modules/develop/jujutsu.nix
@@ -1,5 +1,10 @@
-{
+{den, ...}: {
   den.aspects.develop.jujutsu = {
+    includes =
+      den.lib.policy.when
+      ({host, ...}: host.hasAspect den.aspects.desktop.gnupg)
+      [den.aspects.develop.jujutsu.sign];
+
     homeManager = {user, ...}: {
       programs.jujutsu = {
         enable = true;
@@ -16,4 +21,18 @@
       };
     };
   };
+
+  den.aspects.develop.jujutsu.sign = {
+    homeManager = {
+      programs.jujutsu.settings = {
+        signing = {
+          behavior = "drop";
+          backend = "gpg";
+        };
+        git = {
+          sign-on-push = true;
+        };
+      };
+    };
+  };
 }
modules/users/hpcesia/default.nix
@@ -18,6 +18,7 @@
         ({host, ...}: host.hasAspect den.aspects.roles.desktop)
         (with den.aspects; [
           desktop.env.wm.niri
+          desktop.gnupg
         ]));
   };
 
@@ -28,6 +29,9 @@
     identity = {
       displayName = "HPCesia";
       email = "me@hpcesia.com";
+      gpgKeys = [
+        ./gpg.asc
+      ];
       sshKeys = [
         {
           tag = "hpcesia@kevin";
modules/users/hpcesia/gpg.asc
@@ -0,0 +1,32 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mDMEahCUrRYJKwYBBAHaRw8BAQdAKXQUDTZq1Dsu6EffnhrmyOBunSHJEp+pH+rM
+QSWB2FK0GEhQQ2VzaWEgPG1lQGhwY2VzaWEuY29tPokCLgQTFgoB1gIbAQULCQgH
+AwUVCgkICwUWAgMBAAIeAQIXgBYhBKaONCdbG5LgeY8Hyp1lkviuhDOWBQJqE9uN
+mhSAAAAAABAAgXByb29mQGFyaWFkbmUuaWRtYXRyaXg6L3UvaHBjZXNpYTpteWNl
+LmxpP29yZy5rZXlveGlkZS5yPWRCZlFaeENvR1ZtU1R1amZpdjptYXRyaXgub3Jn
+Jm9yZy5rZXlveGlkZS5lPXRoMl9DZVVWSE5UZ3A1VlpIV0lXd3gxd013Y2NNcnFH
+a1R5NGJ1elYxb2dEFIAAAAAAEAArcHJvb2ZAYXJpYWRuZS5pZGh0dHBzOi8vY29k
+ZWJlcmcub3JnL0hQQ2VzaWEva2V5b3hpZGVfcHJvb2YxFIAAAAAAEAAYcHJvb2ZA
+YXJpYWRuZS5pZGh0dHBzOi8vbXljZS5saS9AaHBjZXNpYTEUgAAAAAAQABhwcm9v
+ZkBhcmlhZG5lLmlkZG5zOmhwY2VzaWEuY29tP3R5cGU9VFhUWRSAAAAAABAAQHBy
+b29mQGFyaWFkbmUuaWRodHRwczovL2dpc3QuZ2l0aHViLmNvbS9IUENlc2lhL2Ri
+ODhkZmQ1NDAxMWMyZWQwNzNhZDJkYjhmYTZmNGMwAAoJEJ1lkviuhDOWMgwBAKfR
+TcE7MYsPXfzYA9dLAofS+cxnEA5oPNamAWF6PPP4AP9M/V3bhMXWXv/EHqVusffU
+nSZBVMcwNcx6pR0xI5WmArgzBGoQlRMWCSsGAQQB2kcPAQEHQBAOsuXn0xmv0ZoG
+TYEY2Fo6YMdJVEz7qtEOle5V80xriPUEGBYKACYWIQSmjjQnWxuS4HmPB8qdZZL4
+roQzlgUCahCVEwIbAgUJAE8aAACBCRCdZZL4roQzlnYgBBkWCgAdFiEEXa0VAC4d
+je6nH8i1rl8ugv65lqcFAmoQlRMACgkQrl8ugv65lqd8sQD/QZNMz0I4aNKTGYTR
+woUT7/vGiRq2yot/as/8sJ1EWmcA/2bb8PDBl0f2e6cpe1xcJ3hU9enX9SkcTyTI
+tTyXgscCIicBAOT70Hhwhsrus1bRBw0PMrAJHSza0HyD0DaT39e+LhTFAQDNEErw
+TzDrwpAea3aHak245JEyuXHwFxdqDEspeGQ9BLg4BGoQlTQSCisGAQQBl1UBBQEB
+B0BTI+WmgiJItXlywB5jDO+hsd96k4SAqwYFuz0XjqK9JgMBCAeIfgQYFgoAJhYh
+BKaONCdbG5LgeY8Hyp1lkviuhDOWBQJqEJU0AhsMBQkATxoAAAoJEJ1lkviuhDOW
+8dkBAOWOD5YJohd45yVgEypiowndk0PLiwHtHlvbJD1IXRAZAQC0rAtJsWQLg8cy
+zni/m/RHRhLfBDMzeWVLqWphyM5LBbgzBGoQlaoWCSsGAQQB2kcPAQEHQJCmRaH1
+yFsy/bVEGHgpujOntbTKlETBx3yZKjMr3v+ZiH4EGBYKACYWIQSmjjQnWxuS4HmP
+B8qdZZL4roQzlgUCahCVqgIbIAUJAE8aAAAKCRCdZZL4roQzluoyAQDteJOtdYmv
+uyK+RUlk1NZBmmyRwlG2QJscJhK7SLqfowD/TYCs3gMlXeWlAS8jGKDqrnfE5GYJ
+xK7vXFY3R/IjTAs=
+=27HS
+-----END PGP PUBLIC KEY BLOCK-----
modules/users/schema.nix
@@ -32,7 +32,7 @@ in {
                 description = "Email address for the user";
               };
               gpgKey = mkOption {
-                type = types.nullOr types.str;
+                type = types.nullOr (types.either types.path types.str);
                 default = null;
                 description = "GPG key ID for the user";
               };