See changes between two generations

If I use system.autoUpgrade.enable = true, how can I see which upgrades were installed between two generations?

NixOS doesn’t do upgrades in the traditional sense.
Nix builds a new system, that may share some data with the old system if it happens to use the same derivations.
There are basically two ways to go about this:

  1. Compare the input (typically nixpkgs and your configuration)
    For your own configuration, you should use a version control system to get the differences.
    For nixpkgs, you can look up the system path that contains the nixpkgs git revision that was used to build it (/nix/store/x04dfrwv3qariypy4m7lw4ldz98rmm4s-nixos-system-yuna-18.09.2347.fdb5b68d155 → nixpkgs git revision fdb5b68d155) and read the Commit messages between these two commits.

  2. Ask nix about each system generation for the full set of derivations that each generation uses and then compare them for their differences.
    First thing is to get the links to the generations you want to compare:

$ ls -ld /nix/var/nix/profiles/system* /run/current-system /run/booted-system
lrwxrwxrwx 1 root root 15 20. Mär 01:25 /nix/var/nix/profiles/system -> system-185-link
lrwxrwxrwx 1 root root 79  8. Feb 16:23 /nix/var/nix/profiles/system-165-link -> /nix/store/77jx66dn1f0r8da2i1xm28m8hwcyfgzv-nixos-system-yuna-18.09.git.b1f4d5d
lrwxrwxrwx 1 root root 84 28. Feb 05:55 /nix/var/nix/profiles/system-166-link -> /nix/store/l0kgd1w5ja6m7s7vhz3sy1rhzblqjmis-nixos-system-yuna-18.09.2273.1374ba6080b
lrwxrwxrwx 1 root root 79 28. Feb 10:27 /nix/var/nix/profiles/system-167-link -> /nix/store/3116yzipa3dhcfjlgzl7ymycnpqm8icw-nixos-system-yuna-18.09.git.49043ea
lrwxrwxrwx 1 root root 79  2. Mär 01:21 /nix/var/nix/profiles/system-168-link -> /nix/store/0xan64rv784fg2s47ic79h52403qi5h5-nixos-system-yuna-18.09.git.49043ea
lrwxrwxrwx 1 root root 79  2. Mär 01:23 /nix/var/nix/profiles/system-169-link -> /nix/store/0d53g9j6snh2wp2wz8mf2zx61lvlgxyk-nixos-system-yuna-18.09.git.49043ea
lrwxrwxrwx 1 root root 79  4. Mär 03:48 /nix/var/nix/profiles/system-170-link -> /nix/store/45bnngnm7a38f67akkadnh07mb4w1f27-nixos-system-yuna-18.09.git.c4e8634
lrwxrwxrwx 1 root root 84  4. Mär 04:41 /nix/var/nix/profiles/system-171-link -> /nix/store/spbrvhdkl32qki22l4yz0c224z94bgjy-nixos-system-yuna-18.09.2300.770d3ca4910
lrwxrwxrwx 1 root root 84  5. Mär 00:16 /nix/var/nix/profiles/system-172-link -> /nix/store/gyv6mfs79w6hyjcsfy8x0pmlbr03balz-nixos-system-yuna-18.09.2300.770d3ca4910
lrwxrwxrwx 1 root root 79  5. Mär 22:26 /nix/var/nix/profiles/system-173-link -> /nix/store/6479wbbcvmczz89nliapf8ww35x28s3y-nixos-system-yuna-18.09.git.1fc3a8b
lrwxrwxrwx 1 root root 79  7. Mär 22:50 /nix/var/nix/profiles/system-174-link -> /nix/store/fybwb0pkv8zg8fzzw6yjnkvnyjg72laz-nixos-system-yuna-18.09.git.1fc3a8b
lrwxrwxrwx 1 root root 79  7. Mär 23:31 /nix/var/nix/profiles/system-175-link -> /nix/store/csp3fdd3gi7jq8wbk95wq6qrxzzd6ssk-nixos-system-yuna-18.09.git.1fc3a8b
lrwxrwxrwx 1 root root 79  7. Mär 23:40 /nix/var/nix/profiles/system-176-link -> /nix/store/42a5zcz6gdyzlbqy4sd8fn3nf4brzfxh-nixos-system-yuna-18.09.git.1fc3a8b
lrwxrwxrwx 1 root root 79 13. Mär 00:02 /nix/var/nix/profiles/system-177-link -> /nix/store/8pi6rfgccl9x2r1n3xgncljfhl8ywnvj-nixos-system-yuna-18.09.git.1fc3a8b
lrwxrwxrwx 1 root root 79 15. Mär 03:13 /nix/var/nix/profiles/system-178-link -> /nix/store/rxlgci5raax4dmjfqrszad8ysxdsblmh-nixos-system-yuna-18.09.git.b5bfc29
lrwxrwxrwx 1 root root 79 16. Mär 02:33 /nix/var/nix/profiles/system-179-link -> /nix/store/d1dnblsf2f5xj8cw3qr96qv342wp6pjn-nixos-system-yuna-18.09.git.b5bfc29
lrwxrwxrwx 1 root root 79 16. Mär 03:11 /nix/var/nix/profiles/system-180-link -> /nix/store/awcj0m4jnq5wbdij4dajryq4607i0mdl-nixos-system-yuna-18.09.git.b5bfc29
lrwxrwxrwx 1 root root 84 16. Mär 05:33 /nix/var/nix/profiles/system-181-link -> /nix/store/x04dfrwv3qariypy4m7lw4ldz98rmm4s-nixos-system-yuna-18.09.2347.fdb5b68d155
lrwxrwxrwx 1 root root 79 16. Mär 21:15 /nix/var/nix/profiles/system-182-link -> /nix/store/7qsjmalyvli3c1lihzn3kamsd7g82dqy-nixos-system-yuna-18.09.git.bf51577
lrwxrwxrwx 1 root root 79 19. Mär 23:35 /nix/var/nix/profiles/system-183-link -> /nix/store/aiw9dxq1m0r52vxc8kra943jj1r4mabs-nixos-system-yuna-18.09.git.bf51577
lrwxrwxrwx 1 root root 79 20. Mär 00:25 /nix/var/nix/profiles/system-184-link -> /nix/store/n43vmgkxag08sqa235b0k1j1209disn5-nixos-system-yuna-18.09.git.d670e90
lrwxrwxrwx 1 root root 79 20. Mär 01:15 /nix/var/nix/profiles/system-185-link -> /nix/store/h1w0zf0i8zg1160m19bw6ihnsmmpgq15-nixos-system-yuna-18.09.git.d670e90
lrwxrwxrwx 1 root root 79 20. Mär 21:28 /run/booted-system -> /nix/store/h1w0zf0i8zg1160m19bw6ihnsmmpgq15-nixos-system-yuna-18.09.git.d670e90
lrwxrwxrwx 1 root root 79 20. Mär 21:28 /run/current-system -> /nix/store/h1w0zf0i8zg1160m19bw6ihnsmmpgq15-nixos-system-yuna-18.09.git.d670e90

Then get the list of derivations used by each generation:

$ nix-store -qR /nix/var/nix/profiles/system-184-link
/nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27
/nix/store/3s920c43pgzi6vdabjs90in308jnbckv-zlib-1.2.11
[...]

To compare them you can use something like the following command, here I’m comparing the generations 184 and 185, which only differ through configuration changes, not any updates to nixpkgs.

$ diff -Naur <( nix-store -qR /nix/var/nix/profiles/system-184-link ) <( nix-store -qR /nix/var/nix/profiles/system-185-link ) | egrep ^[+-]/
-/nix/store/hbzc2rk2mqp4f7z7ylv9wcz4gm42fjgs-font-adobe-75dpi-1.0.3
-/nix/store/szqi2l00ijd5zix6i4p6ljh4y7h9n4ad-kyocera-ppds-1.4
-/nix/store/maf70vcsgp04k32b5iy21rnrilaq6izx-cups-progs
-/nix/store/wcq7xs1kgl3vf989zxxfl4sx5mcgmrq0-cups-files.conf
-/nix/store/z6gd2prsy32g8qi4ka5hc19fzknw15pb-snmp.conf
-/nix/store/m8j9i7aq180xb7l6mcp1kz5fj2ay4v35-cups-progs
-/nix/store/hdhvj8l5vlyjnvyhvva3ilhykmzhfn7g-unit-script-cups-pre-start
-/nix/store/i8ld0glqrb2mgrjzb6pxx0sxdh1vcdr1-unit-zfs-share.service
-/nix/store/icq4p3mkc8c1flmbysidsyxfv2dgbpdl-libva-vdpau-driver-0.7.4
-/nix/store/iqz3rqdc92d2x11k0v7w7jiva19vx7xg-unit-script-nix-gc-start
-/nix/store/iwk62wwyb5hhqlr32wibxxkhh832764h-unit-upower.service
-/nix/store/j4l88fq04w5j4fp5pjn22mdl65hnvbjr-unit-zfs-import.target
-/nix/store/j6l5mcbkjwdyv2d10zk1piw7m1n0n3nd-desktops
-/nix/store/jmcj5yryd3f4cqmqxx1nbvh58j78fwgh-unit-burpClient.service
-/nix/store/y9mlxa5frlff3s6idhsrzssp7yq2fvll-Xresources-Xft
-/nix/store/k19fa5a2cgsc09nr8nzq56j3p05bjfvi-xsession-wrapper
-/nix/store/y2ndj4bwdlgmlijv679fvai9aklifzyk-unit-script-prepare-kexec-start
-/nix/store/k5rzi579hyz240srqqsx2viab2rf7jss-unit-prepare-kexec.service
-/nix/store/kd28l168krl6kxxlyj61qdxvnni3vbzv-unit-network-interfaces.target
-/nix/store/kd49ram95ri5bqz69q3293nk3qkzrckl-mesa-drivers+txc-18.1.7
-/nix/store/kdwsfn6c6jiyj1hcvd011rwl8lj24rbw-unit-network-online.target
+/nix/store/hbzc2rk2mqp4f7z7ylv9wcz4gm42fjgs-font-adobe-75dpi-1.0.3
+/nix/store/i8ld0glqrb2mgrjzb6pxx0sxdh1vcdr1-unit-zfs-share.service
+/nix/store/iwk62wwyb5hhqlr32wibxxkhh832764h-unit-upower.service
+/nix/store/j4l88fq04w5j4fp5pjn22mdl65hnvbjr-unit-zfs-import.target
+/nix/store/jmcj5yryd3f4cqmqxx1nbvh58j78fwgh-unit-burpClient.service
+/nix/store/y2ndj4bwdlgmlijv679fvai9aklifzyk-unit-script-prepare-kexec-start
+/nix/store/k5rzi579hyz240srqqsx2viab2rf7jss-unit-prepare-kexec.service
+/nix/store/kd28l168krl6kxxlyj61qdxvnni3vbzv-unit-network-interfaces.target
+/nix/store/kdwsfn6c6jiyj1hcvd011rwl8lj24rbw-unit-network-online.target
+/nix/store/szqi2l00ijd5zix6i4p6ljh4y7h9n4ad-kyocera-ppds-1.4
+/nix/store/maf70vcsgp04k32b5iy21rnrilaq6izx-cups-progs
+/nix/store/wcq7xs1kgl3vf989zxxfl4sx5mcgmrq0-cups-files.conf
+/nix/store/z6gd2prsy32g8qi4ka5hc19fzknw15pb-snmp.conf
+/nix/store/m8j9i7aq180xb7l6mcp1kz5fj2ay4v35-cups-progs
+/nix/store/hdhvj8l5vlyjnvyhvva3ilhykmzhfn7g-unit-script-cups-pre-start
+/nix/store/iqz3rqdc92d2x11k0v7w7jiva19vx7xg-unit-script-nix-gc-start
+/nix/store/j6l5mcbkjwdyv2d10zk1piw7m1n0n3nd-desktops
+/nix/store/y9mlxa5frlff3s6idhsrzssp7yq2fvll-Xresources-Xft
+/nix/store/k19fa5a2cgsc09nr8nzq56j3p05bjfvi-xsession-wrapper
+/nix/store/icq4p3mkc8c1flmbysidsyxfv2dgbpdl-libva-vdpau-driver-0.7.4
+/nix/store/kd49ram95ri5bqz69q3293nk3qkzrckl-mesa-drivers+txc-18.1.7
-/nix/store/n43vmgkxag08sqa235b0k1j1209disn5-nixos-system-yuna-18.09.git.d670e90
+/nix/store/h1w0zf0i8zg1160m19bw6ihnsmmpgq15-nixos-system-yuna-18.09.git.d670e90
1 Like

I’ve found the nox-update command in GitHub - madjar/nox: Tools to make nix nicer to use to be really useful for this. It produces a lot of output when comparing two entire systems, so I usually run it like this to get a higher-level summary:

nox-update --quiet /run/current-system result | \
grep -v '\.drv : $' | \
sed 's|^ */nix/store/[a-z0-9]*-||' | \
sort -u
1 Like

You can use nix-diff to see the difference between two generations.

nix run nixpkgs.nix-diff
cd /nix/var/nix/profiles
nix-diff $(nix-store -qd system-1139-link system-1140-link)

Unfortunately you have to provide the deriver files instead of the output paths, hence the nix-store -qd.

4 Likes

It looks like this works for NixOS but doesn’t provide anything useful on a single-user Nix install on macOS:

bash-3.2$ nix-diff $(nix-store -qd profile-49-link profile-50-link)
- /nix/store/98m72sh8yj6qrk421sf1yab81ysbyb8r-user-environment.drv:{out}
+ /nix/store/nashi0qvbgrybxwfs24864kahslxzz95-user-environment.drv:{out}
• The set of input sources do not match:
    - /nix/store/q62ifwlk3pa5ab634bcsvg6qqjam84fn-env-manifest.nix
    + /nix/store/jylxqib8rima6yp92kvf1zic0gp9kzdk-env-manifest.nix

That just tells you that you need to diff those two files

diff /nix/store/q62ifwlk3pa5ab634bcsvg6qqjam84fn-env-manifest.nix /nix/store/jylxqib8rima6yp92kvf1zic0gp9kzdk-env-manifest.nix

Ah. Unfortunately, those files are single-line JSON blobs so diffing isn’t very effective >_< I suppose I could write tooling around this.

Alternatively, I may just explore trying to script diffing the output of nix-env -q between generations, using NIX_PROFILE to specify the generation to look at. That will probably give me the closest output to what I want (which is primarily to see which explicitly requested packages were installed/uninstalled/updated in each generation). I’m kind of surprised there’s no built-in way to diff generations like this.

You should have a look at nix-script diff-generations ... from https://github.com/matthiasbeyer/nixos-scripts. It is the best option that I am aware of.

2 Likes

Thanks! Kind of surprised there’s no derivation to install that.

I don’t understand why a copy of the /etc/nixos/configuration.nix isn’t taken when creating each generation. Sure it’s not everything but for 80% it’s enough. Telling people you should version control it separately to the generations seems unhelpful because if we’re going to do that then do it automatically. Make it part of the process that when you nixos-rebuild switch it commits the config. I am underwhelmed that one needs to compare the outputs to figure out what changed between versions. It’s a poor ux story when this really should be nixos’s strength.

3 Likes

It is already at least missing hardware-configuration.nix which is essential.

This is terrible when trying out things and debugging and you had 10 generations before it fully worked and then you do one commit for that.

ux is not a strength of NixOS if we are honest to us.

results in:

Traceback (most recent call last):
  File "/nix/store/k1gfddlghj5gncfpjjgqra5sgvanwicd-nox-0.0.6/bin/.nox-update-wrapped", line 9, in <module>
    sys.exit(main())
             ^^^^^^
  File "/nix/store/2z0jalw27lp6zm642aqvnlydlqblhcdf-python3.11-click-8.1.7/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/2z0jalw27lp6zm642aqvnlydlqblhcdf-python3.11-click-8.1.7/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/nix/store/2z0jalw27lp6zm642aqvnlydlqblhcdf-python3.11-click-8.1.7/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/2z0jalw27lp6zm642aqvnlydlqblhcdf-python3.11-click-8.1.7/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/k1gfddlghj5gncfpjjgqra5sgvanwicd-nox-0.0.6/lib/python3.11/site-packages/nox/update.py", line 196, in main
    diff_pkgs(refs_tree, current_drv, new_drv, opts)
  File "/nix/store/k1gfddlghj5gncfpjjgqra5sgvanwicd-nox-0.0.6/lib/python3.11/site-packages/nox/update.py", line 154, in diff_pkgs
    current_names[(drv.name, bool(drv.extension))].append((parse_version(drv.version), drv))
                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/y8yq448xka665bqyd5gvdhajqdbsnyys-python3.11-setuptools-68.2.2/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/version.py", line 198, in __init__
    raise InvalidVersion(f"Invalid version: '{version}'")
pkg_resources.extern.packaging.version.InvalidVersion: Invalid version: '5.2-p15'

any workaround for that?

Sorry, I’m not sure. I’ve actually moved on from nox to nvd for diffing generations; it’s a much better tool for the purpose IMO.

2 Likes

Low-tech, newbie approach:

$ nix-env --list-generations
   1   2024-03-27 14:55:08   
   2   2024-04-06 14:27:14   (current)

$ nix profile list --profile \
   /home/pmorch/.local/state/nix/profiles/profile-1-link | \
   grep ^Name:
Name:               glibc-locales

$ nix profile list --profile \
   /home/pmorch/.local/state/nix/profiles/profile-2-link | \
   grep ^Name:
Name:               glibc-locales
Name:               neofetch-unstable

So I added neofetch-unstable between 1 and 2.

At least today on my 23.11 system the store query was unneeded, nix-diff system-{1,2}.link gives practically the same output:

Proof by diffing the diffs:

sdiff -sw180 <(nix-diff $(nix-store -qd system-{16,17}-link)) <(nix-diff system-{16,17}-link)
- /nix/store/jajklhjdkgvrmxhlysi4jmjg77ww266b-nixos-system-desktop-23.11.5541.56528ee |	- system-16-link:{out}
+ /nix/store/753lnpm727ifvbl4bn4x47gcw4sghxhj-nixos-system-desktop-23.11.5541.56528ee |	+ system-17-link:{out}