diff options
Diffstat (limited to 'nixos/modules/installer/tools/nixos-option.sh')
-rw-r--r-- | nixos/modules/installer/tools/nixos-option.sh | 395 |
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 |