summaryrefslogtreecommitdiff
path: root/modules/system
diff options
context:
space:
mode:
authorDaiderd Jordan <daiderd@gmail.com>2016-11-05 22:47:09 +0100
committerDaiderd Jordan <daiderd@gmail.com>2016-11-05 22:47:09 +0100
commitcd49cc1ab3cfad373ef2b5c57b99b1cfb5761828 (patch)
tree08cd7640a66bcfa03cc25a58a3b9e6c89b48f20b /modules/system
parent380bdd293bbcd10ffa8f632572ec34e6f1314cfb (diff)
generalized module for write-text
- use custom etc activation script
Diffstat (limited to 'modules/system')
-rw-r--r--modules/system/activation-scripts.nix63
-rw-r--r--modules/system/etc.nix63
-rw-r--r--modules/system/write-text.nix56
3 files changed, 182 insertions, 0 deletions
diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix
new file mode 100644
index 0000000..1efe201
--- /dev/null
+++ b/modules/system/activation-scripts.nix
@@ -0,0 +1,63 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.system;
+
+ script = import ./write-text.nix {
+ inherit lib;
+ mkTextDerivation = name: text: pkgs.writeScript "activate-${name}" text;
+ };
+
+in
+
+{
+ options = {
+
+ system.activationScripts = mkOption {
+ internal = true;
+ type = types.attrsOf (types.submodule script);
+ default = {};
+ description = ''
+ A set of shell script fragments that are executed when a NixOS
+ system configuration is activated. Examples are updating
+ /etc, creating accounts, and so on. Since these are executed
+ every time you boot the system or run
+ <command>nixos-rebuild</command>, it's important that they are
+ idempotent and fast.
+ '';
+ };
+
+ };
+
+ config = {
+
+ system.activationScripts.script.text = ''
+ #! ${pkgs.stdenv.shell}
+
+ systemConfig=@out@
+
+ _status=0
+ trap "_status=1" ERR
+
+ # Ensure a consistent umask.
+ umask 0022
+
+ # Make this configuration the current configuration.
+ # The readlink is there to ensure that when $systemConfig = /system
+ # (which is a symlink to the store), /run/current-system is still
+ # used as a garbage collection root.
+ ln -sfn "$(readlink -f "$systemConfig")" /run/current-system
+
+ # Prevent the current configuration from being garbage-collected.
+ ln -sfn /run/current-system /nix/var/nix/gcroots/current-system
+
+ ${cfg.activationScripts.etc.text}
+
+ exit $_status
+ '';
+
+ };
+}
diff --git a/modules/system/etc.nix b/modules/system/etc.nix
new file mode 100644
index 0000000..9999c1e
--- /dev/null
+++ b/modules/system/etc.nix
@@ -0,0 +1,63 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ text = import ./write-text.nix {
+ inherit lib;
+ mkTextDerivation = name: text: pkgs.writeText "etc-${name}" text;
+ };
+
+ etc = filter (f: f.enable) (attrValues config.environment.etc);
+
+in
+
+{
+ options = {
+
+ environment.etc = mkOption {
+ type = types.loaOf (types.submodule text);
+ default = {};
+ description = ''
+ Set of files that have to be linked in <filename>/etc</filename>.
+ '';
+ };
+
+ };
+
+ config = {
+
+ system.build.etc = pkgs.runCommand "etc" {} ''
+ mkdir -p $out/etc
+ cd $out/etc
+ ${concatMapStringsSep "\n" (attr: "ln -s '${attr.source}' '${attr.target}'") etc}
+ '';
+
+ system.activationScripts.etc.text = ''
+ # Set up the statically computed bits of /etc.
+ echo "setting up /etc..."
+
+ ln -sfn "$(readlink -f $systemConfig/etc)" /etc/static
+
+ for link in $(ls /etc/static/); do
+ if [ -e "/etc/$link" ]; then
+ if [ ! -L "/etc/$link" ]; then
+ echo "warning: /etc/$link is a file, skipping..." >&2
+ fi
+ else
+ ln -sfn "/etc/static/$link" "/etc/$link"
+ fi
+ done
+
+ for link in $(find /etc/ -maxdepth 1 -type l); do
+ if [[ "$(readlink $link)" == /etc/static/* ]]; then
+ if [ ! -e "$(readlink -f $link)" ]; then
+ rm $link
+ fi
+ fi
+ done
+ '';
+
+ };
+}
diff --git a/modules/system/write-text.nix b/modules/system/write-text.nix
new file mode 100644
index 0000000..f15fedd
--- /dev/null
+++ b/modules/system/write-text.nix
@@ -0,0 +1,56 @@
+{ lib, mkTextDerivation }:
+
+with lib;
+
+{ config, name, ... }:
+let
+
+ sourceDrv = mkTextDerivation name config.text;
+
+in
+
+{
+ options = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether this /etc file should be generated. This
+ option allows specific /etc files to be disabled.
+ '';
+ };
+
+ text = mkOption {
+ default = null;
+ type = types.nullOr types.lines;
+ description = ''
+ Text of the file.
+ '';
+ };
+
+ target = mkOption {
+ type = types.str;
+ default = name;
+ description = ''
+ Name of symlink (relative to
+ <filename>/etc</filename>). Defaults to the attribute
+ name.
+ '';
+ };
+
+ source = mkOption {
+ type = types.path;
+ description = ''
+ Path of the source file.
+ '';
+ };
+
+ };
+
+ config = {
+
+ source = mkIf (config.text != null) (mkDefault sourceDrv);
+
+ };
+}