diff --git a/modules/system/activation/activation-script.nix b/modules/system/activation/activation-script.nix index 8e9029d09436..4cf6548ed293 100644 --- a/modules/system/activation/activation-script.nix +++ b/modules/system/activation/activation-script.nix @@ -2,9 +2,9 @@ {pkgs, config, ...}: let - inherit (pkgs.stringsWithDeps) textClosureMap noDepEntry; inherit (pkgs.lib) mkOption mergeTypedOption mergeAttrs mapRecordFlatten - mapAttrs addErrorContext fold id filter; + mapAttrs addErrorContext fold id filter textClosureMap noDepEntry + fullDepEntry; inherit (builtins) attrNames; addAttributeName = mapAttrs (a: v: v // { @@ -14,40 +14,205 @@ let ${v.text} ''; }); + + defaultScripts = { + + systemConfig = noDepEntry '' + systemConfig="$1" + if test -z "$systemConfig"; then + systemConfig="/system" # for the installation CD + fi + ''; + + defaultPath = + let path = [ + pkgs.coreutils pkgs.gnugrep pkgs.findutils + pkgs.glibc # needed for getent + pkgs.pwdutils + pkgs.nettools # needed for hostname + ]; in noDepEntry '' + export PATH=/empty + for i in ${toString path}; do + PATH=$PATH:$i/bin:$i/sbin; + done + ''; + + stdio = fullDepEntry '' + # Needed by some programs. + ln -sfn /proc/self/fd /dev/fd + ln -sfn /proc/self/fd/0 /dev/stdin + ln -sfn /proc/self/fd/1 /dev/stdout + ln -sfn /proc/self/fd/2 /dev/stderr + '' [ + "defaultPath" # path to ln + ]; + + binsh = fullDepEntry '' + # Create the required /bin/sh symlink; otherwise lots of things + # (notably the system() function) won't work. + mkdir -m 0755 -p $mountPoint/bin + ln -sfn ${config.system.build.binsh}/bin/sh $mountPoint/bin/sh + '' [ + "defaultPath" # path to ln & mkdir + "stdio" # ? + ]; + + modprobe = fullDepEntry '' + # Allow the kernel to find our wrapped modprobe (which searches in the + # right location in the Nix store for kernel modules). We need this + # when the kernel (or some module) auto-loads a module. + # !!! maybe this should only happen at boot time, since we shouldn't + # use modules that don't match the running kernel. + echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe + '' [ + # ? + ]; + + var = fullDepEntry '' + # Various log/runtime directories. + mkdir -m 0755 -p /var/run + mkdir -m 0755 -p /var/run/console # for pam_console + + touch /var/run/utmp # must exist + chmod 644 /var/run/utmp + + mkdir -m 0755 -p /var/run/nix/current-load # for distributed builds + mkdir -m 0700 -p /var/run/nix/remote-stores + + mkdir -m 0755 -p /var/log + + touch /var/log/wtmp # must exist + chmod 644 /var/log/wtmp + + touch /var/log/lastlog + chmod 644 /var/log/lastlog + + mkdir -m 1777 -p /var/tmp + + + # Empty, read-only home directory of many system accounts. + mkdir -m 0555 -p /var/empty + '' [ + "defaultPath" # path to mkdir & touch & chmod + ]; + + rootPasswd = fullDepEntry '' + # If there is no password file yet, create a root account with an + # empty password. + if ! test -e /etc/passwd; then + rootHome=/root + touch /etc/passwd; chmod 0644 /etc/passwd + touch /etc/group; chmod 0644 /etc/group + touch /etc/shadow; chmod 0600 /etc/shadow + # Can't use useradd, since it complains that it doesn't know us + # (bootstrap problem!). + echo "root:x:0:0:System administrator:$rootHome:${config.system.shell}" >> /etc/passwd + echo "root::::::::" >> /etc/shadow + echo | passwd --stdin root + fi + '' [ + "defaultPath" # path to touch & passwd + "etc" # for /etc + # ? + ]; + + nix = fullDepEntry '' + # Set up Nix. + mkdir -p /nix/etc/nix + ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf + chown root.nixbld /nix/store + chmod 1775 /nix/store + + # Nix initialisation. + mkdir -m 0755 -p \ + /nix/var/nix/gcroots \ + /nix/var/nix/temproots \ + /nix/var/nix/manifests \ + /nix/var/nix/userpool \ + /nix/var/nix/profiles \ + /nix/var/nix/db \ + /nix/var/log/nix/drvs \ + /nix/var/nix/channel-cache \ + /nix/var/nix/chroots + mkdir -m 1777 -p /nix/var/nix/gcroots/per-user + mkdir -m 1777 -p /nix/var/nix/profiles/per-user + + ln -sf /nix/var/nix/profiles /nix/var/nix/gcroots/ + ln -sf /nix/var/nix/manifests /nix/var/nix/gcroots/ + '' [ + "defaultPath" + "etc" # /etc/nix.conf + "users" # nixbld group + ]; + + hostname = fullDepEntry '' + # Set the host name. Don't clear it if it's not configured in the + # NixOS configuration, since it may have been set by dhclient in the + # meantime. + ${if config.networking.hostName != "" then + ''hostname "${config.networking.hostName}"'' + else '' + # dhclient won't do anything if the hostname isn't empty. + if test "$(hostname)" = "(none)"; then + hostname "" + fi + ''} + '' [ "defaultPath" ]; + + # The activation has to be done at the end. This is forced at the apply + # function of activationScripts option + activate = noDepEntry '' + # Make this configuration the current configuration. + # The readlink is there to ensure that when $systemConfig = /system + # (which is a symlink to the store), /var/run/current-system is still + # used as a garbage collection root. + ln -sfn "$(readlink -f "$systemConfig")" /var/run/current-system + + # Prevent the current configuration from being garbage-collected. + ln -sfn /var/run/current-system /nix/var/nix/gcroots/current-system + ''; + + }; + + in { - system = { - activationScripts = mkOption { - default = []; - example = { - stdio = { - text = " - # Needed by some programs. - ln -sfn /proc/self/fd /dev/fd - ln -sfn /proc/self/fd/0 /dev/stdin - ln -sfn /proc/self/fd/1 /dev/stdout - ln -sfn /proc/self/fd/2 /dev/stderr - "; - deps = []; + require = { + system = { + activationScripts = mkOption { + default = []; + example = { + stdio = { + text = " + # Needed by some programs. + ln -sfn /proc/self/fd /dev/fd + ln -sfn /proc/self/fd/0 /dev/stdin + ln -sfn /proc/self/fd/1 /dev/stdout + ln -sfn /proc/self/fd/2 /dev/stderr + "; + deps = []; + }; + }; + description = '' + Activate the new configuration (i.e., update /etc, make accounts, + and so on). + ''; + merge = mergeTypedOption "script" builtins.isAttrs (fold mergeAttrs {}); + apply = set: + let withHeadlines = addAttributeName set; + activateLib = removeAttrs withHeadlines ["activate"]; + activateLibNames = attrNames activateLib; + in { + script = pkgs.writeScript "nixos-activation-script" + ("#!/bin/sh\n" + + textClosureMap id activateLib activateLibNames + "\n" + # make sure that the activate snippet is added last. + + withHeadlines.activate.text); }; - }; - description = '' - Activate the new configuration (i.e., update /etc, make accounts, - and so on). - ''; - merge = mergeTypedOption "script" builtins.isAttrs (fold mergeAttrs {}); - apply = set: - let withHeadlines = addAttributeName set; - activateLib = removeAttrs withHeadlines ["activate"]; - activateLibNames = attrNames activateLib; - in { - script = pkgs.writeScript "nixos-activation-script" - ("#!/bin/sh\n" - + textClosureMap id activateLib activateLibNames + "\n" - # make sure that the activate snippet is added last. - + withHeadlines.activate.text); }; }; }; + + system.activationScripts = defaultScripts; } diff --git a/system/system-options.nix b/system/system-options.nix index 38dfce264f0d..01bff26b87c3 100644 --- a/system/system-options.nix +++ b/system/system-options.nix @@ -44,162 +44,5 @@ in build = { binsh = pkgs.bashInteractive; }; - - activationScripts = { - systemConfig = noDepEntry '' - systemConfig="$1" - if test -z "$systemConfig"; then - systemConfig="/system" # for the installation CD - fi - ''; - - defaultPath = - let path = [ - pkgs.coreutils pkgs.gnugrep pkgs.findutils - pkgs.glibc # needed for getent - pkgs.pwdutils - pkgs.nettools # needed for hostname - ]; in noDepEntry '' - export PATH=/empty - for i in ${toString path}; do - PATH=$PATH:$i/bin:$i/sbin; - done - ''; - - stdio = fullDepEntry '' - # Needed by some programs. - ln -sfn /proc/self/fd /dev/fd - ln -sfn /proc/self/fd/0 /dev/stdin - ln -sfn /proc/self/fd/1 /dev/stdout - ln -sfn /proc/self/fd/2 /dev/stderr - '' [ - "defaultPath" # path to ln - ]; - - binsh = fullDepEntry '' - # Create the required /bin/sh symlink; otherwise lots of things - # (notably the system() function) won't work. - mkdir -m 0755 -p $mountPoint/bin - ln -sfn ${config.system.build.binsh}/bin/sh $mountPoint/bin/sh - '' [ - "defaultPath" # path to ln & mkdir - "stdio" # ? - ]; - - modprobe = fullDepEntry '' - # Allow the kernel to find our wrapped modprobe (which searches in the - # right location in the Nix store for kernel modules). We need this - # when the kernel (or some module) auto-loads a module. - # !!! maybe this should only happen at boot time, since we shouldn't - # use modules that don't match the running kernel. - echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe - '' [ - # ? - ]; - - var = fullDepEntry '' - # Various log/runtime directories. - mkdir -m 0755 -p /var/run - mkdir -m 0755 -p /var/run/console # for pam_console - - touch /var/run/utmp # must exist - chmod 644 /var/run/utmp - - mkdir -m 0755 -p /var/run/nix/current-load # for distributed builds - mkdir -m 0700 -p /var/run/nix/remote-stores - - mkdir -m 0755 -p /var/log - - touch /var/log/wtmp # must exist - chmod 644 /var/log/wtmp - - touch /var/log/lastlog - chmod 644 /var/log/lastlog - - mkdir -m 1777 -p /var/tmp - - - # Empty, read-only home directory of many system accounts. - mkdir -m 0555 -p /var/empty - '' [ - "defaultPath" # path to mkdir & touch & chmod - ]; - - rootPasswd = fullDepEntry '' - # If there is no password file yet, create a root account with an - # empty password. - if ! test -e /etc/passwd; then - rootHome=/root - touch /etc/passwd; chmod 0644 /etc/passwd - touch /etc/group; chmod 0644 /etc/group - touch /etc/shadow; chmod 0600 /etc/shadow - # Can't use useradd, since it complains that it doesn't know us - # (bootstrap problem!). - echo "root:x:0:0:System administrator:$rootHome:${config.system.shell}" >> /etc/passwd - echo "root::::::::" >> /etc/shadow - echo | passwd --stdin root - fi - '' [ - "defaultPath" # path to touch & passwd - "etc" # for /etc - # ? - ]; - - nix = fullDepEntry '' - # Set up Nix. - mkdir -p /nix/etc/nix - ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf - chown root.nixbld /nix/store - chmod 1775 /nix/store - - # Nix initialisation. - mkdir -m 0755 -p \ - /nix/var/nix/gcroots \ - /nix/var/nix/temproots \ - /nix/var/nix/manifests \ - /nix/var/nix/userpool \ - /nix/var/nix/profiles \ - /nix/var/nix/db \ - /nix/var/log/nix/drvs \ - /nix/var/nix/channel-cache \ - /nix/var/nix/chroots - mkdir -m 1777 -p /nix/var/nix/gcroots/per-user - mkdir -m 1777 -p /nix/var/nix/profiles/per-user - - ln -sf /nix/var/nix/profiles /nix/var/nix/gcroots/ - ln -sf /nix/var/nix/manifests /nix/var/nix/gcroots/ - '' [ - "defaultPath" - "etc" # /etc/nix.conf - "users" # nixbld group - ]; - - hostname = fullDepEntry '' - # Set the host name. Don't clear it if it's not configured in the - # NixOS configuration, since it may have been set by dhclient in the - # meantime. - ${if config.networking.hostName != "" then - ''hostname "${config.networking.hostName}"'' - else '' - # dhclient won't do anything if the hostname isn't empty. - if test "$(hostname)" = "(none)"; then - hostname "" - fi - ''} - '' [ "defaultPath" ]; - - # The activation has to be done at the end. This is forced at the apply - # function of activationScripts option - activate = noDepEntry '' - # Make this configuration the current configuration. - # The readlink is there to ensure that when $systemConfig = /system - # (which is a symlink to the store), /var/run/current-system is still - # used as a garbage collection root. - ln -sfn "$(readlink -f "$systemConfig")" /var/run/current-system - - # Prevent the current configuration from being garbage-collected. - ln -sfn /var/run/current-system /nix/var/nix/gcroots/current-system - ''; - }; }; }