1# Management of static files in /etc.
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8
9 etc' = filter (f: f.enable) (attrValues config.environment.etc);
10
11 etc = pkgs.stdenvNoCC.mkDerivation {
12 name = "etc";
13
14 builder = ./make-etc.sh;
15
16 preferLocalBuild = true;
17 allowSubstitutes = false;
18
19 /* !!! Use toXML. */
20 sources = map (x: x.source) etc';
21 targets = map (x: x.target) etc';
22 modes = map (x: x.mode) etc';
23 users = map (x: x.user) etc';
24 groups = map (x: x.group) etc';
25 };
26
27in
28
29{
30
31 ###### interface
32
33 options = {
34
35 environment.etc = mkOption {
36 default = {};
37 example = literalExample ''
38 { example-configuration-file =
39 { source = "/nix/store/.../etc/dir/file.conf.example";
40 mode = "0440";
41 };
42 "default/useradd".text = "GROUP=100 ...";
43 }
44 '';
45 description = ''
46 Set of files that have to be linked in <filename>/etc</filename>.
47 '';
48
49 type = with types; loaOf (submodule (
50 { name, config, ... }:
51 { options = {
52
53 enable = mkOption {
54 type = types.bool;
55 default = true;
56 description = ''
57 Whether this /etc file should be generated. This
58 option allows specific /etc files to be disabled.
59 '';
60 };
61
62 target = mkOption {
63 type = types.str;
64 description = ''
65 Name of symlink (relative to
66 <filename>/etc</filename>). Defaults to the attribute
67 name.
68 '';
69 };
70
71 text = mkOption {
72 default = null;
73 type = types.nullOr types.lines;
74 description = "Text of the file.";
75 };
76
77 source = mkOption {
78 type = types.path;
79 description = "Path of the source file.";
80 };
81
82 mode = mkOption {
83 type = types.str;
84 default = "symlink";
85 example = "0600";
86 description = ''
87 If set to something else than <literal>symlink</literal>,
88 the file is copied instead of symlinked, with the given
89 file mode.
90 '';
91 };
92
93 uid = mkOption {
94 default = 0;
95 type = types.int;
96 description = ''
97 UID of created file. Only takes affect when the file is
98 copied (that is, the mode is not 'symlink').
99 '';
100 };
101
102 gid = mkOption {
103 default = 0;
104 type = types.int;
105 description = ''
106 GID of created file. Only takes affect when the file is
107 copied (that is, the mode is not 'symlink').
108 '';
109 };
110
111 user = mkOption {
112 default = "+${toString config.uid}";
113 type = types.str;
114 description = ''
115 User name of created file.
116 Only takes affect when the file is copied (that is, the mode is not 'symlink').
117 Changing this option takes precedence over <literal>uid</literal>.
118 '';
119 };
120
121 group = mkOption {
122 default = "+${toString config.gid}";
123 type = types.str;
124 description = ''
125 Group name of created file.
126 Only takes affect when the file is copied (that is, the mode is not 'symlink').
127 Changing this option takes precedence over <literal>gid</literal>.
128 '';
129 };
130
131 };
132
133 config = {
134 target = mkDefault name;
135 source = mkIf (config.text != null) (
136 let name' = "etc-" + baseNameOf name;
137 in mkDefault (pkgs.writeText name' config.text));
138 };
139
140 }));
141
142 };
143
144 };
145
146
147 ###### implementation
148
149 config = {
150
151 system.build.etc = etc;
152
153 system.activationScripts.etc = stringAfter [ "users" "groups" ]
154 ''
155 # Set up the statically computed bits of /etc.
156 echo "setting up /etc..."
157 ${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl ${./setup-etc.pl} ${etc}/etc
158 '';
159
160 };
161
162}