diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md index b7cbe4b1323..b9f1c814cd5 100644 --- a/nixos/doc/manual/release-notes/rl-2311.section.md +++ b/nixos/doc/manual/release-notes/rl-2311.section.md @@ -8,6 +8,8 @@ - LXD now supports virtual machine instances to complement the existing container support +- The `nixos-rebuild` command has been given a `list-generations` subcommand. See `man nixos-rebuild` for more details. + ## New Services {#sec-release-23.11-new-services} - [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server built for redstone. Available as [services.mchprs](#opt-services.mchprs.enable). diff --git a/pkgs/os-specific/linux/nixos-rebuild/default.nix b/pkgs/os-specific/linux/nixos-rebuild/default.nix index b871c63e36d..c6ec0866791 100644 --- a/pkgs/os-specific/linux/nixos-rebuild/default.nix +++ b/pkgs/os-specific/linux/nixos-rebuild/default.nix @@ -3,6 +3,8 @@ , coreutils , gnused , gnugrep +, jq +, util-linux , nix , lib , nixosTests @@ -20,7 +22,7 @@ substituteAll { nix_x86_64_linux = fallback.x86_64-linux; nix_i686_linux = fallback.i686-linux; nix_aarch64_linux = fallback.aarch64-linux; - path = lib.makeBinPath [ coreutils gnused gnugrep ]; + path = lib.makeBinPath [ coreutils gnused gnugrep jq util-linux ]; nativeBuildInputs = [ installShellFiles ]; diff --git a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 index 64bbbee411d..b0ff5b0a672 100644 --- a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 +++ b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.8 @@ -10,7 +10,7 @@ .Sh SYNOPSIS .Nm .Bro -.Cm switch | boot | test | build | dry-build | dry-activate | edit | build-vm | build-vm-with-bootloader +.Cm switch | boot | test | build | dry-build | dry-activate | edit | build-vm | build-vm-with-bootloader | list-generations Op Fl -json .Brc .br .Op Fl -upgrade | -upgrade-all @@ -196,6 +196,14 @@ The boot loader is installed on an automatically generated virtual disk containing a .Pa /boot partition. +. +.It Cm list-generations Op Fl -json +List the available generations in a similar manner to the boot loader +menu. It shows the generation number, build date and time, NixOS version, +kernel version and the configuration revision. This is useful to get +information e.g. for which generation to roll back to with +.Ic nixos-rebuild switch Fl -generation Ar N +There is also a json version of output available. .El . . diff --git a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh index 89871056c48..2f89642845e 100755 --- a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh +++ b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh @@ -36,6 +36,7 @@ verboseScript= noFlake= # comma separated list of vars to preserve when using sudo preservedSudoVars=NIXOS_INSTALL_BOOTLOADER +json= # log the given argument to stderr log() { @@ -48,7 +49,7 @@ while [ "$#" -gt 0 ]; do --help) showSyntax ;; - switch|boot|test|build|edit|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader) + switch|boot|test|build|edit|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader|list-generations) if [ "$i" = dry-run ]; then i=dry-build; fi # exactly one action mandatory, bail out if multiple are given if [ -n "$action" ]; then showSyntax; fi @@ -146,6 +147,9 @@ while [ "$#" -gt 0 ]; do k="$1"; shift 1 lockFlags+=("$i" "$j" "$k") ;; + --json) + json=1 + ;; *) log "$0: unknown option \`$i'" exit 1 @@ -507,6 +511,87 @@ if [ "$action" = dry-build ]; then extraBuildFlags+=(--dry-run) fi +if [ "$action" = list-generations ]; then + if [ ! -L "$profile" ]; then + log "No profile \`$(basename "$profile")' found" + exit 1 + fi + + generation_from_dir() { + generation_dir="$1" + generation_base="$(basename "$generation_dir")" # Has the format "system-123-link" for generation 123 + no_link_gen="${generation_base%-link}" # remove the "-link" + echo "${no_link_gen##*-}" # remove everything before the last dash + } + describe_generation(){ + generation_dir="$1" + generation_number="$(generation_from_dir "$generation_dir")" + nixos_version="$(cat "$generation_dir/nixos-version" 2> /dev/null || echo "Unknown")" + + kernel_dir="$(dirname "$(realpath "$generation_dir/kernel")")" + kernel_version="$(ls "$kernel_dir/lib/modules" || echo "Unknown")" + + configurationRevision="$("$generation_dir/sw/bin/nixos-version" --configuration-revision 2> /dev/null || true)" + + # Old nixos-version output ignored unknown flags and just printed the version + # therefore the following workaround is done not to show the default output + nixos_version_default="$("$generation_dir/sw/bin/nixos-version")" + if [ "$configurationRevision" == "$nixos_version_default" ]; then + configurationRevision="" + fi + + # jq automatically quotes the output => don't try to quote it in output! + build_date="$(stat "$generation_dir" --format=%W | jq 'todate')" + + pushd "$generation_dir/specialisation/" > /dev/null || : + specialisation_list=(*) + popd > /dev/null || : + + specialisations="$(jq --compact-output --null-input '$ARGS.positional' --args -- "${specialisation_list[@]}")" + + if [ "$(basename "$generation_dir")" = "$(readlink "$profile")" ]; then + current_generation_tag="true" + else + current_generation_tag="false" + fi + + # Escape userdefined strings + nixos_version="$(jq -aR <<< "$nixos_version")" + kernel_version="$(jq -aR <<< "$kernel_version")" + configurationRevision="$(jq -aR <<< "$configurationRevision")" + cat << EOF +{ + "generation": $generation_number, + "date": $build_date, + "nixosVersion": $nixos_version, + "kernelVersion": $kernel_version, + "configurationRevision": $configurationRevision, + "specialisations": $specialisations, + "current": $current_generation_tag +} +EOF + } + + find "$(dirname "$profile")" -regex "$profile-[0-9]+-link" | + sort -Vr | + while read -r generation_dir; do + describe_generation "$generation_dir" + done | + if [ -z "$json" ]; then + jq --slurp -r '.[] | [ + ([.generation, (if .current == true then "current" else "" end)] | join(" ")), + (.date | fromdate | strflocaltime("%Y-%m-%d %H:%M:%S")), + .nixosVersion, .kernelVersion, .configurationRevision, + (.specialisations | join(" ")) + ] | @tsv' | + column --separator $'\t' --table --table-columns "Generation,Build-date,NixOS version,Kernel,Configuration Revision,Specialisation" | + ${PAGER:cat} + else + jq --slurp . + fi + exit 0 +fi + # Either upgrade the configuration in the system profile (for "switch" # or "boot"), or just build it and create a symlink "result" in the