summary refs log tree commit diff
path: root/modules/system
diff options
context:
space:
mode:
Diffstat (limited to 'modules/system')
-rw-r--r--modules/system/etc/etc.nix91
-rw-r--r--modules/system/etc/make-etc.nix12
-rw-r--r--modules/system/etc/make-etc.sh22
3 files changed, 125 insertions, 0 deletions
diff --git a/modules/system/etc/etc.nix b/modules/system/etc/etc.nix
new file mode 100644
index 00000000000..c499cc0583a
--- /dev/null
+++ b/modules/system/etc/etc.nix
@@ -0,0 +1,91 @@
+# produce a script to generate /etc
+{config, pkgs, ...}:
+
+###### interface
+let
+  inherit (pkgs.lib) mkOption;
+
+  option = {
+    environment.etc = mkOption {
+      default = [];
+      example = [
+        { source = "/nix/store/.../etc/dir/file.conf.example";
+          target = "dir/file.conf";
+          mode = "0440";
+        }
+      ];
+      description = ''
+        List of files that have to be linked in /etc.
+      '';
+    };
+  };
+in
+
+###### implementation
+let
+
+  copyScript = {source, target, mode ? "644", own ? "root.root"}:
+    assert target != "nixos";
+    ''
+      source="${source}"
+      target="/etc/${target}"
+      mkdir -p $(dirname "$target")
+      test -e "$target" && rm -f "$target"
+      cp "$source" "$target"
+      chown ${own} "$target"
+      chmod ${mode} "$target"
+    '';
+
+  makeEtc = import ./make-etc.nix {
+    inherit (pkgs) stdenv;
+    configFiles = config.environment.etc;
+  };
+  
+in
+
+{
+  require = [option];
+
+  system = {
+    build = {
+      etc = makeEtc;
+    };
+
+    activationScripts = {
+      etc = pkgs.lib.fullDepEntry ''
+        # Set up the statically computed bits of /etc.
+        staticEtc=/etc/static
+        rm -f $staticEtc
+        ln -s ${makeEtc}/etc $staticEtc
+        for i in $(cd $staticEtc && find * -type l); do
+            mkdir -p /etc/$(dirname $i)
+            rm -f /etc/$i
+            if test -e "$staticEtc/$i.mode"; then
+                # Create a regular file in /etc.
+                cp $staticEtc/$i /etc/$i
+                chown 0.0 /etc/$i
+                chmod "$(cat "$staticEtc/$i.mode")" /etc/$i
+            else
+                # Create a symlink in /etc.
+                ln -s $staticEtc/$i /etc/$i
+            fi
+        done
+
+        # Remove dangling symlinks that point to /etc/static.  These are
+        # configuration files that existed in a previous configuration but not
+        # in the current one.  For efficiency, don't look under /etc/nixos
+        # (where all the NixOS sources live).
+        for i in $(find /etc/ \( -path /etc/nixos -prune \) -o -type l); do
+            target=$(readlink "$i")
+            if test "''${target:0:''${#staticEtc}}" = "$staticEtc" -a ! -e "$i"; then
+                rm -f "$i"
+            fi
+        done
+      '' [
+        "systemConfig"
+        "defaultPath" # path to cp, chmod, chown
+        "stdio"
+      ];
+    };
+  };
+}
diff --git a/modules/system/etc/make-etc.nix b/modules/system/etc/make-etc.nix
new file mode 100644
index 00000000000..94ea248f669
--- /dev/null
+++ b/modules/system/etc/make-etc.nix
@@ -0,0 +1,12 @@
+{stdenv, configFiles}:
+
+stdenv.mkDerivation {
+  name = "etc";
+
+  builder = ./make-etc.sh;
+
+  /* !!! Use toXML. */
+  sources = map (x: x.source) configFiles;
+  targets = map (x: x.target) configFiles;
+  modes = map (x: if x ? mode then x.mode else "symlink") configFiles;
+}
diff --git a/modules/system/etc/make-etc.sh b/modules/system/etc/make-etc.sh
new file mode 100644
index 00000000000..4b7bb68be4b
--- /dev/null
+++ b/modules/system/etc/make-etc.sh
@@ -0,0 +1,22 @@
+source $stdenv/setup
+
+ensureDir $out/etc
+
+sources_=($sources)
+targets_=($targets)
+modes_=($modes)
+for ((i = 0; i < ${#targets_[@]}; i++)); do
+    ensureDir $out/etc/$(dirname ${targets_[$i]})
+    if ! test -e $out/etc/${targets_[$i]}; then
+      ln -s ${sources_[$i]} $out/etc/${targets_[$i]};
+    else
+      echo Duplicate entry "${targets_[$i]} -> ${sources_[$i]}"
+      if test "$(readlink "$targets_[$i]")" -ne "$sources_[$i]"; then
+        echo Mismatched duplicate entry "$(readlink "$targets_[$i]") "'<>'" $sources_[$i]"
+	exit 1
+      fi
+    fi;
+    if test "${modes_[$i]}" != symlink; then
+        echo "${modes_[$i]}" > $out/etc/${targets_[$i]}.mode
+    fi
+done