Deploying Private GitHub Repositories To NixOS Servers
In a previous post I’ve already shared a way to deploy private git repositories to a NixOS based server. While the old approach is still working I’m using a different approach today. The previously approach requires the private key to be stored on the server. The new approach uses SSH agent forwarding. This way your ssh key never needs to sit on the server.
So this post is basically an update to the previous post to share a simpler way to deploy private git repositories to NixOS hosts.
Example Package
Before we can start, we first need a package to deploy. For this example I picked the nix expression I’m using for this blog:
with import <nixpkgs> {};
stdenv.mkDerivation rec {
name = "blog";
src = fetchgitPrivate {
url = "git@github.com:mpscholten/mpscholten.github.io.git";
sha256 = "0fy43d0nhbmpf3f8v302r7bhpyd3qk2dyjr2fnvwwdx2825an6cq";
};
buildInputs = [ jekyll ];
buildPhase = "jekyll build";
installPhase = "cp -R _site \$out";
}
The above nix expression is saved to a file blog.nix
locally on my computer (so not on the NixOS host yet). It does nothing more than fetching the source code from the private git repository, doing a jekyll build
and copying the resulting _site
directory to $out
.
The corresponding configuration.nix
contains the following lines to run the blog:
services.nginx = {
enable = true;
virtualHosts."www.mpscholten.de" = {
enableACME = true;
forceSSL = true;
root = (let blog = import ./blog.nix; in "${blog}");
};
}
It just adds a vhost to the nginx service and enables letsencrypt.
Enabling SSH Agent Forwarding
As we’re going to use SSH Agent Forwarding for the deployment, we first have to enable it locally. For that we just need to update our local ~/.ssh/config
and add a ForwardAgent yes
to the host:
This step of course requires that you already use git over ssh locally.
Host digitallyinduced.com
HostName 46.101.152.239
User root
ForwardAgent yes # <--- Add this line
AddKeysToAgent yes # <--- If you're on macOS, you also need to enable this
When we now ssh
into the server, we should already be able to just git clone
the repository, even though there is no key on the server itself.
The Deployment
To deploy the above package to the NixOS server the blog.nix
as well as the configuration.nix
are copied to the server. Then a nixos-rebuild switch
is started.
By default NixOS will not pick up our SSH Agent Forwarding. To fix that we have to pass the ssh auth socket to nixos-rebuild
. We also need to set correct permissions, so that the nix build users can access the socket. Sounds complicated. Luckily Adrien Devresse shared a script to automatically do this on the nix-dev mailing list. Thanks for sharing this Adrien!
The original script is only outputting the new $NIX_PATH
, for my uses I changed the script to directly run nixos-rebuild switch
. You can find my patched version, which is going to be used below, here: https://gist.github.com/mpscholten/1a12fca4a21fca4fb485148595ffd9b3.
Now we have all the ingridents ready for the actual deployment process. My deploy
shell script for the whole thing looks like this:
#!/bin/sh
scp configuration.nix digitallyinduced.com:/etc/nixos/configuration.nix
scp blog.nix digitallyinduced.com:/etc/nixos/blog.nix
scp run_deployment.sh digitallyinduced.com:/root/run_deployment.sh
ssh digitallyinduced.com "chmod +x run_deployment.sh && ./run_deployment.sh";
The usual nixos-rebuild switch
is handled by the run_deployment.sh
script.
Now by running the above script, NixOS will install the blog package and download the private GitHub repository. That’s it already.
The Result
With the above process we can easily deploy all kinds of private packages to NixOS servers. There’s also never a private key stored on the server.
Thanks for reading :) Follow me on twitter if you’re interested in more of this stuff!
Hey! I’m Marc, founder of digitally induced. I love playing with exciting new technology. Feel free to contact me.
If you liked this post feel free to subscribe to my mailing list.