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 ${v.text}
12 '';
13 });
14
15 path =
16 [ pkgs.coreutils pkgs.gnugrep pkgs.findutils
17 pkgs.glibc # needed for getent
18 pkgs.shadow
19 pkgs.nettools # needed for hostname
20 ];
21
22in
23
24{
25
26 ###### interface
27
28 options = {
29
30 system.activationScripts = mkOption {
31 default = {};
32
33 example = {
34 stdio = {
35 text = ''
36 # Needed by some programs.
37 ln -sfn /proc/self/fd /dev/fd
38 ln -sfn /proc/self/fd/0 /dev/stdin
39 ln -sfn /proc/self/fd/1 /dev/stdout
40 ln -sfn /proc/self/fd/2 /dev/stderr
41 '';
42 deps = [];
43 };
44 };
45
46 description = ''
47 A set of shell script fragments that are executed when a NixOS
48 system configuration is activated. Examples are updating
49 /etc, creating accounts, and so on. Since these are executed
50 every time you boot the system or run
51 <command>nixos-rebuild</command>, it's important that they are
52 idempotent and fast.
53 '';
54
55 type = types.attrsOf types.unspecified; # FIXME
56
57 apply = set: {
58 script =
59 ''
60 #! ${pkgs.stdenv.shell}
61
62 systemConfig=@out@
63
64 export PATH=/empty
65 for i in ${toString path}; do
66 PATH=$PATH:$i/bin:$i/sbin
67 done
68
69 _status=0
70 trap "_status=1" ERR
71
72 # Ensure a consistent umask.
73 umask 0022
74
75 ${
76 let
77 set' = mapAttrs (n: v: if isString v then noDepEntry v else v) set;
78 withHeadlines = addAttributeName set';
79 in textClosureMap id (withHeadlines) (attrNames withHeadlines)
80 }
81
82 # Make this configuration the current configuration.
83 # The readlink is there to ensure that when $systemConfig = /system
84 # (which is a symlink to the store), /run/current-system is still
85 # used as a garbage collection root.
86 ln -sfn "$(readlink -f "$systemConfig")" /run/current-system
87
88 # Prevent the current configuration from being garbage-collected.
89 ln -sfn /run/current-system /nix/var/nix/gcroots/current-system
90
91 exit $_status
92 '';
93 };
94
95 };
96
97 };
98
99
100 ###### implementation
101
102 config = {
103
104 system.activationScripts.stdio =
105 ''
106 # Needed by some programs.
107 ln -sfn /proc/self/fd /dev/fd
108 ln -sfn /proc/self/fd/0 /dev/stdin
109 ln -sfn /proc/self/fd/1 /dev/stdout
110 ln -sfn /proc/self/fd/2 /dev/stderr
111 '';
112
113 system.activationScripts.var =
114 ''
115 # Various log/runtime directories.
116
117 mkdir -m 0755 -p /run/nix/current-load # for distributed builds
118 mkdir -m 0700 -p /run/nix/remote-stores
119
120 mkdir -m 0755 -p /var/log
121
122 touch /var/log/wtmp /var/log/lastlog # must exist
123 chmod 644 /var/log/wtmp /var/log/lastlog
124
125 mkdir -m 1777 -p /var/tmp
126
127 # Empty, read-only home directory of many system accounts.
128 mkdir -m 0555 -p /var/empty
129 '';
130
131 system.activationScripts.usrbinenv =
132 ''
133 mkdir -m 0755 -p /usr/bin
134 ln -sfn ${pkgs.coreutils}/bin/env /usr/bin/.env.tmp
135 mv /usr/bin/.env.tmp /usr/bin/env # atomically replace /usr/bin/env
136 '';
137
138 system.activationScripts.tmpfs =
139 ''
140 ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.devSize}" none /dev
141 ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.devShmSize}" none /dev/shm
142 ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.runSize}" none /run
143 '';
144
145 };
146
147}