summary refs log tree commit diff
path: root/nixos/modules/installer/tools/nixos-option.sh
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/installer/tools/nixos-option.sh')
-rw-r--r--nixos/modules/installer/tools/nixos-option.sh395
1 files changed, 395 insertions, 0 deletions
diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh
new file mode 100644
index 00000000000..7f008d62c24
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-option.sh
@@ -0,0 +1,395 @@
+#! @shell@ -e
+
+# Allow the location of NixOS sources and the system configuration
+# file to be overridden.
+
+: ${mountPoint=/mnt}
+: ${NIXOS_CONFIG=/etc/nixos/configuration.nix}
+export NIXOS_CONFIG
+
+usage () {
+  echo 1>&2 "
+Usage: $0 [-v] [-d] [-l] [--xml] OPTION_NAME
+       $0 --install
+
+This program allows you to inspect the current value of NixOS
+configuration options.  It can also generate a basic NixOS
+configuration file.
+
+Options:
+
+  -i | --install        Write a template NixOS configuration file to
+                        ${mountPoint:+$mountPoint/}$NIXOS_CONFIG.
+  -v | --value          Display the current value, based on your
+                        configuration.
+  -d | --description    Display the default value, the example and the
+                        description.
+  -l | --lookup         Display where the option is defined and where it
+                        is declared.
+  --xml                 Print an XML representation of the result.
+                        Implies -vdl options.
+  --help                Show this message.
+
+Environment variables affecting $0:
+
+  \$mountPoint          Path to the target file system.
+  \$NIXOS_CONFIG        Path to your configuration file.
+
+"
+
+  exit 1;
+}
+
+#####################
+# Process Arguments #
+#####################
+
+desc=false
+defs=false
+value=false
+xml=false
+install=false
+verbose=false
+
+option=""
+
+argfun=""
+for arg; do
+  if test -z "$argfun"; then
+    case $arg in
+      -*)
+        longarg=""
+        sarg="$arg"
+        while test "$sarg" != "-"; do
+          case $sarg in
+            --*) longarg=$arg; sarg="--";;
+            -d*) longarg="$longarg --description";;
+            -v*) longarg="$longarg --value";;
+            -l*) longarg="$longarg --lookup";;
+            -i*) longarg="$longarg --install";;
+            -*) usage;;
+          esac
+          # remove the first letter option
+          sarg="-${sarg#??}"
+        done
+        ;;
+      *) longarg=$arg;;
+    esac
+    for larg in $longarg; do
+      case $larg in
+        --description) desc=true;;
+        --value) value=true;;
+        --lookup) defs=true;;
+        --xml) xml=true;;
+        --install) install=true;;
+        --verbose) verbose=true;;
+        --help) usage;;
+        -*) usage;;
+        *) if test -z "$option"; then
+             option="$larg"
+           else
+             usage
+           fi;;
+      esac
+    done
+  else
+    case $argfun in
+      set_*)
+        var=$(echo $argfun | sed 's,^set_,,')
+        eval $var=$arg
+        ;;
+    esac
+    argfun=""
+  fi
+done
+
+if $xml; then
+  value=true
+  desc=true
+  defs=true
+fi
+
+# --install cannot be used with -d -v -l without option name.
+if $value || $desc || $defs && $install && test -z "$option"; then
+  usage
+fi
+
+generate=false
+if ! $defs && ! $desc && ! $value && $install && test -z "$option"; then
+  generate=true
+fi
+
+if ! $defs && ! $desc; then
+  value=true
+fi
+
+if $verbose; then
+  set -x
+else
+  set +x
+fi
+
+#############################
+# Process the configuration #
+#############################
+
+evalNix(){
+  nix-instantiate - --eval-only "$@"
+}
+
+evalAttr(){
+  local prefix=$1
+  local suffix=$2
+  local strict=$3
+  echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" |
+    evalNix ${strict:+--strict}
+}
+
+evalOpt(){
+  evalAttr "eval.options" "$@"
+}
+
+evalCfg(){
+  evalAttr "config" "$@"
+}
+
+findSources(){
+  local suffix=$1
+  echo "builtins.map (f: f.source) (import <nixos> {}).eval.options${option:+.$option}.$suffix" |
+    evalNix --strict
+}
+
+# Given a result from nix-instantiate, recover the list of attributes it
+# contains.
+attrNames() {
+  local attributeset=$1
+  # sed is used to replace un-printable subset by 0s, and to remove most of
+  # the inner-attribute set, which reduce the likelyhood to encounter badly
+  # pre-processed input.
+  echo "builtins.attrNames $attributeset" | \
+    sed 's,<[A-Z]*>,0,g; :inner; s/{[^\{\}]*};/0;/g; t inner;' | \
+    evalNix --strict
+}
+
+# map a simple list which contains strings or paths.
+nixMap() {
+  local fun="$1"
+  local list="$2"
+  local elem
+  for elem in $list; do
+    test $elem = '[' -o $elem = ']' && continue;
+    $fun $elem
+  done
+}
+
+if $install; then
+  NIXOS_CONFIG="$mountPoint$NIXOS_CONFIG"
+fi
+
+if $generate; then
+  mkdir -p $(dirname "$NIXOS_CONFIG")
+
+  # Scan the hardware and add the result to /etc/nixos/hardware-scan.nix.
+  hardware_config="${NIXOS_CONFIG%/configuration.nix}/hardware-configuration.nix"
+  if test -e "$hardware_config"; then
+    echo "A hardware configuration file exists, generation skipped."
+  else
+    echo "Generating a hardware configuration file in $hardware_config..."
+    nixos-hardware-scan > "$hardware_config"
+  fi
+
+  if test -e "$NIXOS_CONFIG"; then
+    echo 1>&2 "error: Cannot generate a template configuration because a configuration file exists."
+    exit 1
+  fi
+
+  nl="
+"
+  if test -e /sys/firmware/efi/efivars; then
+    l1="  # Use the gummiboot efi boot loader."
+    l2="  boot.loader.grub.enable = false;"
+    l3="  boot.loader.gummiboot.enable = true;"
+    l4="  boot.loader.efi.canTouchEfiVariables = true;"
+    # !!! Remove me when nixos is on 3.10 or greater by default
+    l5="  # EFI booting requires kernel >= 3.10"
+    l6="  boot.kernelPackages = pkgs.linuxPackages_3_10;"
+    bootloader_config="$l1$nl$l2$nl$l3$nl$l4$nl$nl$l5$nl$l6"
+  else
+    l1="  # Use the Grub2 boot loader."
+    l2="  boot.loader.grub.enable = true;"
+    l3="  boot.loader.grub.version = 2;"
+    l4="  # Define on which hard drive you want to install Grub."
+    l5='  # boot.loader.grub.device = "/dev/sda";'
+    bootloader_config="$l1$nl$l2$nl$l3$nl$nl$l4$nl$l5"
+  fi
+
+  echo "Generating a basic configuration file in $NIXOS_CONFIG..."
+
+  # Generate a template configuration file where the user has to
+  # fill the gaps.
+  cat <<EOF > "$NIXOS_CONFIG"
+# Edit this configuration file to define what should be installed on
+# the system.  Help is available in the configuration.nix(5) man page
+# or the NixOS manual available on virtual console 8 (Alt+F8).
+
+{ config, pkgs, ... }:
+
+{
+  imports =
+    [ # Include the results of the hardware scan.
+      ./hardware-configuration.nix
+    ];
+
+  boot.initrd.kernelModules =
+    [ # Specify all kernel modules that are necessary for mounting the root
+      # filesystem.
+      # "xfs" "ata_piix"
+      # fbcon # Uncomment this when EFI booting to see the console before the root partition is mounted
+    ];
+    
+$bootloader_config
+
+  # networking.hostName = "nixos"; # Define your hostname.
+  # networking.wireless.enable = true;  # Enables Wireless.
+
+  # Add filesystem entries for each partition that you want to see
+  # mounted at boot time.  This should include at least the root
+  # filesystem.
+
+  # fileSystems."/".device = "/dev/disk/by-label/nixos";
+
+  # fileSystems."/data" =     # where you want to mount the device
+  #   { device = "/dev/sdb";  # the device
+  #     fsType = "ext3";      # the type of the partition
+  #     options = "data=journal";
+  #   };
+
+  # List swap partitions activated at boot time.
+  swapDevices =
+    [ # { device = "/dev/disk/by-label/swap"; }
+    ];
+
+  # Select internationalisation properties.
+  # i18n = {
+  #   consoleFont = "lat9w-16";
+  #   consoleKeyMap = "us";
+  #   defaultLocale = "en_US.UTF-8";
+  # };
+
+  # List services that you want to enable:
+
+  # Enable the OpenSSH daemon.
+  # services.openssh.enable = true;
+
+  # Enable CUPS to print documents.
+  # services.printing.enable = true;
+
+  # Enable the X11 windowing system.
+  # services.xserver.enable = true;
+  # services.xserver.layout = "us";
+  # services.xserver.xkbOptions = "eurosign:e";
+
+  # Enable the KDE Desktop Environment.
+  # services.xserver.displayManager.kdm.enable = true;
+  # services.xserver.desktopManager.kde4.enable = true;
+}
+EOF
+
+  exit 0
+fi;
+
+# This duplicates the work made below, but it is useful for processing
+# the output of nixos-option with other tools such as nixos-gui.
+if $xml; then
+  evalNix --xml --no-location <<EOF
+let
+  reach = attrs: attrs${option:+.$option};
+  nixos = import <nixos> {};
+  nixpkgs = import <nixpkgs> {};
+  sources = builtins.map (f: f.source);
+  opt = reach nixos.eval.options;
+  cfg = reach nixos.config;
+in
+
+with nixpkgs.lib;
+
+let
+  optStrict = v:
+    let
+      traverse = x :
+        if isAttrs x then
+          if x ? outPath then true
+          else all id (mapAttrsFlatten (n: traverseNoAttrs) x)
+        else traverseNoAttrs x;
+      traverseNoAttrs = x:
+        # do not continue in attribute sets
+        if isAttrs x then true
+        else if isList x then all id (map traverse x)
+        else true;
+    in assert traverse v; v;
+in
+
+if isOption opt then
+  optStrict ({}
+  // optionalAttrs (opt ? default) { inherit (opt) default; }
+  // optionalAttrs (opt ? example) { inherit (opt) example; }
+  // optionalAttrs (opt ? description) { inherit (opt) description; }
+  // optionalAttrs (opt ? type) { typename = opt.type.name; }
+  // optionalAttrs (opt ? options) { inherit (opt) options; }
+  // {
+    # to disambiguate the xml output.
+    _isOption = true;
+    declarations = sources opt.declarations;
+    definitions = sources opt.definitions;
+    value = cfg;
+  })
+else
+  opt
+EOF
+  exit $?
+fi
+
+if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then
+  $value && evalCfg;
+
+  if $desc; then
+    $value && echo;
+
+    if default=$(evalOpt "default" - 2> /dev/null); then
+      echo "Default: $default"
+    else
+      echo "Default: <None>"
+    fi
+    if example=$(evalOpt "example" - 2> /dev/null); then
+      echo "Example: $example"
+    fi
+    echo "Description:"
+    eval printf $(evalOpt "description")
+  fi
+
+  if $defs; then
+    $desc || $value && echo;
+
+    printPath () { echo "  $1"; }
+
+    echo "Declared by:"
+    nixMap printPath "$(findSources "declarations")"
+    echo ""
+    echo "Defined by:"
+    nixMap printPath "$(findSources "definitions")"
+    echo ""
+  fi
+
+else
+  # echo 1>&2 "Warning: This value is not an option."
+
+  result=$(evalCfg)
+  if names=$(attrNames "$result" 2> /dev/null); then
+    echo 1>&2 "This attribute set contains:"
+    escapeQuotes () { eval echo "$1"; }
+    nixMap escapeQuotes "$names"
+  else
+    echo 1>&2 "An error occured while looking for attribute names."
+    echo $result
+  fi
+fi