-
-
Save 0atman/1a5133b842f929ba4c1e195ee67599d5 to your computer and use it in GitHub Desktop.
{ | |
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 |
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.
@MvRens updated, well spotted!
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
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 ;)
Very cool!
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
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.
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
Yeah all good, got it working shortly afterwards. Added to it with a Home-Manager step as well, very useful script!
Hi Tris, thanks to you I benefit from NixOS and I recently stumbled to a tool called nh that can be integrated to your workflow, you might want to check it out.
@ArgumentumAdUlgenum yeah! I also recently discovered nh (thanks to the #nix channel on my discord) - and really like it.
HOWEVER, I recently switched my whole setup away from flakes to get back unattended upgrade (and some other reasons) , which means I can't use nh (it requires flakes). However, as there are only 3 main features, according to the readme:
- Tree of builds with nix-output-monitor
- Visualization of the upgrade diff with nvd
- Asking for confirmation before performing activation
... The only one of those features I didn't really have (due to my git diff printing) was the build tree visualising using nom, which is easy enough to add on to this existing script! 😁
For those who want it, the line is
sudo nixos-rebuild --upgrade switch --log-format internal-json |& nom --json
which outputs the log in json, that nom
consumes.
So, I tried to make a flake free configuration and arrived at conclusion flakes makes it far easier to deal with dependencies to other nix projects like home-manager or nixvim.
As far as I know you use Nix to just configure your computer, your dotfiles are managed outside of Nix. If you ever decide to change from this paradigm, you might want to give flakes another chance.
See you later Tris.
Yeah, I actually abandoned not having flakes enabled after a day - so many tools assume you've got a flakes system. The rust flake works very well, for instance. I'm down to use it for links to these other projects - but not core system stuff.
I'm sad though: My dream of unattended upgrades seems dead. By design, flakes don't update their lockfile without user input, right?
The difference between me and many nix folks is that I don't care about reproducibility. I care about stability and bleeding-edge features. Lucky for me, Nixos gives me that!
I did indeed trynixvim for a while, but lazynvim is turnkey, so I'm simply using that. Home Assistant is fine, but I don't think it makes sense for my low-stress life. I want my config to instantly change when I change a config file, not requiring a hm switch - an symlinks work great for that!
Using GNU Stow I run stow .
on my dotfiles directory, and with no config, everything's symlinked into my home directory. I get config rollback with git, and given that neither HM or Stow is linked to my nixos system generations... feels like I'm not missing anything?
I'm sad though: My dream of unattended upgrades seems dead. By design, flakes don't update their lockfile without user input, right? The difference between me and many nix folks is that I don't care about reproducibility. I care about stability and bleeding-edge features. Lucky for me, Nixos gives me that!
Ditto on the reproducability (I want reproducability in my package set and configs but versions are unimportant to me). It's not quite "unattended", but you could add a nix flake update
line into your rebuild script and update lock files that way
Very good point. I could perhaps run that on a cron?
@0atman You can create a systemd service with nixos that does it automagically
systemd.services.bleeding_edger = {
enable = true;
path = [ pkgs.nix ];
serviceConfig = {
ExecStart = "nix flake update";
}
}
Extra help: https://discourse.nixos.org/t/creating-a-systemd-service-that-runs-a-nix-command/38437
I always thought that --update-input flag in system.autoUpgrade basically does nix flake update before schedules update. At least wiki says that it's enough for flake system to get autoupdates: https://nixos.wiki/wiki/Automatic_system_upgrades
Very good point. I could perhaps run that on a cron?
In my system nix flake update command requires sudo, I'm pretty sure this wasn't always the case though.
I did indeed trynixvim for a while, but lazynvim is turnkey, so I'm simply using that. Home Assistant is fine, but I don't think it makes sense for my low-stress life.
I also experienced the issue of not being able to set things too easily when using home-manager. So I use home-manager to set things like setting universal colorscheme with stylix, and configurations that I don't always mess with, I'm confident I want them in a certain way.
I used to configure my browser with Nix too but I stopped doing that since it was a pain Nix overwriting some of the things I changed between rebuilds every time. Stow is an amazing tool for your use-case though. I feel bad I didn't knew it i before i spent many months running mostly Arch.
so many tools assume you've got a flakes system
A wise man once told "Popularity Matters" in his "The Unreasonable Effectiveness Of Plain Text" video . Flakes, let alone still being labeled as a experimental feature, as far as i know 40% of Nix users use it. Probably has a higher margin on desktop usage.
New functionality implemented: instead of hiding the output of the rebuild script (creating anti-climatic moments) what about using the alternative screen buffer? So when the program is done all the logs go away and you're left with a pleasant 'Rebuild Completed' or not so pleasant 'Rebuild failed'
Final output
/.dotfiles/nixos $ rebuild-system
Hostname not passed, defaulting to #acer
Analysing changes... Not found
Rebuilding NixOS... Done
[sudo] password for justcode:
NixOS Rebuild Completed!
/.dotfiles/nixos $
Here the escape codes to enter alt screen buffer
# Enter alt-buff and clear screen
echo -ne "\033[?1049h\033[H"
# Exit alt-buff
echo -ne "\033[?1049l"
And here's the snippet that I use
# Rebuild system
echo -n "Rebuilding NixOS... "
echo -ne "\033[?1049h\033[H" # enter alt-buff and clear
echo "Rebuilding NixOS..."
set +o pipefail # Disable pipafail since we check ourselves
# shellcheck disable=SC2024 #ah the irony
sudo nixos-rebuild switch --show-trace --flake ".#${HOST_SHELL}" 2>&1 | tee .nixos-switch.log
exit_code="${PIPESTATUS[0]}"
set -o pipefail # Re-enable pipefail
# Wait a bit before exiting buffer
echo -e "\n\033[34mNixOS rebuild completed\033[0m (code: $exit_code)"
echo -ne "\rExit in 3" && sleep 1
echo -ne "\rExit in 2" && sleep 1
echo -ne "\rExit in 1" && sleep 1
echo -ne "\033[?1049l" # exit alt-buff
# Check exit code of nixos-rebuild and act accordingly
if [[ "${exit_code}" == 0 ]]; then
echo -e "Done\n"
...
Holy carp, that's some deep magic there, thank you! Will experiment
@0atman You can test the full version of the script by taking it from my dotfiles. This way you can get a feel if you like it or not [link]
let me know ;)
edit: You might want to disable certain stuff like the automatic host recognition, the flake auto-update (based on the current host), the auto-restore (so that it can properly detect if it's rebuilding with changes after a failed attempt) and the auto-commit (for obvious reasons)
Thank you! Hopefully useful for others too!
I found out something very useful
You can unlink
nixos files without extra permissions and on the next rebuild they will get recreated
This means that when you want to quickly iterate over a configuration (waybar for example) you can remove the nixos link, point it to your configuration folder, modify it and test things out without having to rebuild
When you're done just rebuild and nixos will bake the new config into the next generation
Isn't the current autoformatting command forgetting to popd on formatting failure?
@S1rDev10us huh, I don't think pushd/popd work in the way I (or maybe you!) think. Perhaps someone smarter than I can explain what happens to the directory stack on an early exit?
A script I just tried that surprised me:
#!/usr/bin/env bash
set -e
pushd ~/Music
pwd
exit 1
# after exit, cwd is back where we started, despite not popd-ing
@0atman As far I know pushd
and popd
act only inside of the shell that get's created when you execute the script, like if you had two terminals and you changed directory in one of them. Once the script has terminated it exits to the "outer shell" (bash or zsh) and resume the previous environment
oh of course! it's running in the shebang's process, not hijacking the outer shell 😅
I have a laptop with only two cores and - since everytime I started a rebuild it would freeze my desktop - I implemented the simplest throttling mechanism to tell nixos-rebuild to use only half of the available cores (snippet below)
# Detect processors
procs="$(nproc)"
if [ -z "${procs:-}" ]; then
echo "No processors detected! Assuming 2..."
procs="2"
fi
hprocs="$(( procs / 2 ))"
echo "Detected ${procs} processors, using ${hprocs} of them"
nixos-rebuild switch --max-jobs "${hprocs}" #...
Yeah, I know.. I came across it when fiddling with a VM that only had root and no
sudo
installedI like the idea to nixify the script too ( to ensure those dependency commands are available)