diff options
Diffstat (limited to 'modules/system')
-rw-r--r-- | modules/system/etc/etc.nix | 91 | ||||
-rw-r--r-- | modules/system/etc/make-etc.nix | 12 | ||||
-rw-r--r-- | modules/system/etc/make-etc.sh | 22 |
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 |