diff --git a/README.md b/README.md index 5ac5b02..5882ee1 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,14 @@ $ nix-shell -p sops --run "sops updatekeys secrets/example.yaml" See [the official sops-nix docs](https://github.com/Mic92/sops-nix/blob/master/README.md) for details. +## Switch-fix + +I've added a tool, [switch-fix](https://blog.femtodata.com/posts/switch-fix/) to the deployment. From the docs: + + "you set-rollback before you do your nixos-rebuild switch." + "you do cancel-rollback if it works" + "you wait if it doesn't, and the system should come back." + ## Successful avenues of exploration ### nixos-anywhere diff --git a/flake.lock b/flake.lock index 9355a40..0171a5e 100644 --- a/flake.lock +++ b/flake.lock @@ -221,16 +221,16 @@ ] }, "locked": { - "lastModified": 1765605144, - "narHash": "sha256-RM2xs+1HdHxesjOelxoA3eSvXShC8pmBvtyTke4Ango=", + "lastModified": 1763992789, + "narHash": "sha256-WHkdBlw6oyxXIra/vQPYLtqY+3G8dUVZM8bEXk0t8x4=", "owner": "nix-community", "repo": "home-manager", - "rev": "90b62096f099b73043a747348c11dbfcfbdea949", + "rev": "44831a7eaba4360fb81f2acc5ea6de5fde90aaa3", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-25.11", + "ref": "release-25.05", "repo": "home-manager", "type": "github" } @@ -309,6 +309,21 @@ "type": "github" } }, + "nixos-facter-modules": { + "locked": { + "lastModified": 1766558141, + "narHash": "sha256-Ud9v49ZPsoDBFuyJSQ2Mpw1ZgAH/aMwUwwzrVoetNus=", + "owner": "numtide", + "repo": "nixos-facter-modules", + "rev": "e796d536e3d83de74267069e179dc620a608ed7d", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nixos-facter-modules", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1756386758, @@ -374,16 +389,16 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1765608474, - "narHash": "sha256-9Wx53UK0z8Di5iesJID0tS1dRKwGxI4i7tsSanOHhF0=", + "lastModified": 1767051569, + "narHash": "sha256-0MnuWoN+n1UYaGBIpqpPs9I9ZHW4kynits4mrnh1Pk4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "28bb483c11a1214a73f9fd2d9928a6e2ea86ec71", + "rev": "40ee5e1944bebdd128f9fbada44faefddfde29bd", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-25.11", + "ref": "nixos-25.05", "repo": "nixpkgs", "type": "github" } @@ -428,16 +443,16 @@ "systems": "systems_5" }, "locked": { - "lastModified": 1765647805, - "narHash": "sha256-CdaiOfpBiS4kw/DR0Ut+02fpFnjM8hNZMZ53a1pavak=", + "lastModified": 1767448045, + "narHash": "sha256-g+LGq2LxOeCgf1M/xbk7gGqpZD3P66Isx2Z13W48npI=", "owner": "nix-community", "repo": "nixvim", - "rev": "f0b0cc7cae2cf5d76608c9164ab8824a2387e146", + "rev": "ce3ce82c09a5d9e552d0ef39ab15b417c2d893cb", "type": "github" }, "original": { "owner": "nix-community", - "ref": "nixos-25.11", + "ref": "nixos-25.05", "repo": "nixvim", "type": "github" } @@ -543,6 +558,7 @@ "fieldseeker-sync": "fieldseeker-sync", "home-manager": "home-manager", "nidus-sync": "nidus-sync", + "nixos-facter-modules": "nixos-facter-modules", "nixpkgs": "nixpkgs_4", "nixvim": "nixvim", "sops-nix": "sops-nix", diff --git a/modules/system/default.nix b/modules/system/default.nix index 92d6889..24fbeee 100644 --- a/modules/system/default.nix +++ b/modules/system/default.nix @@ -25,6 +25,7 @@ ./sillytavern.nix ./static-websites.nix ./sudo.nix + ./switch-fix.nix ./synapse.nix ./tegola.nix ./timecardbot.nix diff --git a/modules/system/switch-fix.nix b/modules/system/switch-fix.nix new file mode 100644 index 0000000..daffb95 --- /dev/null +++ b/modules/system/switch-fix.nix @@ -0,0 +1,85 @@ +{ pkgs, ... }: +let + switch-fix = pkgs.writeShellScriptBin "switch-fix" '' + sudo nix-env --profile /nix/var/nix/profiles/system --set /run/current-system + sudo /run/current-system/bin/switch-to-configuration switch + ''; + boot-fix = pkgs.writeShellScriptBin "boot-fix" '' + sudo nix-env --profile /nix/var/nix/profiles/system --set $1 + sudo $1/bin/switch-to-configuration boot + ''; + rollback-profile-base = "/var/lib/nix-autorollback"; + rollback-profile-path = "${rollback-profile-base}/profile"; + rollback-profile-switch-path = "${rollback-profile-base}/profile-switch"; + rollback-delay = "300"; + + set-rollback = pkgs.writeShellScriptBin "set-rollback" '' + if [ -d ${rollback-profile-switch-path} ]; then + echo "Error: rollback-profile-switch-path at ${rollback-profile-switch-path} exists" + else + sudo ln -sf $(readlink /run/current-system) ${rollback-profile-path} + fi + ''; + + set-rollback-switch = pkgs.writeShellScriptBin "set-rollback-switch" '' + if [ -d ${rollback-profile-path} ]; then + echo "Error: rollback-profile-switch-path at ${rollback-profile-switch-path} exists" + else + sudo ln -sf $(readlink /run/current-system) ${rollback-profile-switch-path} + fi + ''; + + cancel-rollback = pkgs.writeShellScriptBin "cancel-rollback" '' + sudo systemctl stop nix-autorollback.service + if [ -d ${rollback-profile-path} ]; then + sudo rm ${rollback-profile-path} + fi + if [ -d ${rollback-profile-switch-path} ]; then + sudo rm ${rollback-profile-switch-path} + fi + ''; +in +{ + systemd.tmpfiles.rules = [ + "d ${rollback-profile-base} 0755 root root - -" + ]; + + environment.systemPackages = [ + switch-fix + boot-fix + set-rollback + set-rollback-switch + cancel-rollback + ]; + + systemd.services."nix-autorollback" = { + description = "rollback to set profile unless stopped"; + wantedBy = [ "sysinit.target" ]; + script = '' + if [ -d ${rollback-profile-path} ]; then + ${pkgs.util-linux}/bin/wall -t 5 "Autorollback in ${rollback-delay}" + echo "Autorollback in ${rollback-delay}" + ${pkgs.coreutils}/bin/sleep ${rollback-delay} + ${pkgs.util-linux}/bin/wall "Rolling back to $(readlink ${rollback-profile-path})" + echo "Rolling back to $(readlink ${rollback-profile-path})" + ${pkgs.nix}/bin/nix-env --profile /nix/var/nix/profiles/system --set $(readlink ${rollback-profile-path}) + $(readlink ${rollback-profile-path})/bin/switch-to-configuration boot + rm ${rollback-profile-path} + ${pkgs.systemd}/bin/shutdown -r now + elif [ -d ${rollback-profile-switch-path} ]; then + ${pkgs.util-linux}/bin/wall -t 5 "Autorollback (switch) in ${rollback-delay}" + echo "Autorollback in ${rollback-delay}" + ${pkgs.coreutils}/bin/sleep ${rollback-delay} + ${pkgs.util-linux}/bin/wall "Rolling back to $(readlink ${rollback-profile-switch-path})" + echo "Rolling back to $(readlink ${rollback-profile-switch-path})" + ${pkgs.nix}/bin/nix-env --profile /nix/var/nix/profiles/system --set $(readlink ${rollback-profile-switch-path}) + $(readlink ${rollback-profile-switch-path})/bin/switch-to-configuration switch + rm ${rollback-profile-switch-path} + fi + ''; + serviceConfig = { + Type = "simple"; + User = "root"; + }; + }; +}