you can sign git commits using the ssh key you already have

after reading a lovely how-to from calebhearth.com, i decided to do the same using nix and home-manager

what is nix?

Nix is a tool that takes a unique approach to package management and system configuration. Make reproducible, declarative and reliable systems

what is home-manager?

provides a basic system for managing a user environment using the Nix package manager together with the Nix libraries found in Nixpkgs. It allows declarative configuration of user specific (non global) packages and dotfiles

using home-manager to configure git

let’s create the most basic home-manager configuration to install git

1
2
3
4
5
6
7
8
9
# ~/.config/nixpkgs/home.nix
{ config, pkgs, ... }:
{
  programs = {
    git = {
      enable = true;
    };
  };
}

activate updated home-manager configuration

$ home-manager switch
/nix/store/ysha94fay20k72d5am0sn6q1jvljfdh4-home-manager-generation
...
Activating reloadSystemd

verify git is installed

$ git --version
git version 2.34.1

let’s add my user name and email to git. i’ll be using the email provided by github

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# ~/.config/nixpkgs/home.nix
{ config, pkgs, ... }:
{
  programs = {
    git = {
      enable = true;
      userName = "Nelson Jeppesen";
      userEmail = "50854675+NelsonJeppesen@users.noreply.github.com";
    };
  };
}

now lets configure git to use my ssh key to sign my requests. the extraconfig values all map to standard git config --global options

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# ~/.config/nixpkgs/home.nix
{ config, pkgs, ... }:
{
  programs = {
    git = {
      enable = true;
      userName = "Nelson Jeppesen";
      userEmail = "50854675+NelsonJeppesen@users.noreply.github.com";

      extraConfig = {
        # Sign all commits using ssh key
        commit.gpgsign = true;
        gpg.format = "ssh";
        user.signingkey = "~/.ssh/id_ed25519.pub";
      };
    };
  };
}

lets test it!

$ home-manager switch
...
Activating reloadSystemd

create empty commit

$ git commit --allow-empty --message="Testing SSH signing"
[main a231116] Testing SSH signing

lets take a look at the signature

$ git show --show-signature
error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification
commit a231116650b68cc165d45904f0077a3a775f1666 (HEAD -> main)
No signature
Author: Nelson Jeppesen <50854675+NelsonJeppesen@users.noreply.github.com>
Date:   Sat Jan 29 13:33:22 2022 -0800

    Testing SSH signing

oh dear! we have an issue, we need to configure allowedsignersfile

let’s create a file that holds my public key, then have git use it. Notice I add a wildcard. This indicates that it should be used for all emails

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# ~/.config/nixpkgs/home.nix
{ config, pkgs, ... }:
{
  home.file.".ssh/allowed_signers".text =
    "* ${builtins.readFile /home/nelson/.ssh/id_ed25519.pub}";

  programs = {
    git = {
      enable = true;
      userName = "Nelson Jeppesen";
      userEmail = "50854675+NelsonJeppesen@users.noreply.github.com";

      extraConfig = {
        # Sign all commits using ssh key
        commit.gpgsign = true;
        gpg.format = "ssh";
        gpg.ssh.allowedSignersFile = "~/.ssh/allowed_signers";
        user.signingkey = "~/.ssh/id_ed25519.pub";

let’s check again!

$ home-manager switch
...
Activating reloadSystemd

looking at the same commit again

$ git show --show-signature
commit a231116650b68cc165d45904f0077a3a775f1666 (HEAD -> main)
Good "git" signature for * with ED25519 key SHA256:X+rvccMdeOFfHlPyW6pDKxurqSo3lQUbg14hxE3Sb5A
Author: Nelson Jeppesen <50854675+NelsonJeppesen@users.noreply.github.com>
Date:   Sat Jan 29 13:33:22 2022 -0800

    Testing SSH signing

Yay! If I rotate my ssh key, all I need to do is run home-manager switch and upload to github

Here’s what it looks like as a real-world example that I use every day github.com/NelsonJeppesen/nix-lifestyle:git.nix