diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index a73070ab332f..17b24e1678be 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -155,6 +155,23 @@ mkdir -m 0755 -p /var/setuid-wrappers
mount -t tmpfs -o "mode=0755" tmpfs /var/setuid-wrappers
+# Optionally log the script output to /dev/kmsg or /run/log/stage-2-init.log.
+# Only at this point are all the necessary prerequisites ready for these commands.
+if test -n "@logCommands@"; then
+ exec {logOutFd}>&1 {logErrFd}>&2
+ if test -w /dev/kmsg; then
+ exec > >(tee -i /proc/self/fd/"$logOutFd" | while read line; do
+ if test -n "$line"; then
+ echo "stage-2-init: $line" > /dev/kmsg
+ fi
+ done) 2>&1
+ else
+ mkdir -p /run/log
+ exec > >(tee -i /run/log/stage-2-init.log) 2>&1
+ fi
+fi
+
+
# Run the script that performs all configuration activation that does
# not have to be done at boot time.
echo "running activation script..."
@@ -182,6 +199,13 @@ ln -sfn /run/booted-system /nix/var/nix/gcroots/booted-system
@shell@ @postBootCommands@
+# Reset the logging file descriptors
+if test -n "@logCommands@"; then
+ exec 1>&$logOutFd 2>&$logErrFd
+ exec {logOutFd}>&- {logErrFd}>&-
+fi
+
+
# Start systemd.
echo "starting systemd..."
PATH=/run/current-system/systemd/lib/systemd \
diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix
index c0ef4e02d1ff..32281e63af24 100644
--- a/nixos/modules/system/boot/stage-2.nix
+++ b/nixos/modules/system/boot/stage-2.nix
@@ -17,7 +17,7 @@ let
src = ./stage-2-init.sh;
shellDebug = "${pkgs.bashInteractive}/bin/bash";
isExecutable = true;
- inherit (config.boot) devShmSize runSize;
+ inherit (config.boot) logCommands devShmSize runSize;
inherit (config.nix) readOnlyStore;
inherit (config.networking) useHostResolvConf;
ttyGid = config.ids.gids.tty;
@@ -40,6 +40,14 @@ in
boot = {
+ logCommands = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Whether to replicate command output of stage-1 booting to /dev/kmsg or /run/log/stage-2-init.log if /dev/kmsg is not writable.
+ '';
+ };
+
postBootCommands = mkOption {
default = "";
example = "rm -f /var/log/messages";