7.2 KiB
Configuration Diff Tool
Tool to compare all NixOS host configurations between current working tree and HEAD commit.
Purpose
Before committing changes (especially refactors), verify that you haven't accidentally broken existing host configurations. This tool:
- Builds all host configurations in current state (with uncommitted changes)
- Builds all host configurations at HEAD (last commit)
- Uses
nvdto show readable diffs for each host - Highlights which hosts changed and which didn't
Usage
Prerequisites
The script requires nvd to be in PATH. Use either:
Option 1: direnv (recommended)
# Allow direnv in the repository (one-time setup)
direnv allow
# direnv will automatically load the dev shell when you cd into the directory
cd /home/ppetru/projects/alo-cluster
# nvd is now in PATH
Option 2: nix develop
# Enter dev shell manually
nix develop
# Now run the script
./scripts/diff-configs.sh
Quick Start
# Compare all hosts (summary)
./scripts/diff-configs.sh
# Compare with detailed path listing
./scripts/diff-configs.sh -v c1
# Compare with content diffs of changed files (deep mode)
./scripts/diff-configs.sh --deep c1
# Compare only x86_64 hosts (avoid slow ARM cross-compilation)
./scripts/diff-configs.sh c1 c2 c3 zippy chilly sparky
# Verbose mode with multiple hosts
./scripts/diff-configs.sh --verbose c1 c2 c3
# Via flake app
nix run .#diff-configs
# Show help
./scripts/diff-configs.sh --help
Typical Workflow
# 1. Make changes to configurations
vim common/impermanence.nix
# 2. Stage changes (required for flake to see them)
git add common/impermanence.nix
# 3. Check what would change if you committed now
# For quick feedback, compare only x86_64 hosts first:
./scripts/diff-configs.sh c1 c2 c3 zippy chilly sparky
# 4. Review output, make adjustments if needed
# 5. If changes look good and affect ARM hosts, check those too:
./scripts/diff-configs.sh stinky alo-cloud-1
# 6. Commit when satisfied
git commit -m "Refactor impermanence config"
Output Explanation
No Changes
━━━ c1 ━━━
Building current... done
Building HEAD... done
✓ No changes
This host's configuration is identical between current and HEAD.
Changes Detected
━━━ stinky ━━━
Building current... done
Building HEAD... done
⚠ Configuration changed
<<< /nix/store/abc-nixos-system-stinky-25.05 (HEAD)
>>> /nix/store/xyz-nixos-system-stinky-25.05 (current)
Version changes:
[C] octoprint: 1.9.3 -> 1.10.0
[A+] libcamera: ∅ -> 0.1.0
Closure size: 1500 -> 1520 (5 paths added, 2 paths removed, +3, +15.2 MB)
Legend:
[C]- Changed package version[A+]- Added package[R-]- Removed package[U.]- Updated (same version, rebuilt)
Verbose Mode (--verbose)
With -v or --verbose, also shows the actual store paths that changed:
━━━ c1 ━━━
Building current... done
Building HEAD... done
⚠ Configuration changed
[nvd summary as above]
Changed store paths:
Removed (17 paths):
- config.fish
- system-units
- home-manager-generation
- etc-fuse.conf
... and 13 more
Added (17 paths):
- config.fish
- system-units
- home-manager-generation
- etc-fuse.conf
... and 13 more
This is useful when nvd shows "No version changes" but paths still changed (e.g., refactors that rebuild config files).
Deep Mode (--deep)
With -d or --deep, shows actual content diffs of changed files within store paths (implies verbose):
━━━ c1 ━━━
Building current... done
Building HEAD... done
⚠ Configuration changed
[nvd summary and path listing as above]
Content diffs of changed files:
▸ etc-fuse.conf
@@ -1,2 +1,2 @@
-user_allow_other
+#user_allow_other
mount_max = 1000
▸ nixos-system-c1-25.05
activate:
@@ -108,7 +108,7 @@
echo "setting up /etc..."
-/nix/store/...-perl/bin/perl /nix/store/...-setup-etc.pl /nix/store/abc-etc/etc
+/nix/store/...-perl/bin/perl /nix/store/...-setup-etc.pl /nix/store/xyz-etc/etc
▸ unit-dbus.service
dbus.service:
@@ -1,5 +1,5 @@
[Service]
+Environment="LD_LIBRARY_PATH=/nix/store/.../systemd/lib"
Environment="LOCALE_ARCHIVE=..."
What it shows:
- Matches changed paths by basename (e.g., both have "config.fish")
- Diffs important files: activate scripts, etc/*, *.conf, *.fish, *.service, *.nix
- Shows unified diff format (lines added/removed)
- Limits to first 50 lines per file
When to use:
- When you need to know what exactly changed in config files
- Debugging unexpected configuration changes
- Reviewing refactors that don't change package versions
- Understanding why a host rebuilt despite "No version changes"
Build Failures
━━━ broken-host ━━━
Building current... FAILED
Error: attribute 'foo' missing
If a host fails to build, the error is shown and the script continues with other hosts.
How It Works
- Discovers hosts: Queries
deploy.nodesfrom flake to get all configured hosts - Creates worktree: Uses
git worktreeto check out HEAD in a temporary directory - Builds configurations: Builds
config.system.build.toplevelfor each host in both locations - Compares with nvd: Runs
nvd diffto show package-level changes - Cleans up: Removes temporary worktree automatically
Important Notes
Git Staging Required
Flakes only evaluate files that are tracked by git. To make changes visible:
# Stage new files
git add new-file.nix
# Stage changes to existing files
git add modified-file.nix
# Or stage everything
git add .
Unstaged changes to tracked files are visible (flake uses working tree content).
Performance
- First run may be slow (building all configurations)
- Subsequent runs benefit from Nix evaluation cache
- Typical runtime: 1-5 minutes depending on changes
- ARM cross-compilation is slow: Use host filtering to avoid building ARM hosts when not needed
- Example:
./scripts/diff-configs.sh c1 c2 c3(x86_64 only, fast) - vs
./scripts/diff-configs.sh(includes stinky/alo-cloud-1, slow)
- Example:
When to Use
Good use cases:
- Refactoring shared modules (like impermanence)
- Updating common configurations
- Before committing significant changes
- Verifying deploy target consistency
Not needed for:
- Adding a single new host
- Trivial one-host changes
- Documentation updates
Troubleshooting
"Not in a git repository"
cd /home/ppetru/projects/alo-cluster
./scripts/diff-configs.sh
"No changes detected"
All changes are already committed. Stage some changes first:
git add .
Build failures for all hosts
Check flake syntax:
nix flake check
nvd not found
Install nvd:
nix profile install nixpkgs#nvd
(Already included in workstation-node.nix packages)
Related Tools
nvd- Package diff tool (used internally)nix diff-closures- Low-level closure diffnix store diff-closures- Alternative diff commanddeploy-rs- Actual deployment tool
See Also
common/global/show-changelog.nix- Shows changes during system activationdocs/RASPBERRY_PI_SD_IMAGE.md- SD image building process