I’m having a lot of trouble finding an ergonomic way to create a flake that has an input that comes from a private GitHub repository.
I’m aware that I can use git+ssh://git@github.com/...
URLs in the inputs and Nix will use my user SSH config (and agent) to authenticate.
The trouble is that if I have multiple GitHub accounts, there’s no pure-SSH configuration way (that I know of) to select the correct SSH key based on the repository (which is natural because SSH doesn’t know about git repositories, it only deals with users and hosts).
To deal with multiple GitHub accounts in the past I have created multiple fake hosts in my SSH config, e.g.
Host github.com
IdentityFile ~/.ssh/id_personal
Host work1-github
HostName github.com
IdentityFile ~/.ssh/id_work1
Host work2-github
HostName github.com
IdentityFile ~/.ssh/id_work2
This works reasonably well when I’m using git; I just remember to clone from a different URL depending on which identity is required, and can then forget about it and push/pull as normal. And this configuration on my system doesn’t affect anyone else. So a single flake stored in a private repository has also worked fine by this system.
However when I want to use a private repository as an input to a flake, things get awkward.
To use the fake-host workaround, I need to embed the host I made up into the flake, which means everyone using it needs to set up the same fake host in their own SSH configs; it’s not just a local configuration of my access credentials anymore, it infects the whole organisation.
I can leave the real URL in the flake and use --override-input name git+ssh://git@work1-github/work1/name
. I’d be doing something similar if I need to override it with a local checkout anyway. But that still puts the fake host in the lock file; if I commit that the flake won’t be a reproducible build that anyone else can run.
I could use GitHub access tokens instead of SSH keys to authenticate, and switch from git+ssh://
input urls to github:...
ones. But there doesn’t seem to be any way to use multiple access tokens for the same host, so it still wouldn’t work with private repositories from multiple GitHub accounts. (Access tokens also require leaving plaintext credentials sitting around which I’m not wild about, and using github:...
input URLs forces everyone else in the organisation to use them instead of SSH keys too, even if they don’t need to access more than one GitHub account)
I’ve just discovered I can use Git’s hasconfig:remote
feature to (finally) avoid the need for fake hosts in my SSH config. e.g:
# ~/.config/git/config
[includeIf "hasconfig:remote.*.url:git+ssh://git@github.com/work1/**"]
path = "config file that sets core.sshCommand to 'ssh -i ~/.ssh/id_work1'"
But of course Nix won’t use my user’s git configuration the way it uses my user’s SSH configuration. So this makes my usual git pushing and pulling better, but doesn’t help flake inputs.
At this point the only thing I can think of that would work is not configuring any access and manually managing which SSH key is in my agent based on which repositories I’m working on (or maybe some hacky wrapper for nix
that does the same based on which folder I’m in).
Is there anything I’ve missed that would allow me to get all of:
- The flake’s input URL (and also the lock file) to contain the actual “address” of the private repository, not an artefact of any user’s local configuration
- Nix can fetch flake inputs without manual preparation (it’s fine if it prompts me for a pass phrase like SSH would, though something like an SSH agent is ideal)
- I can access private repositories from more than one GitHub account