Put NixOS config into a Git repository

This tutorial will show how to consolidate NixOS configuration and home-manager configuration into one Git repository.

Prerequisite: Have a working NixOS install, with git, git-crypt, gnupg and home-manager installed.

Make a directory where the Git repo will be placed. In my case it's inside the Development folder in my home directory.

cd ~/Development
mkdir nixos-config

Make a directory where the system configuration will be stored (NixOS config).

mkdir nixos-config/hosts

Make a directory where the user config (home-manager config) will be stored for particular users.

mkdir nixos-config/users

Make a directory for particular user.

mkdir nixos-config/users/eric

Initialise the git repository.

cd nixos-config
git init

Configuring the system directory.

Copy the NixOS configuration files to the nixos-config/hosts/ folder.

cd system
cp /etc/nixos/*.nix .

Double check that he permissions are fine (i.e check that the user is correct and has appropiate permissions).

ls -lAh
-rw-r--r-- 1 eric users 5.2K May 18 20:46 configuration.nix
-rw-r--r-- 1 eric users  935 May 18 20:46 hardware-configuration.nix

To make the NixOS run the configuration in the git directory:

sudo nixos-rebuild switch -I nixos-config=~/Development/nixos-config/hosts/configuration.nix

Configuring the users directory.

Copy the home-manager configuration files to the nixos-config/user/eric/ folder.

cd ~/Development/nixos-config/users/eric
cp ~/.config/nixpkgs/home.nix .

Double check that he permissions are fine (i.e check that the user is correct and has appropiate permissions).

ls -lAh
-rw-r--r-- 1 eric users  935 May 18 20:46 home.nix

To make the NixOS run the home-manager configuration in the git directory:

home-manager switch -f ~/Development/nixos-config/users/eric/home.nix

Making scripts to automate running the config files.

To make it easier to rebuild the configurations, instead of having to type long commands each time.

Script to run system rebuild.

cat > ~/Development/nixos-config/apply-system.sh
#!/bin/sh

pushd ~/Development/nixos-config # Change to the nixos-config directory

sudo nixos-rebuild switch -I nixos-config=./hosts/configuration.nix # Rebuild configuration.nix.

popd # Return to previous directory.

Script to run home-manager rebuild.

cat > ~/Development/nixos-config/apply-user.sh
#!/bin/sh

pushd ~/Development/nixos-config # Change to the nixos-config directory

home-manager switch -f ./users/eric/home.nix # Rebuild home-manager.

popd # Return to previous directory.

Make the scripts executable:

chmod +x ~/Development/nixos-config/*.sh

To run configurations:

cd ~/Development/nixos-config
./apply-system.sh
./apply-user.sh

Making scripts to automate updating.

Script to update the system:

cat > update-system.sh
#!/bin/sh

sudo nix-channel --update

Script to update the user:

cat > update-user.sh
#!/bin/sh

nix-channel --update

Make the scripts executable:

chmod +x ~/Development/nixos-config/*.sh

To run configurations:

cd ~/Development/nixos-config
./update-system.sh
./update-user.sh

Setting up git-crypt

When using a service like GitHub to host repositories, if there are any secrects stored in the repositories, such as passwords for wifi,or other sensitive information. git-crypt can be used to encrypt (with a GPG key) parts of a repository that may contain secrets. It is best practice to encrypt secrets even in private repositories, just in case they are made public later on, because even if the files that contain secrets are removed, the history will still have the secrets in it.

Add gpg-agent setup to the home-manager configuration, add the pinentry package, then execute the apply-user.sh script.

{ config, pkgs, ... }: {

  programs.gpg-agent = {
    enable = true;
  };

  services.gpg-agent = {
    enable = true;
    pinentryFlavor = "qt";
  };

  home.packages = with pkgs; [
    pinentry_qt
    # Etcetera ...
  ];

    # Etcetera ...
}
          
        

Generate the gpg key and follow the prompts, fill in name and email and password.

gpg --generate-key

Double check to ensure the key is trusted. First, list all keys.

gpg --list-key

Backup the public key.

gpg --output ~/public.gpg --armor --export mail@cebo.ooo

Backup the private key (follow thw prompt and fill in password).

gpg --output ~/private.gpg --armor --export-secret-key mail@cebo.ooo

Trust the key.

gpg --edit-key mail@cebo.ooo

If the key is showing as ultimate, then the key is being trusted. if it doesn't, type in "trust" in the gpg prompt. Select 5 to trust it ultimately. Click 'y' to confirm and then type quit when finished.

Setting the repository up to git-crypt

Before continuing, with this step, ensure git is setup with username and email address. To check is it is already setup:

git config --list

If name and email are setup correctly, then they should be displayed. If no name and email appear, then git has to be setup. To setup git with username and email, add git setup to ~/NixOS/users/eric/home.nix:

{ config, pkgs, ... }: {

  rograms.git = {
   enable = true;
   userName = "Eric C Chiruka";
   userEmail = "mail@cebo.ooo";
  };

  # Etcetera ...
}

In the repository, generate the git-crypt key.

git crypt init

This then creates a file ~/Development/nixos-config/.git/git-crypt

Add the gpg key to the repository so that it can be encrypted when needed.

git crypt add-gpg-user mail@cebo.ooo

This then creates a few files in the keys directory ~/Development/nixos-config/.git/git-crypt/keys/. Essentially, now, any user with an authorised gpg key can decrypt the main key and decrypt the contents of all the secrets stored in the repository. Multiple users can be added and also revoked at will by adding/revoking their gpg key.

Backup the git-crypt key:

git crypt export-key ~/gitgpg.key

Encrypting secrets

Create a secrets directory in the repository:

mkdir .secrets

Create a secret file:

echo "testing" > ./secrets/test.txt

Create a .gitattributes file in the repository.

cat > .gitattributes
.secrets/** filter=git-crypt diff=git-crypt

Add and commit changes (use git status to ensure all files are added.)

git add .
git status
git commit -m "Initial commit"

Lock the repository (encrypts secrets)

git crypt lock

Now if we try viewing encrypted content, it should be encrypted.

cat ~/Development/nixos-config/.secrets/test.txt

To unlock/decrypt secrets

git crypt unlock

Now if we try viewing encrypted content, it should be decrypted.

cat ~/Development/nixos-config/.secrets/test.txt