at 18.09-beta 4.9 kB view raw
1# generate the script used to activate the configuration. 2{ config, lib, pkgs, ... }: 3 4with lib; 5 6let 7 8 addAttributeName = mapAttrs (a: v: v // { 9 text = '' 10 #### Activation script snippet ${a}: 11 _localstatus=0 12 ${v.text} 13 14 if (( _localstatus > 0 )); then 15 printf "Activation script snippet '%s' failed (%s)\n" "${a}" "$_localstatus" 16 fi 17 ''; 18 }); 19 20 path = with pkgs; map getBin 21 [ coreutils 22 gnugrep 23 findutils 24 glibc # needed for getent 25 shadow 26 nettools # needed for hostname 27 utillinux # needed for mount and mountpoint 28 ]; 29 30in 31 32{ 33 34 ###### interface 35 36 options = { 37 38 system.activationScripts = mkOption { 39 default = {}; 40 41 example = literalExample '' 42 { stdio = { 43 text = ''' 44 # Needed by some programs. 45 ln -sfn /proc/self/fd /dev/fd 46 ln -sfn /proc/self/fd/0 /dev/stdin 47 ln -sfn /proc/self/fd/1 /dev/stdout 48 ln -sfn /proc/self/fd/2 /dev/stderr 49 '''; 50 deps = []; 51 }; 52 } 53 ''; 54 55 description = '' 56 A set of shell script fragments that are executed when a NixOS 57 system configuration is activated. Examples are updating 58 /etc, creating accounts, and so on. Since these are executed 59 every time you boot the system or run 60 <command>nixos-rebuild</command>, it's important that they are 61 idempotent and fast. 62 ''; 63 64 type = types.attrsOf types.unspecified; # FIXME 65 66 apply = set: { 67 script = 68 '' 69 #! ${pkgs.runtimeShell} 70 71 systemConfig=@out@ 72 73 export PATH=/empty 74 for i in ${toString path}; do 75 PATH=$PATH:$i/bin:$i/sbin 76 done 77 78 _status=0 79 trap "_status=1 _localstatus=\$?" ERR 80 81 # Ensure a consistent umask. 82 umask 0022 83 84 ${ 85 let 86 set' = mapAttrs (n: v: if isString v then noDepEntry v else v) set; 87 withHeadlines = addAttributeName set'; 88 in textClosureMap id (withHeadlines) (attrNames withHeadlines) 89 } 90 91 # Make this configuration the current configuration. 92 # The readlink is there to ensure that when $systemConfig = /system 93 # (which is a symlink to the store), /run/current-system is still 94 # used as a garbage collection root. 95 ln -sfn "$(readlink -f "$systemConfig")" /run/current-system 96 97 # Prevent the current configuration from being garbage-collected. 98 ln -sfn /run/current-system /nix/var/nix/gcroots/current-system 99 100 exit $_status 101 ''; 102 }; 103 104 }; 105 106 environment.usrbinenv = mkOption { 107 default = "${pkgs.coreutils}/bin/env"; 108 example = literalExample '' 109 "''${pkgs.busybox}/bin/env" 110 ''; 111 type = types.nullOr types.path; 112 visible = false; 113 description = '' 114 The env(1) executable that is linked system-wide to 115 <literal>/usr/bin/env</literal>. 116 ''; 117 }; 118 }; 119 120 121 ###### implementation 122 123 config = { 124 125 system.activationScripts.stdio = ""; # obsolete 126 127 system.activationScripts.var = 128 '' 129 # Various log/runtime directories. 130 131 mkdir -m 0755 -p /run/nix/current-load # for distributed builds 132 mkdir -m 0700 -p /run/nix/remote-stores 133 134 mkdir -m 0755 -p /var/log 135 136 touch /var/log/wtmp /var/log/lastlog # must exist 137 chmod 644 /var/log/wtmp /var/log/lastlog 138 139 mkdir -m 1777 -p /var/tmp 140 141 # Empty, immutable home directory of many system accounts. 142 mkdir -p /var/empty 143 # Make sure it's really empty 144 ${pkgs.e2fsprogs}/bin/chattr -f -i /var/empty || true 145 find /var/empty -mindepth 1 -delete 146 chmod 0555 /var/empty 147 chown root:root /var/empty 148 ${pkgs.e2fsprogs}/bin/chattr -f +i /var/empty || true 149 ''; 150 151 system.activationScripts.usrbinenv = if config.environment.usrbinenv != null 152 then '' 153 mkdir -m 0755 -p /usr/bin 154 ln -sfn ${config.environment.usrbinenv} /usr/bin/.env.tmp 155 mv /usr/bin/.env.tmp /usr/bin/env # atomically replace /usr/bin/env 156 '' 157 else '' 158 rm -f /usr/bin/env 159 rmdir --ignore-fail-on-non-empty /usr/bin /usr 160 ''; 161 162 system.activationScripts.specialfs = 163 '' 164 specialMount() { 165 local device="$1" 166 local mountPoint="$2" 167 local options="$3" 168 local fsType="$4" 169 170 if mountpoint -q "$mountPoint"; then 171 local options="remount,$options" 172 else 173 mkdir -m 0755 -p "$mountPoint" 174 fi 175 mount -t "$fsType" -o "$options" "$device" "$mountPoint" 176 } 177 source ${config.system.build.earlyMountScript} 178 ''; 179 180 }; 181 182}