Skip to content

Instantly share code, notes, and snippets.

@0atman
Last active July 5, 2024 04:13
Show Gist options
  • Save 0atman/1a5133b842f929ba4c1e195ee67599d5 to your computer and use it in GitHub Desktop.
Save 0atman/1a5133b842f929ba4c1e195ee67599d5 to your computer and use it in GitHub Desktop.
A rebuild script that commits on a successful build
{
config,
pkgs,
options,
...
}: let
hostname = "oatman-pc"; # to alllow per-machine config
in {
networking.hostName = hostname;
imports = [
/etc/nixos/hardware-configuration.nix
(/home/oatman/dotfiles/nixos + "/${hostname}.nix")
];
}
#!/usr/bin/env bash
#
# I believe there are a few ways to do this:
#
# 1. My current way, using a minimal /etc/nixos/configuration.nix that just imports my config from my home directory (see it in the gist)
# 2. Symlinking to your own configuration.nix in your home directory (I think I tried and abandoned this and links made relative paths weird)
# 3. My new favourite way: as @clot27 says, you can provide nixos-rebuild with a path to the config, allowing it to be entirely inside your dotfies, with zero bootstrapping of files required.
# `nixos-rebuild switch -I nixos-config=path/to/configuration.nix`
# 4. If you uses a flake as your primary config, you can specify a path to `configuration.nix` in it and then `nixos-rebuild switch —flake` path/to/directory
# As I hope was clear from the video, I am new to nixos, and there may be other, better, options, in which case I'd love to know them! (I'll update the gist if so)
# A rebuild script that commits on a successful build
set -e
# Edit your config
$EDITOR configuration.nix
# cd to your config dir
pushd ~/dotfiles/nixos/
# Early return if no changes were detected (thanks @singiamtel!)
if git diff --quiet '*.nix'; then
echo "No changes detected, exiting."
popd
exit 0
fi
# Autoformat your nix files
alejandra . &>/dev/null \
|| ( alejandra . ; echo "formatting failed!" && exit 1)
# Shows your changes
git diff -U0 '*.nix'
echo "NixOS Rebuilding..."
# Rebuild, output simplified errors, log trackebacks
sudo nixos-rebuild switch &>nixos-switch.log || (cat nixos-switch.log | grep --color error && exit 1)
# Get current generation metadata
current=$(nixos-rebuild list-generations | grep current)
# Commit all changes witih the generation metadata
git commit -am "$current"
# Back to where you were
popd
# Notify all OK!
notify-send -e "NixOS Rebuilt OK!" --icon=software-update-available
@0atman
Copy link
Author

0atman commented Mar 19, 2024

@aikomastboom love the alejandra tweak - added.

Interesting sudo tweak - but on my machine root using sudo is a no-op and can safely run both normal and sudoed commands?

@aikomastboom
Copy link

Yeah, I know.. I came across it when fiddling with a VM that only had root and no sudo installed

I like the idea to nixify the script too ( to ensure those dependency commands are available)

@MvRens
Copy link

MvRens commented Mar 19, 2024

Fellow NixOS noob here thanks to your video! thanks for sharing this script as well.

FYI, I had to surround the two references to '*.nix' in single quotes to prevent bash from expanding the glob which resulted in 'No changes detected' and no diff output. Probably because my configuration is mostly in subfolders.

@0atman
Copy link
Author

0atman commented Mar 20, 2024

@MvRens updated, well spotted!

@mipdableep
Copy link

Hi! First of all, great video and an amazing script!
A weird problem i got stuck with is the fact that the nixos-rebuild hashing would not rebuild if the git repo was dirty - this blog post helped but i realized that staging the files fixed it - git add ./*.nix before the rebuild stage.
Aside from that, i found that using sudo nix-env -p /nix/var/nix/profiles/system --list-generations | grep "current" gave a cleaner output then nixos-rebuild list-generations

@JustCoderdev
Copy link

I added a bit where if a rebuild fails it asks if you want to open the logs or not

# In my case I use flakes but here it checks whether it fails or not
if sudo nixos-rebuild switch --flake ".#$1" &>.nixos-switch.log; then
	echo -e "Done\n"
else
	echo ""
	cat .nixos-switch.log | grep --color error

	# this is needed otherwise the script would not start next time telling you "no changes detected"
	# (The weird patter is to include all subdirectories)
	sudo git restore --staged ./**/*.nix

	if read -p "Open log? (y/N): " confirm && [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then
		cat .nixos-switch.log | vim - 	
	fi

	# Clean stuff and exit
	shopt -u globstar
	popd > /dev/null
	exit 1
fi

thx @0atman for the *hem inspiration ;)

@0atman
Copy link
Author

0atman commented Mar 26, 2024

Very cool!

@taiwithers
Copy link

Here's a version that's I edited to work with Home Manager and custom *.nix file locations, I've also added a segment to check for untracked *.nix files since these don't get picked up by git diff
Not sure if ether of those things are useful to anyone else but shrug

@Mjb141
Copy link

Mjb141 commented May 25, 2024

Thanks for sharing this script. Now, I won't ruin my system because I messed up my configuration.nix. One improvement that I made when I started using it was to handle the script itself the nix way by storing is a nixos-rebuild.nix file:

{
  config,
  pkgs,
  ...
}: {
  environment.systemPackages = with pkgs; [
    (writeShellScriptBin "nixos-rebuild.sh" ''
    // Script without shebang
        '')
  ];
}

And just importing it in my managed version of configuration.nix. This way, I don't need to think about shebang and my script is also versioned via NixOS using generations too.

Can you link how you've done this? I've imported such a file into my configuration.nix but it's not making the script findable on PATH.

@Lemm1
Copy link

Lemm1 commented May 26, 2024

Can you link how you've done this? I've imported such a file into my configuration.nix but it's not making the script findable on PATH.

You need to rebuild the system first use simple nixos-rebuild switch once so script is generated by nix and added to PATH

@Mjb141
Copy link

Mjb141 commented May 26, 2024

Yeah all good, got it working shortly afterwards. Added to it with a Home-Manager step as well, very useful script!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment