diff --git a/nixos/modules/system/activation/activatable-system.nix b/nixos/modules/system/activation/activatable-system.nix index bb207ec0c18f..c3739f627a16 100644 --- a/nixos/modules/system/activation/activatable-system.nix +++ b/nixos/modules/system/activation/activatable-system.nix @@ -11,12 +11,6 @@ let mkOption types ; - - systemBuilderArgs = { - activationScript = config.system.activationScripts.script; - dryActivationScript = config.system.dryActivationScript; - }; - in { options = { @@ -52,36 +46,51 @@ in ''; }; }; - config = { - system.activatableSystemBuilderCommands = '' - echo "$activationScript" > $out/activate - echo "$dryActivationScript" > $out/dry-activate - substituteInPlace $out/activate --subst-var-by out ''${!toplevelVar} - substituteInPlace $out/dry-activate --subst-var-by out ''${!toplevelVar} - chmod u+x $out/activate $out/dry-activate - unset activationScript dryActivationScript - ''; + config = + let + activationScript = lib.getExe ( + pkgs.writeShellApplication { + name = "activate"; + text = config.system.activationScripts.script; + checkPhase = ""; + bashOptions = [ ]; + } + ); + dryActivationScript = lib.getExe ( + pkgs.writeShellApplication { + name = "dry-activate"; + text = config.system.dryActivationScript; + checkPhase = ""; + bashOptions = [ ]; + } + ); + in + { + system.activatableSystemBuilderCommands = + # We use sed here instead of substitute(InPlace), because the substitute + # functions load the content of the file into a bash variable, which fails + # for very large activation scripts. + # bash + '' + cp ${activationScript} $out/activate + cp ${dryActivationScript} $out/dry-activate + ${lib.getExe pkgs.gnused} --in-place --expression "s|@out@|''${!toplevelVar}|g" $out/activate $out/dry-activate + ''; - system.systemBuilderCommands = lib.mkIf config.system.activatable config.system.activatableSystemBuilderCommands; - system.systemBuilderArgs = lib.mkIf config.system.activatable ( - systemBuilderArgs - // { + system.systemBuilderCommands = lib.mkIf config.system.activatable config.system.activatableSystemBuilderCommands; + system.systemBuilderArgs = lib.mkIf config.system.activatable { toplevelVar = "out"; - } - ); + }; - system.build.separateActivationScript = - pkgs.runCommand "separate-activation-script" - ( - systemBuilderArgs - // { + system.build.separateActivationScript = + pkgs.runCommand "separate-activation-script" + { toplevelVar = "toplevel"; toplevel = config.system.build.toplevel; } - ) - '' - mkdir $out - ${config.system.activatableSystemBuilderCommands} - ''; - }; + '' + mkdir $out + ${config.system.activatableSystemBuilderCommands} + ''; + }; } diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index 08ab396e1de2..8fd274276a61 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -50,8 +50,6 @@ let ) withHeadlines; in '' - #!${pkgs.runtimeShell} - source ${./lib/lib.sh} systemConfig='@out@' diff --git a/nixos/tests/restart-by-activation-script.nix b/nixos/tests/restart-by-activation-script.nix index 6d26d9843aff..2fad1f21584e 100644 --- a/nixos/tests/restart-by-activation-script.nix +++ b/nixos/tests/restart-by-activation-script.nix @@ -6,7 +6,7 @@ }; nodes.machine = - { pkgs, ... }: + { pkgs, lib, ... }: { imports = [ ../modules/profiles/minimal.nix ]; @@ -46,6 +46,14 @@ fi ''; }; + + # Make sure we don't crash on long activation scripts + specialisation.longscript.configuration = { + system.activationScripts.long = { + supportsDryActivation = true; + text = lib.concatStringsSep "\n" (lib.genList (i: ''# line number ${toString i}'') 1000000); + }; + }; }; testScript = # python