diff options
Diffstat (limited to 'nixpkgs/nixos/modules/installer/tools')
14 files changed, 2072 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/installer/tools/get-version-suffix b/nixpkgs/nixos/modules/installer/tools/get-version-suffix new file mode 100644 index 000000000000..8d72905cdcb4 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/get-version-suffix @@ -0,0 +1,23 @@ +getVersion() { + local dir="$1" + rev= + gitDir="$dir/.git" + if [ -e "$gitDir" ]; then + if [ -z "$(type -P git)" ]; then + echo "warning: Git not found; cannot figure out revision of $dir" >&2 + return + fi + cd "$dir" + rev=$(git --git-dir="$gitDir" rev-parse --short HEAD) + if git --git-dir="$gitDir" describe --always --dirty | grep -q dirty; then + rev+=M + fi + fi +} + +if nixpkgs=$(nix-instantiate --find-file nixpkgs "$@"); then + getVersion $nixpkgs + if [ -n "$rev" ]; then + echo ".git.$rev" + fi +fi diff --git a/nixpkgs/nixos/modules/installer/tools/manpages/nixos-build-vms.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-build-vms.8 new file mode 100644 index 000000000000..6a8f2c42eddf --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-build-vms.8 @@ -0,0 +1,105 @@ +.Dd January 1, 1980 +.Dt nixos-build-vms 8 +.Os +.Sh NAME +.Nm nixos-build-vms +.Nd build a network of virtual machines from a network of NixOS configurations +. +. +. +.Sh SYNOPSIS +.Nm nixos-build-vms +.Op Fl -show-trace +.Op Fl -no-out-link +.Op Fl -help +.Op Fl -option Ar name value +.Pa network.nix +. +. +. +.Sh DESCRIPTION +. +This command builds a network of QEMU\-KVM virtual machines of a Nix expression +specifying a network of NixOS machines. The virtual network can be started by +executing the +.Pa bin/run-vms +shell script that is generated by this command. By default, a +.Pa result +symlink is produced that points to the generated virtual network. +. +.Pp +A network Nix expression has the following structure: +.Bd -literal -offset indent +{ + test1 = {pkgs, config, ...}: + { + services.openssh.enable = true; + nixpkgs.localSystem.system = "i686-linux"; + deployment.targetHost = "test1.example.net"; + + # Other NixOS options + }; + + test2 = {pkgs, config, ...}: + { + services.openssh.enable = true; + services.httpd.enable = true; + environment.systemPackages = [ pkgs.lynx ]; + nixpkgs.localSystem.system = "x86_64-linux"; + deployment.targetHost = "test2.example.net"; + + # Other NixOS options + }; +} +.Ed +. +.Pp +Each attribute in the expression represents a machine in the network +.Ns (e.g. +.Va test1 +and +.Va test2 Ns +) referring to a function defining a NixOS configuration. In each NixOS +configuration, two attributes have a special meaning. The +.Va deployment.targetHost +specifies the address (domain name or IP address) of the system which is used by +.Ic ssh +to perform remote deployment operations. The +.Va nixpkgs.localSystem.system +attribute can be used to specify an architecture for the target machine, such as +.Ql i686-linux +which builds a 32-bit NixOS configuration. Omitting this property will build the +configuration for the same architecture as the host system. +. +. +. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl -show-trace +Shows a trace of the output. +. +.It Fl -no-out-link +Do not create a +.Pa result +symlink. +. +.It Fl h , -help +Shows the usage of this command to the user. +. +.It Fl -option Ar name Va value +Set the Nix configuration option +.Va name +to +.Va value Ns +\&. This overrides settings in the Nix configuration file (see +.Xr nix.conf 5 Ns +). +.El +. +. +. +.Sh AUTHORS +.An -nosplit +.An Eelco Dolstra +and +.An the Nixpkgs/NixOS contributors diff --git a/nixpkgs/nixos/modules/installer/tools/manpages/nixos-enter.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-enter.8 new file mode 100644 index 000000000000..646f92199d62 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-enter.8 @@ -0,0 +1,72 @@ +.Dd January 1, 1980 +.Dt nixos-enter 8 +.Os +.Sh NAME +.Nm nixos-enter +.Nd run a command in a NixOS chroot environment +. +. +. +.Sh SYNOPSIS +.Nm nixos-enter +.Op Fl -root Ar root +.Op Fl -system Ar system +.Op Fl -command | c Ar shell-command +.Op Fl -silent +.Op Fl -help +.Op Fl - Ar arguments ... +. +. +. +.Sh DESCRIPTION +This command runs a command in a NixOS chroot environment, that is, in a filesystem hierarchy previously prepared using +.Xr nixos-install 8 . +. +. +. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl -root Ar root +The path to the NixOS system you want to enter. It defaults to +.Pa /mnt Ns +\&. +.It Fl -system Ar system +The NixOS system configuration to use. It defaults to +.Pa /nix/var/nix/profiles/system Ns +\&. You can enter a previous NixOS configuration by specifying a path such as +.Pa /nix/var/nix/profiles/system-106-link Ns +\&. +. +.It Fl -command Ar shell-command , Fl c Ar shell-command +The bash command to execute. +. +.It Fl -silent +Suppresses all output from the activation script of the target system. +. +.It Fl - +Interpret the remaining arguments as the program name and arguments to be invoked. +The program is not executed in a shell. +.El +. +. +. +.Sh EXAMPLES +.Bl -tag -width indent +.It Ic nixos-enter --root /mnt +Start an interactive shell in the NixOS installation in +.Pa /mnt Ns . +. +.It Ic nixos-enter -c 'ls -l /; cat /proc/mounts' +Run a shell command. +. +.It Ic nixos-enter -- cat /proc/mounts +Run a non-shell command. +.El +. +. +. +.Sh AUTHORS +.An -nosplit +.An Eelco Dolstra +and +.An the Nixpkgs/NixOS contributors diff --git a/nixpkgs/nixos/modules/installer/tools/manpages/nixos-generate-config.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-generate-config.8 new file mode 100644 index 000000000000..1b95599e156a --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-generate-config.8 @@ -0,0 +1,165 @@ +.Dd January 1, 1980 +.Dt nixos-generate-config 8 +.Os +.Sh NAME +.Nm nixos-generate-config +.Nd generate NixOS configuration modules +. +. +. +.Sh SYNOPSIS +.Nm nixos-generate-config +.Op Fl -force +.Op Fl -root Ar root +.Op Fl -dir Ar dir +. +. +. +.Sh DESCRIPTION +This command writes two NixOS configuration modules: +.Bl -tag -width indent +.It Pa /etc/nixos/hardware-configuration.nix +This module sets NixOS configuration options based on your current hardware +configuration. In particular, it sets the +.Va fileSystem +option to reflect all currently mounted file systems, the +.Va swapDevices +option to reflect active swap devices, and the +.Va boot.initrd.* +options to ensure that the initial ramdisk contains any kernel modules necessary +for mounting the root file system. +.Pp +If this file already exists, it is overwritten. Thus, you should not modify it +manually. Rather, you should include it from your +.Pa /etc/nixos/configuration.nix Ns +, and re-run +.Nm +to update it whenever your hardware configuration changes. +. +.It Pa /etc/nixos/configuration.nix +This is the main NixOS system configuration module. If it already exists, it’s +left unchanged. Otherwise, +.Nm +will write a template for you to customise. +.El +. +. +. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl -root Ar root +If this option is given, treat the directory +.Ar root +as the root of the file system. This means that configuration files will be written to +.Ql Ar root Ns /etc/nixos Ns +, and that any file systems outside of +.Ar root +are ignored for the purpose of generating the +.Va fileSystems +option. +. +.It Fl -dir Ar dir +If this option is given, write the configuration files to the directory +.Ar dir +instead of +.Pa /etc/nixos Ns +\&. +. +.It Fl -force +Overwrite +.Pa /etc/nixos/configuration.nix +if it already exists. +. +.It Fl -no-filesystems +Omit everything concerning file systems and swap devices from the hardware configuration. +. +.It Fl -show-hardware-config +Don't generate +.Pa configuration.nix +or +.Pa hardware-configuration.nix +and print the hardware configuration to stdout only. +.El +. +. +. +.Sh EXAMPLES +This command is typically used during NixOS installation to write initial +configuration modules. For example, if you created and mounted the target file +systems on +.Pa /mnt +and +.Pa /mnt/boot Ns +, you would run: +.Bd -literal -offset indent +$ nixos-generate-config --root /mnt +.Ed +. +.Pp +The resulting file +.Pa /mnt/etc/nixos/hardware-configuration.nix +might look like this: +.Bd -literal -offset indent +# Do not modify this file! It was generated by 'nixos-generate-config' +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, pkgs, ... }: + +{ + imports = + [ <nixos/modules/installer/scan/not-detected.nix> + ]; + + boot.initrd.availableKernelModules = [ "ehci_hcd" "ahci" ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-label/nixos"; + fsType = "ext3"; + options = [ "rw" "data=ordered" "relatime" ]; + }; + + fileSystems."/boot" = + { device = "/dev/sda1"; + fsType = "ext3"; + options = [ "rw" "errors=continue" "user_xattr" "acl" "barrier=1" "data=writeback" "relatime" ]; + }; + + swapDevices = + [ { device = "/dev/sda2"; } + ]; + + nix.maxJobs = 8; +} +.Ed +. +.Pp +It will also create a basic +.Pa /mnt/etc/nixos/configuration.nix Ns +, which you should edit to customise the logical configuration of your system. \ +This file includes the result of the hardware scan as follows: +.Bd -literal -offset indent +imports = [ ./hardware-configuration.nix ]; +.Ed +. +.Pp +After installation, if your hardware configuration changes, you can run: +.Bd -literal -offset indent +$ nixos-generate-config +.Ed +. +.Pp +to update +.Pa /etc/nixos/hardware-configuration.nix Ns +\&. Your +.Pa /etc/nixos/configuration.nix +will +.Em not +be overwritten. +. +.Sh AUTHORS +.An -nosplit +.An Eelco Dolstra +and +.An the Nixpkgs/NixOS contributors diff --git a/nixpkgs/nixos/modules/installer/tools/manpages/nixos-install.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-install.8 new file mode 100644 index 000000000000..c6c8ed15224d --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-install.8 @@ -0,0 +1,191 @@ +.Dd January 1, 1980 +.Dt nixos-install 8 +.Os +.Sh NAME +.Nm nixos-install +.Nd install bootloader and NixOS +. +. +. +.Sh SYNOPSIS +.Nm nixos-install +.Op Fl -verbose | v +.Op Fl I Ar path +.Op Fl -root Ar root +.Op Fl -system Ar path +.Op Fl -flake Ar flake-uri +.Op Fl -impure +.Op Fl -channel Ar channel +.Op Fl -no-channel-copy +.Op Fl -no-root-password | -no-root-passwd +.Op Fl -no-bootloader +.Op Fl -max-jobs | j Ar number +.Op Fl -cores Ar number +.Op Fl -option Ar name value +.Op Fl -show-trace +.Op Fl -keep-going +.Op Fl -help +. +. +. +.Sh DESCRIPTION +This command installs NixOS in the file system mounted on +.Pa /mnt Ns +, based on the NixOS configuration specified in +.Pa /mnt/etc/nixos/configuration.nix Ns +\&. It performs the following steps: +. +.Bl -enum +.It +It copies Nix and its dependencies to +.Pa /mnt/nix/store Ns +\&. +. +.It +It runs Nix in +.Pa /mnt +to build the NixOS configuration specified in +.Pa /mnt/etc/nixos/configuration.nix Ns +\&. +. +.It +It installs the current channel +.Dq nixos +in the target channel profile (unless +.Fl -no-channel-copy +is specified). +. +.It +It installs the GRUB boot loader on the device specified in the option +.Va boot.loader.grub.device +(unless +.Fl -no-bootloader +is specified), and generates a GRUB configuration file that boots into the NixOS +configuration just installed. +. +.It +It prompts you for a password for the root account (unless +.Fl -no-root-password +is specified). +.El +. +.Pp +This command is idempotent: if it is interrupted or fails due to a temporary +problem (e.g. a network issue), you can safely re-run it. +. +. +. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl -verbose , v +Increases the level of verbosity of diagnostic messages printed on standard +error. For each Nix operation, the information printed on standard output is +well-defined; any diagnostic information is printed on standard error, never on +standard output. +.Pp +Please note that this option may be specified repeatedly. +. +.It Fl -root Ar root +Defaults to +.Pa /mnt Ns +\&. If this option is given, treat the directory +.Ar root +as the root of the NixOS installation. +. +.It Fl -system Ar path +If this option is provided, +.Nm +will install the specified closure rather than attempt to build one from +.Pa /mnt/etc/nixos/configuration.nix Ns +\&. +.Pp +The closure must be an appropriately configured NixOS system, with boot loader +and partition configuration that fits the target host. Such a closure is +typically obtained with a command such as +.Ic nix-build -I nixos-config=./configuration.nix '<nixpkgs/nixos>' -A system --no-out-link Ns +\&. +. +.It Fl -flake Ar flake-uri Ns # Ns Ar name +Build the NixOS system from the specified flake. The flake must contain an +output named +.Ql nixosConfigurations. Ns Ar name Ns +\&. +. +.It Fl -channel Ar channel +If this option is provided, do not copy the current +.Dq nixos +channel to the target host. Instead, use the specified derivation. +. +.It Fl I Ar Path +Add a path to the Nix expression search path. This option may be given multiple +times. See the +.Ev NIX_PATH +environment variable for information on the semantics of the Nix search path. Paths added through +.Fl I +take precedence over +.Ev NIX_PATH Ns +\&. +. +.It Fl -max-jobs , j Ar number +Sets the maximum number of build jobs that Nix will perform in parallel to the +specified number. The default is 1. A higher value is useful on SMP systems or +to exploit I/O latency. +. +.It Fl -cores Ar N +Sets the value of the +.Ev NIX_BUILD_CORES +environment variable in the invocation of builders. Builders can use this +variable at their discretion to control the maximum amount of parallelism. For +instance, in Nixpkgs, if the derivation attribute +.Va enableParallelBuilding +is set to true, the builder passes the +.Fl j Ns Va N +flag to GNU Make. The value 0 means that the builder should use all available CPU cores in the system. +. +.It Fl -option Ar name value +Set the Nix configuration option +.Ar name +to +.Ar value Ns +\&. +. +.It Fl -show-trace +Causes Nix to print out a stack trace in case of Nix expression evaluation errors. +. +.It Fl -keep-going +Causes Nix to continue building derivations as far as possible in the face of failed builds. +. +.It Fl -help +Synonym for +.Ic man nixos-install Ns +\&. +.El +. +. +. +.Sh EXAMPLES +A typical NixOS installation is done by creating and mounting a file system on +.Pa /mnt Ns +, generating a NixOS configuration in +.Pa /mnt/etc/nixos/configuration.nix Ns +, and running +.Nm Ns +\&. For instance, if we want to install NixOS on an ext4 file system created in +.Pa /dev/sda1 Ns +: +.Bd -literal -offset indent +$ mkfs.ext4 /dev/sda1 +$ mount /dev/sda1 /mnt +$ nixos-generate-config --root /mnt +$ # edit /mnt/etc/nixos/configuration.nix +$ nixos-install +$ reboot +.Ed +. +. +. +.Sh AUTHORS +.An -nosplit +.An Eelco Dolstra +and +.An the Nixpkgs/NixOS contributors diff --git a/nixpkgs/nixos/modules/installer/tools/manpages/nixos-version.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-version.8 new file mode 100644 index 000000000000..f661611599fb --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-version.8 @@ -0,0 +1,86 @@ +.Dd January 1, 1980 +.Dt nixos-version 8 +.Os +.Sh NAME +.Nm nixos-version +.Nd show the NixOS version +. +. +. +.Sh SYNOPSIS +.Nm nixos-version +.Op Fl -hash +.Op Fl -revision +.Op Fl -configuration-revision +.Op Fl -json +. +. +. +.Sh DESCRIPTION +This command shows the version of the currently active NixOS configuration. For example: +.Bd -literal -offset indent +$ nixos-version +16.03.1011.6317da4 (Emu) +.Ed +. +.Pp +The version consists of the following elements: +.Bl -tag -width indent +.It Ql 16.03 +The NixOS release, indicating the year and month in which it was released +(e.g. March 2016). +.It Ql 1011 +The number of commits in the Nixpkgs Git repository between the start of the +release branch and the commit from which this version was built. This ensures +that NixOS versions are monotonically increasing. It is +.Ql git +when the current NixOS configuration was built from a checkout of the Nixpkgs +Git repository rather than from a NixOS channel. +.It Ql 6317da4 +The first 7 characters of the commit in the Nixpkgs Git repository from which +this version was built. +.It Ql Emu +The code name of the NixOS release. The first letter of the code name indicates +that this is the N'th stable NixOS release; for example, Emu is the fifth +release. +.El +. +. +. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl -hash , -revision +Show the full SHA1 hash of the Git commit from which this configuration was +built, e.g. +.Bd -literal -offset indent +$ nixos-version --hash +6317da40006f6bc2480c6781999c52d88dde2acf +.Ed +. +.It Fl -configuration-revision +Show the configuration revision if available. This could be the full SHA1 hash +of the Git commit of the system flake, if you add +.Bd -literal -offset indent +{ system.configurationRevision = self.rev or "dirty"; } +.Ed +.Pp +to the +.Ql modules +array of your flake.nix system configuration e.g. +.Bd -literal -offset indent +$ nixos-version --configuration-revision +aa314ebd1592f6cdd53cb5bba8bcae97d9323de8 +.Ed +. +.It Fl -json +Print a JSON representation of the versions of NixOS and the top-level +configuration flake. +.El +. +. +. +.Sh AUTHORS +.An -nosplit +.An Eelco Dolstra +and +.An the Nixpkgs/NixOS contributors diff --git a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix new file mode 100644 index 000000000000..e4241e965403 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix @@ -0,0 +1,7 @@ +{ + x86_64-linux = "/nix/store/azvn85cras6xv4z5j85fiy406f24r1q0-nix-2.18.1"; + i686-linux = "/nix/store/9bnwy7f9h0kzdzmcnjjsjg0aak5waj40-nix-2.18.1"; + aarch64-linux = "/nix/store/hh65xwqm9s040s3cgn9vzcmrxj0sf5ij-nix-2.18.1"; + x86_64-darwin = "/nix/store/6zi5fqzn9n17wrk8r41rhdw4j7jqqsi3-nix-2.18.1"; + aarch64-darwin = "/nix/store/0pbq6wzr2f1jgpn5212knyxpwmkjgjah-nix-2.18.1"; +} diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix new file mode 100644 index 000000000000..21a257378a63 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix @@ -0,0 +1,31 @@ +{ system ? builtins.currentSystem +, config ? {} +, networkExpr +}: + +let + nodes = builtins.mapAttrs (vm: module: { + _file = "${networkExpr}@node-${vm}"; + imports = [ module ]; + }) (import networkExpr); + + pkgs = import ../../../../.. { inherit system config; }; + + testing = import ../../../../lib/testing-python.nix { + inherit system pkgs; + }; + + interactiveDriver = (testing.makeTest { inherit nodes; name = "network"; testScript = "start_all(); join_all();"; }).test.driverInteractive; +in + + +pkgs.runCommand "nixos-build-vms" { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' + mkdir -p $out/bin + ln -s ${interactiveDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver + ln -s ${interactiveDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms + wrapProgram $out/bin/nixos-test-driver \ + --add-flags "--interactive" + wrapProgram $out/bin/nixos-run-vms \ + --set testScript "${pkgs.writeText "start-all" "start_all(); join_all();"}" \ + --add-flags "--no-interactive" +'' diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh new file mode 100644 index 000000000000..490ede04e6bb --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh @@ -0,0 +1,53 @@ +#! @runtimeShell@ -e +# shellcheck shell=bash + +# Shows the usage of this command to the user + +showUsage() { + exec man nixos-build-vms + exit 1 +} + +# Parse valid argument options + +nixBuildArgs=() +networkExpr= + +while [ $# -gt 0 ]; do + case "$1" in + --no-out-link) + nixBuildArgs+=("--no-out-link") + ;; + --show-trace) + nixBuildArgs+=("--show-trace") + ;; + -h|--help) + showUsage + exit 0 + ;; + --option) + shift + nixBuildArgs+=("--option" "$1" "$2"); shift + ;; + *) + if [ -n "$networkExpr" ]; then + echo "Network expression already set!" + showUsage + exit 1 + fi + networkExpr="$(readlink -f "$1")" + ;; + esac + + shift +done + +if [ -z "$networkExpr" ] +then + echo "ERROR: A network expression must be specified!" >&2 + exit 1 +fi + +# Build a network of VMs +nix-build '<nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix>' \ + --argstr networkExpr "$networkExpr" "${nixBuildArgs[@]}" diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh new file mode 100755 index 000000000000..9141cc285702 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh @@ -0,0 +1,110 @@ +#! @runtimeShell@ +# shellcheck shell=bash + +set -e + +# Re-exec ourselves in a private mount namespace so that our bind +# mounts get cleaned up automatically. +if [ -z "$NIXOS_ENTER_REEXEC" ]; then + export NIXOS_ENTER_REEXEC=1 + if [ "$(id -u)" != 0 ]; then + extraFlags="-r" + fi + exec unshare --fork --mount --uts --mount-proc --pid $extraFlags -- "$0" "$@" +else + mount --make-rprivate / +fi + +mountPoint=/mnt +system=/nix/var/nix/profiles/system +command=("$system/sw/bin/bash" "--login") +silent=0 + +while [ "$#" -gt 0 ]; do + i="$1"; shift 1 + case "$i" in + --root) + mountPoint="$1"; shift 1 + ;; + --system) + system="$1"; shift 1 + ;; + --help) + exec man nixos-enter + exit 1 + ;; + --command|-c) + command=("$system/sw/bin/bash" "-c" "$1") + shift 1 + ;; + --silent) + silent=1 + ;; + --) + command=("$@") + break + ;; + *) + echo "$0: unknown option \`$i'" + exit 1 + ;; + esac +done + +if [[ ! -e $mountPoint/etc/NIXOS ]]; then + echo "$0: '$mountPoint' is not a NixOS installation" >&2 + exit 126 +fi + +mkdir -p "$mountPoint/dev" "$mountPoint/sys" +chmod 0755 "$mountPoint/dev" "$mountPoint/sys" +mount --rbind /dev "$mountPoint/dev" +mount --rbind /sys "$mountPoint/sys" + +# modified from https://github.com/archlinux/arch-install-scripts/blob/bb04ab435a5a89cd5e5ee821783477bc80db797f/arch-chroot.in#L26-L52 +chroot_add_resolv_conf() { + local chrootDir="$1" resolvConf="$1/etc/resolv.conf" + + [[ -e /etc/resolv.conf ]] || return 0 + + # Handle resolv.conf as a symlink to somewhere else. + if [[ -L "$resolvConf" ]]; then + # readlink(1) should always give us *something* since we know at this point + # it's a symlink. For simplicity, ignore the case of nested symlinks. + # We also ignore the possibility of `../`s escaping the root. + resolvConf="$(readlink "$resolvConf")" + if [[ "$resolvConf" = /* ]]; then + resolvConf="$chrootDir$resolvConf" + else + resolvConf="$chrootDir/etc/$resolvConf" + fi + fi + + # ensure file exists to bind mount over + if [[ ! -f "$resolvConf" ]]; then + install -Dm644 /dev/null "$resolvConf" || return 1 + fi + + mount --bind /etc/resolv.conf "$resolvConf" +} + +chroot_add_resolv_conf "$mountPoint" || echo "$0: failed to set up resolv.conf" >&2 + +( + # If silent, write both stdout and stderr of activation script to /dev/null + # otherwise, write both streams to stderr of this process + if [ "$silent" -eq 1 ]; then + exec 2>/dev/null + fi + + # Run the activation script. Set $LOCALE_ARCHIVE to suppress some Perl locale warnings. + LOCALE_ARCHIVE="$system/sw/lib/locale/locale-archive" IN_NIXOS_ENTER=1 chroot "$mountPoint" "$system/activate" 1>&2 || true + + # Create /tmp. This is needed for nix-build and the NixOS activation script to work. + # Hide the unhelpful "failed to replace specifiers" errors caused by missing /etc/machine-id. + chroot "$mountPoint" "$system/sw/bin/systemd-tmpfiles" --create --remove -E 2> /dev/null || true +) + +unset TMPDIR + +exec chroot "$mountPoint" "${command[@]}" diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl new file mode 100644 index 000000000000..2f9edba4f0c9 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl @@ -0,0 +1,701 @@ +#! @perl@ + +use strict; +use Cwd 'abs_path'; +use File::Spec; +use File::Path; +use File::Basename; +use File::Slurp; +use File::stat; + +umask(0022); + +sub uniq { + my %seen; + my @res = (); + foreach my $s (@_) { + if (!defined $seen{$s}) { + $seen{$s} = 1; + push @res, $s; + } + } + return @res; +} + +sub runCommand { + my ($cmd) = @_; + open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n"; + my @ret = <FILE>; + close FILE; + return ($?, @ret); +} + +# Process the command line. +my $outDir = "/etc/nixos"; +my $rootDir = ""; # = / +my $force = 0; +my $noFilesystems = 0; +my $showHardwareConfig = 0; + +for (my $n = 0; $n < scalar @ARGV; $n++) { + my $arg = $ARGV[$n]; + if ($arg eq "--help") { + exec "man nixos-generate-config" or die; + } + elsif ($arg eq "--dir") { + $n++; + $outDir = $ARGV[$n]; + die "$0: ‘--dir’ requires an argument\n" unless defined $outDir; + } + elsif ($arg eq "--root") { + $n++; + $rootDir = $ARGV[$n]; + die "$0: ‘--root’ requires an argument\n" unless defined $rootDir; + die "$0: no need to specify `/` with `--root`, it is the default\n" if $rootDir eq "/"; + $rootDir =~ s/\/*$//; # remove trailing slashes + $rootDir = File::Spec->rel2abs($rootDir); # resolve absolute path + } + elsif ($arg eq "--force") { + $force = 1; + } + elsif ($arg eq "--no-filesystems") { + $noFilesystems = 1; + } + elsif ($arg eq "--show-hardware-config") { + $showHardwareConfig = 1; + } + else { + die "$0: unrecognized argument ‘$arg’\n"; + } +} + + +my @attrs = (); +my @kernelModules = (); +my @initrdKernelModules = (); +my @initrdAvailableKernelModules = (); +my @modulePackages = (); +my @imports; + + +sub debug { + return unless defined $ENV{"DEBUG"}; + print STDERR @_; +} + + +# nixpkgs.system +push @attrs, "nixpkgs.hostPlatform = lib.mkDefault \"@hostPlatformSystem@\";"; + + +my $cpuinfo = read_file "/proc/cpuinfo"; + + +sub hasCPUFeature { + my $feature = shift; + return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m; +} + + +sub cpuManufacturer { + my $id = shift; + return $cpuinfo =~ /^vendor_id\s*:.* $id$/m; +} + +# Virtualization support? +push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; +push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; + + +# Look at the PCI devices and add necessary modules. Note that most +# modules are auto-detected so we don't need to list them here. +# However, some are needed in the initrd to boot the system. + +my $videoDriver; + +sub pciCheck { + my $path = shift; + my $vendor = read_file "$path/vendor"; chomp $vendor; + my $device = read_file "$path/device"; chomp $device; + my $class = read_file "$path/class"; chomp $class; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + debug "$path: $vendor $device $class"; + debug " $module" if defined $module; + debug "\n"; + + if (defined $module) { + # See the bottom of https://pciids.sourceforge.net/pci.ids for + # device classes. + if (# Mass-storage controller. Definitely important. + $class =~ /^0x01/ || + + # Firewire controller. A disk might be attached. + $class =~ /^0x0c00/ || + + # USB controller. Needed if we want to use the + # keyboard when things go wrong in the initrd. + $class =~ /^0x0c03/ + ) + { + push @initrdAvailableKernelModules, $module; + } + } + + # broadcom STA driver (wl.ko) + # list taken from http://www.broadcom.com/docs/linux_sta/README.txt + if ($vendor eq "0x14e4" && + ($device eq "0x4311" || $device eq "0x4312" || $device eq "0x4313" || + $device eq "0x4315" || $device eq "0x4327" || $device eq "0x4328" || + $device eq "0x4329" || $device eq "0x432a" || $device eq "0x432b" || + $device eq "0x432c" || $device eq "0x432d" || $device eq "0x4353" || + $device eq "0x4357" || $device eq "0x4358" || $device eq "0x4359" || + $device eq "0x4331" || $device eq "0x43a0" || $device eq "0x43b1" + ) ) + { + push @modulePackages, "config.boot.kernelPackages.broadcom_sta"; + push @kernelModules, "wl"; + } + + # broadcom FullMac driver + # list taken from + # https://wireless.wiki.kernel.org/en/users/Drivers/brcm80211#brcmfmac + if ($vendor eq "0x14e4" && + ($device eq "0x43a3" || $device eq "0x43df" || $device eq "0x43ec" || + $device eq "0x43d3" || $device eq "0x43d9" || $device eq "0x43e9" || + $device eq "0x43ba" || $device eq "0x43bb" || $device eq "0x43bc" || + $device eq "0xaa52" || $device eq "0x43ca" || $device eq "0x43cb" || + $device eq "0x43cc" || $device eq "0x43c3" || $device eq "0x43c4" || + $device eq "0x43c5" + ) ) + { + # we need e.g. brcmfmac43602-pcie.bin + push @imports, "(modulesPath + \"/hardware/network/broadcom-43xx.nix\")"; + } + + # In case this is a virtio scsi device, we need to explicitly make this available. + if ($vendor eq "0x1af4" && ($device eq "0x1004" || $device eq "0x1048") ) { + push @initrdAvailableKernelModules, "virtio_scsi"; + } + + # Can't rely on $module here, since the module may not be loaded + # due to missing firmware. Ideally we would check modules.pcimap + # here. + push @attrs, "networking.enableIntel2200BGFirmware = true;" if + $vendor eq "0x8086" && + ($device eq "0x1043" || $device eq "0x104f" || $device eq "0x4220" || + $device eq "0x4221" || $device eq "0x4223" || $device eq "0x4224"); + + push @attrs, "networking.enableIntel3945ABGFirmware = true;" if + $vendor eq "0x8086" && + ($device eq "0x4229" || $device eq "0x4230" || + $device eq "0x4222" || $device eq "0x4227"); + + # Assume that all NVIDIA cards are supported by the NVIDIA driver. + # There may be exceptions (e.g. old cards). + # FIXME: do we want to enable an unfree driver here? + #$videoDriver = "nvidia" if $vendor eq "0x10de" && $class =~ /^0x03/; +} + +foreach my $path (glob "/sys/bus/pci/devices/*") { + pciCheck $path; +} + +# Idem for USB devices. + +sub usbCheck { + my $path = shift; + my $class = read_file "$path/bInterfaceClass"; chomp $class; + my $subclass = read_file "$path/bInterfaceSubClass"; chomp $subclass; + my $protocol = read_file "$path/bInterfaceProtocol"; chomp $protocol; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + debug "$path: $class $subclass $protocol"; + debug " $module" if defined $module; + debug "\n"; + + if (defined $module) { + if (# Mass-storage controller. Definitely important. + $class eq "08" || + + # Keyboard. Needed if we want to use the + # keyboard when things go wrong in the initrd. + ($class eq "03" && $protocol eq "01") + ) + { + push @initrdAvailableKernelModules, $module; + } + } +} + +foreach my $path (glob "/sys/bus/usb/devices/*") { + if (-e "$path/bInterfaceClass") { + usbCheck $path; + } +} + + +# Add the modules for all block and MMC devices. +foreach my $path (glob "/sys/class/{block,mmc_host}/*") { + my $module; + if (-e "$path/device/driver/module") { + $module = basename `readlink -f $path/device/driver/module`; + chomp $module; + push @initrdAvailableKernelModules, $module; + } +} + +# Add bcache module, if needed. +my @bcacheDevices = glob("/dev/bcache*"); +@bcacheDevices = grep(!qr#dev/bcachefs.*#, @bcacheDevices); +if (scalar @bcacheDevices > 0) { + push @initrdAvailableKernelModules, "bcache"; +} + +# Prevent unbootable systems if LVM snapshots are present at boot time. +if (`lsblk -o TYPE` =~ "lvm") { + push @initrdKernelModules, "dm-snapshot"; +} + +my $virt = `@detectvirt@`; +chomp $virt; + + +# Check if we're a VirtualBox guest. If so, enable the guest +# additions. +if ($virt eq "oracle") { + push @attrs, "virtualisation.virtualbox.guest.enable = true;" +} + +# Check if we're a Parallels guest. If so, enable the guest additions. +# It is blocked by https://github.com/systemd/systemd/pull/23859 +if ($virt eq "parallels") { + push @attrs, "hardware.parallels.enable = true;"; + push @attrs, "nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ \"prl-tools\" ];"; +} + +# Likewise for QEMU. +if ($virt eq "qemu" || $virt eq "kvm" || $virt eq "bochs") { + push @imports, "(modulesPath + \"/profiles/qemu-guest.nix\")"; +} + +# Also for Hyper-V. +if ($virt eq "microsoft") { + push @attrs, "virtualisation.hypervGuest.enable = true;" +} + + +# Pull in NixOS configuration for containers. +if ($virt eq "systemd-nspawn") { + push @attrs, "boot.isContainer = true;"; +} + + +# Check if we're on bare metal, not in a VM/container. +if ($virt eq "none") { + # Provide firmware for devices that are not detected by this script. + push @imports, "(modulesPath + \"/installer/scan/not-detected.nix\")"; + + # Update the microcode. + push @attrs, "hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "AuthenticAMD"; + push @attrs, "hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "GenuineIntel"; +} + +# For a device name like /dev/sda1, find a more stable path like +# /dev/disk/by-uuid/X or /dev/disk/by-label/Y. +sub findStableDevPath { + my ($dev) = @_; + return $dev if substr($dev, 0, 1) ne "/"; + return $dev unless -e $dev; + + my $st = stat($dev) or return $dev; + + foreach my $dev2 (glob("/dev/stratis/*/*"), glob("/dev/disk/by-uuid/*"), glob("/dev/mapper/*"), glob("/dev/disk/by-label/*")) { + my $st2 = stat($dev2) or next; + return $dev2 if $st->rdev == $st2->rdev; + } + + return $dev; +} + +push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];" if $videoDriver; + +# Generate the swapDevices option from the currently activated swap +# devices. +my @swaps = read_file("/proc/swaps", err_mode => 'carp'); +my @swapDevices; +if (@swaps) { + shift @swaps; + foreach my $swap (@swaps) { + my @fields = split ' ', $swap; + my $swapFilename = $fields[0]; + my $swapType = $fields[1]; + next unless -e $swapFilename; + my $dev = findStableDevPath $swapFilename; + if ($swapType =~ "partition") { + # zram devices are more likely created by configuration.nix, so + # ignore them here + next if ($swapFilename =~ /^\/dev\/zram/); + push @swapDevices, "{ device = \"$dev\"; }"; + } elsif ($swapType =~ "file") { + # swap *files* are more likely specified in configuration.nix, so + # ignore them here. + } else { + die "Unsupported swap type: $swapType\n"; + } + } +} + + +# Generate the fileSystems option from the currently mounted +# filesystems. +sub in { + my ($d1, $d2) = @_; + return $d1 eq $d2 || substr($d1, 0, length($d2) + 1) eq "$d2/"; +} + +my $fileSystems; +my %fsByDev; +my $useSwraid = 0; +foreach my $fs (read_file("/proc/self/mountinfo")) { + chomp $fs; + my @fields = split / /, $fs; + my $mountPoint = $fields[4]; + $mountPoint =~ s/\\040/ /g; # account for mount points with spaces in the name (\040 is the escape character) + $mountPoint =~ s/\\011/\t/g; # account for mount points with tabs in the name (\011 is the escape character) + next unless -d $mountPoint; + my @mountOptions = split /,/, $fields[5]; + + next if !in($mountPoint, $rootDir); + $mountPoint = substr($mountPoint, length($rootDir)); # strip the root directory (e.g. /mnt) + $mountPoint = "/" if $mountPoint eq ""; + + # Skip special filesystems. + next if in($mountPoint, "/proc") || in($mountPoint, "/dev") || in($mountPoint, "/sys") || in($mountPoint, "/run") || $mountPoint eq "/var/lib/nfs/rpc_pipefs"; + + # Skip the optional fields. + my $n = 6; $n++ while $fields[$n] ne "-"; $n++; + my $fsType = $fields[$n]; + my $device = $fields[$n + 1]; + my @superOptions = split /,/, $fields[$n + 2]; + $device =~ s/\\040/ /g; # account for devices with spaces in the name (\040 is the escape character) + $device =~ s/\\011/\t/g; # account for mount points with tabs in the name (\011 is the escape character) + + # Skip the read-only bind-mount on /nix/store. + next if $mountPoint eq "/nix/store" && (grep { $_ eq "rw" } @superOptions) && (grep { $_ eq "ro" } @mountOptions); + + # Maybe this is a bind-mount of a filesystem we saw earlier? + if (defined $fsByDev{$fields[2]}) { + # Make sure this isn't a btrfs subvolume. + my $msg = `@btrfs@ subvol show $rootDir$mountPoint`; + if ($? != 0 || $msg =~ /ERROR:/s) { + my $path = $fields[3]; $path = "" if $path eq "/"; + my $base = $fsByDev{$fields[2]}; + $base = "" if $base eq "/"; + $fileSystems .= <<EOF; + fileSystems.\"$mountPoint\" = + { device = \"$base$path\"; + fsType = \"none\"; + options = \[ \"bind\" \]; + }; + +EOF + next; + } + } + $fsByDev{$fields[2]} = $mountPoint; + + # We don't know how to handle FUSE filesystems. + if ($fsType eq "fuseblk" || $fsType eq "fuse") { + print STDERR "warning: don't know how to emit ‘fileSystem’ option for FUSE filesystem ‘$mountPoint’\n"; + next; + } + + # Is this a mount of a loopback device? + my @extraOptions; + if ($device =~ /\/dev\/loop(\d+)/) { + my $loopnr = $1; + my $backer = read_file "/sys/block/loop$loopnr/loop/backing_file"; + if (defined $backer) { + chomp $backer; + $device = $backer; + push @extraOptions, "loop"; + } + } + + # Is this a btrfs filesystem? + if ($fsType eq "btrfs") { + my ($status, @info) = runCommand("@btrfs@ subvol show $rootDir$mountPoint"); + if ($status != 0 || join("", @info) =~ /ERROR:/) { + die "Failed to retrieve subvolume info for $mountPoint\n"; + } + my @ids = join("\n", @info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s; + if ($#ids > 0) { + die "Btrfs subvol name for $mountPoint listed multiple times in mount\n" + } elsif ($#ids == 0) { + my @paths = join("", @info) =~ m/^([^\n]*)/; + if ($#paths > 0) { + die "Btrfs returned multiple paths for a single subvolume id, mountpoint $mountPoint\n"; + } elsif ($#paths != 0) { + die "Btrfs did not return a path for the subvolume at $mountPoint\n"; + } + push @extraOptions, "subvol=$paths[0]"; + } + } + + # is this a stratis fs? + my $stableDevPath = findStableDevPath $device; + my $stratisPool; + if ($stableDevPath =~ qr#/dev/stratis/(.*)/.*#) { + my $poolName = $1; + my ($header, @lines) = split "\n", qx/stratis pool list/; + my $uuidIndex = index $header, 'UUID'; + my ($line) = grep /^$poolName /, @lines; + $stratisPool = substr $line, $uuidIndex - 32, 36; + } + + # Don't emit tmpfs entry for /tmp, because it most likely comes from the + # boot.tmp.useTmpfs option in configuration.nix (managed declaratively). + next if ($mountPoint eq "/tmp" && $fsType eq "tmpfs"); + + # This should work for single and multi-device systems. + # still needs subvolume support + if ($fsType eq "bcachefs") { + my ($status, @info) = runCommand("bcachefs fs usage $rootDir$mountPoint"); + my $UUID = $info[0]; + + if ($status == 0 && $UUID =~ /^Filesystem:[ \t\n]*([0-9a-z-]+)/) { + $stableDevPath = "UUID=$1"; + } else { + print STDERR "warning: can't find bcachefs mount UUID falling back to device-path"; + } + } + + # Emit the filesystem. + $fileSystems .= <<EOF; + fileSystems.\"$mountPoint\" = + { device = \"$stableDevPath\"; + fsType = \"$fsType\"; +EOF + + if (scalar @extraOptions > 0) { + $fileSystems .= <<EOF; + options = \[ ${\join " ", map { "\"" . $_ . "\"" } uniq(@extraOptions)} \]; +EOF + } + + if ($stratisPool) { + $fileSystems .= <<EOF; + stratis.poolUuid = "$stratisPool"; +EOF + } + + $fileSystems .= <<EOF; + }; + +EOF + + # If this filesystem is on a LUKS device, then add a + # boot.initrd.luks.devices entry. + if (-e $device) { + my $deviceName = basename(abs_path($device)); + my $dmUuid = read_file("/sys/class/block/$deviceName/dm/uuid", err_mode => 'quiet'); + if ($dmUuid =~ /^CRYPT-LUKS/) + { + my @slaves = glob("/sys/class/block/$deviceName/slaves/*"); + if (scalar @slaves == 1) { + my $slave = "/dev/" . basename($slaves[0]); + if (-e $slave) { + my $dmName = read_file("/sys/class/block/$deviceName/dm/name"); + chomp $dmName; + # Ensure to add an entry only once + my $luksDevice = " boot.initrd.luks.devices.\"$dmName\".device"; + if ($fileSystems !~ /^\Q$luksDevice\E/m) { + $fileSystems .= "$luksDevice = \"${\(findStableDevPath $slave)}\";\n\n"; + } + } + } + } + if (-e "/sys/class/block/$deviceName/md/uuid") { + $useSwraid = 1; + } + } +} +if ($useSwraid) { + push @attrs, "boot.swraid.enable = true;\n\n"; +} + + +# Generate the hardware configuration file. + +sub toNixStringList { + my $res = ""; + foreach my $s (@_) { + $res .= " \"$s\""; + } + return $res; +} +sub toNixList { + my $res = ""; + foreach my $s (@_) { + $res .= " $s"; + } + return $res; +} + +sub multiLineList { + my $indent = shift; + return " [ ]" if !@_; + my $res = "\n${indent}[ "; + my $first = 1; + foreach my $s (@_) { + $res .= "$indent " if !$first; + $first = 0; + $res .= "$s\n"; + } + $res .= "$indent]"; + return $res; +} + +my $initrdAvailableKernelModules = toNixStringList(uniq @initrdAvailableKernelModules); +my $initrdKernelModules = toNixStringList(uniq @initrdKernelModules); +my $kernelModules = toNixStringList(uniq @kernelModules); +my $modulePackages = toNixList(uniq @modulePackages); + +my $fsAndSwap = ""; +if (!$noFilesystems) { + $fsAndSwap = "\n$fileSystems "; + $fsAndSwap .= "swapDevices =" . multiLineList(" ", @swapDevices) . ";\n"; +} + +my $networkingDhcpConfig = generateNetworkingDhcpConfig(); + +my $hwConfig = <<EOF; +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports =${\multiLineList(" ", @imports)}; + + boot.initrd.availableKernelModules = [$initrdAvailableKernelModules ]; + boot.initrd.kernelModules = [$initrdKernelModules ]; + boot.kernelModules = [$kernelModules ]; + boot.extraModulePackages = [$modulePackages ]; +$fsAndSwap +$networkingDhcpConfig +${\join "", (map { " $_\n" } (uniq @attrs))}} +EOF + +sub generateNetworkingDhcpConfig { + # FIXME disable networking.useDHCP by default when switching to networkd. + my $config = <<EOF; + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. + networking.useDHCP = lib.mkDefault true; +EOF + + foreach my $path (glob "/sys/class/net/*") { + my $dev = basename($path); + if ($dev ne "lo") { + $config .= " # networking.interfaces.$dev.useDHCP = lib.mkDefault true;\n"; + } + } + + return $config; +} + +sub generateXserverConfig { + my $xserverEnabled = "@xserverEnabled@"; + + my $config = ""; + if ($xserverEnabled eq "1") { + $config = <<EOF; + # Enable the X11 windowing system. + services.xserver.enable = true; +EOF + } else { + $config = <<EOF; + # Enable the X11 windowing system. + # services.xserver.enable = true; +EOF + } +} + +if ($showHardwareConfig) { + print STDOUT $hwConfig; +} else { + if ($outDir eq "/etc/nixos") { + $outDir = "$rootDir$outDir"; + } else { + $outDir = File::Spec->rel2abs($outDir); + $outDir =~ s/\/*$//; # remove trailing slashes + } + + my $fn = "$outDir/hardware-configuration.nix"; + print STDERR "writing $fn...\n"; + mkpath($outDir, 0, 0755); + write_file($fn, $hwConfig); + + # Generate a basic configuration.nix, unless one already exists. + $fn = "$outDir/configuration.nix"; + if ($force || ! -e $fn) { + print STDERR "writing $fn...\n"; + + my $bootLoaderConfig = ""; + if (-e "/sys/firmware/efi/efivars") { + $bootLoaderConfig = <<EOF; + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; +EOF + } elsif (-e "/boot/extlinux") { + $bootLoaderConfig = <<EOF; + # Use the extlinux boot loader. (NixOS wants to enable GRUB by default) + boot.loader.grub.enable = false; + # Enables the generation of /boot/extlinux/extlinux.conf + boot.loader.generic-extlinux-compatible.enable = true; +EOF + } elsif ($virt ne "systemd-nspawn") { + $bootLoaderConfig = <<EOF; + # Use the GRUB 2 boot loader. + boot.loader.grub.enable = true; + # boot.loader.grub.efiSupport = true; + # boot.loader.grub.efiInstallAsRemovable = true; + # boot.loader.efi.efiSysMountPoint = "/boot/efi"; + # Define on which hard drive you want to install Grub. + # boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only +EOF + } + + my $networkingDhcpConfig = generateNetworkingDhcpConfig(); + + my $xserverConfig = generateXserverConfig(); + + (my $desktopConfiguration = <<EOF)=~s/^/ /gm; +@desktopConfiguration@ +EOF + + write_file($fn, <<EOF); +@configuration@ +EOF + print STDERR "For more hardware-specific settings, see https://github.com/NixOS/nixos-hardware.\n" + } else { + print STDERR "warning: not overwriting existing $fn\n"; + } +} + +# workaround for a bug in substituteAll diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-install.sh b/nixpkgs/nixos/modules/installer/tools/nixos-install.sh new file mode 100755 index 000000000000..4e42875c0365 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-install.sh @@ -0,0 +1,231 @@ +#! @runtimeShell@ +# shellcheck shell=bash + +set -e +shopt -s nullglob + +export PATH=@path@:$PATH + +# Ensure a consistent umask. +umask 0022 + +# Parse the command line for the -I flag +extraBuildFlags=() +flakeFlags=() + +mountPoint=/mnt +channelPath= +system= +verbosity=() + +while [ "$#" -gt 0 ]; do + i="$1"; shift 1 + case "$i" in + --max-jobs|-j|--cores|-I|--substituters) + j="$1"; shift 1 + extraBuildFlags+=("$i" "$j") + ;; + --option) + j="$1"; shift 1 + k="$1"; shift 1 + extraBuildFlags+=("$i" "$j" "$k") + ;; + --root) + mountPoint="$1"; shift 1 + ;; + --system|--closure) + system="$1"; shift 1 + ;; + --flake) + flake="$1" + flakeFlags=(--experimental-features 'nix-command flakes') + shift 1 + ;; + --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file) + lockFlags+=("$i") + ;; + --update-input) + j="$1"; shift 1 + lockFlags+=("$i" "$j") + ;; + --override-input) + j="$1"; shift 1 + k="$1"; shift 1 + lockFlags+=("$i" "$j" "$k") + ;; + --channel) + channelPath="$1"; shift 1 + ;; + --no-channel-copy) + noChannelCopy=1 + ;; + --no-root-password|--no-root-passwd) + noRootPasswd=1 + ;; + --no-bootloader) + noBootLoader=1 + ;; + --show-trace|--impure|--keep-going) + extraBuildFlags+=("$i") + ;; + --help) + exec man nixos-install + exit 1 + ;; + --debug) + set -x + ;; + -v*|--verbose) + verbosity+=("$i") + ;; + *) + echo "$0: unknown option \`$i'" + exit 1 + ;; + esac +done + +if ! test -e "$mountPoint"; then + echo "mount point $mountPoint doesn't exist" + exit 1 +fi + +# Verify permissions are okay-enough +checkPath="$(realpath "$mountPoint")" +while [[ "$checkPath" != "/" ]]; do + mode="$(stat -c '%a' "$checkPath")" + if [[ "${mode: -1}" -lt "5" ]]; then + echo "path $checkPath should have permissions 755, but had permissions $mode. Consider running 'chmod o+rx $checkPath'." + exit 1 + fi + checkPath="$(dirname "$checkPath")" +done + +# Get the path of the NixOS configuration file. +if [[ -z $NIXOS_CONFIG ]]; then + NIXOS_CONFIG=$mountPoint/etc/nixos/configuration.nix +fi + +if [[ ${NIXOS_CONFIG:0:1} != / ]]; then + echo "$0: \$NIXOS_CONFIG is not an absolute path" + exit 1 +fi + +if [[ -n $flake ]]; then + if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then + flake="${BASH_REMATCH[1]}" + flakeAttr="${BASH_REMATCH[2]}" + fi + if [[ -z "$flakeAttr" ]]; then + echo "Please specify the name of the NixOS configuration to be installed, as a URI fragment in the flake-uri." + echo "For example, to use the output nixosConfigurations.foo from the flake.nix, append \"#foo\" to the flake-uri." + exit 1 + fi + flakeAttr="nixosConfigurations.\"$flakeAttr\"" +fi + +# Resolve the flake. +if [[ -n $flake ]]; then + flake=$(nix "${flakeFlags[@]}" flake metadata --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url) +fi + +if [[ ! -e $NIXOS_CONFIG && -z $system && -z $flake ]]; then + echo "configuration file $NIXOS_CONFIG doesn't exist" + exit 1 +fi + +# A place to drop temporary stuff. +tmpdir="$(mktemp -d -p "$mountPoint")" +trap 'rm -rf $tmpdir' EXIT + +# store temporary files on target filesystem by default +export TMPDIR=${TMPDIR:-$tmpdir} + +sub="auto?trusted=1" + +# Copy the NixOS/Nixpkgs sources to the target as the initial contents +# of the NixOS channel. +if [[ -z $noChannelCopy ]]; then + if [[ -z $channelPath ]]; then + channelPath="$(nix-env -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")" + fi + if [[ -n $channelPath ]]; then + echo "copying channel..." + mkdir -p "$mountPoint"/nix/var/nix/profiles/per-user/root + nix-env --store "$mountPoint" "${extraBuildFlags[@]}" --extra-substituters "$sub" \ + -p "$mountPoint"/nix/var/nix/profiles/per-user/root/channels --set "$channelPath" --quiet \ + "${verbosity[@]}" + install -m 0700 -d "$mountPoint"/root/.nix-defexpr + ln -sfn /nix/var/nix/profiles/per-user/root/channels "$mountPoint"/root/.nix-defexpr/channels + fi +fi + +# Build the system configuration in the target filesystem. +if [[ -z $system ]]; then + outLink="$tmpdir/system" + if [[ -z $flake ]]; then + echo "building the configuration in $NIXOS_CONFIG..." + nix-build --out-link "$outLink" --store "$mountPoint" "${extraBuildFlags[@]}" \ + --extra-substituters "$sub" \ + '<nixpkgs/nixos>' -A system -I "nixos-config=$NIXOS_CONFIG" "${verbosity[@]}" + else + echo "building the flake in $flake..." + nix "${flakeFlags[@]}" build "$flake#$flakeAttr.config.system.build.toplevel" \ + --store "$mountPoint" --extra-substituters "$sub" "${verbosity[@]}" \ + "${extraBuildFlags[@]}" "${lockFlags[@]}" --out-link "$outLink" + fi + system=$(readlink -f "$outLink") +fi + +# Set the system profile to point to the configuration. TODO: combine +# this with the previous step once we have a nix-env replacement with +# a progress bar. +nix-env --store "$mountPoint" "${extraBuildFlags[@]}" \ + --extra-substituters "$sub" \ + -p "$mountPoint"/nix/var/nix/profiles/system --set "$system" "${verbosity[@]}" + +# Mark the target as a NixOS installation, otherwise switch-to-configuration will chicken out. +mkdir -m 0755 -p "$mountPoint/etc" +touch "$mountPoint/etc/NIXOS" + +# Switch to the new system configuration. This will install Grub with +# a menu default pointing at the kernel/initrd/etc of the new +# configuration. +if [[ -z $noBootLoader ]]; then + echo "installing the boot loader..." + # Grub needs an mtab. + ln -sfn /proc/mounts "$mountPoint"/etc/mtab + export mountPoint + NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root "$mountPoint" -c "$(cat <<'EOF' + # Create a bind mount for each of the mount points inside the target file + # system. This preserves the validity of their absolute paths after changing + # the root with `nixos-enter`. + # Without this the bootloader installation may fail due to options that + # contain paths referenced during evaluation, like initrd.secrets. + # when not root, re-execute the script in an unshared namespace + mount --rbind --mkdir / "$mountPoint" + mount --make-rslave "$mountPoint" + /run/current-system/bin/switch-to-configuration boot + umount -R "$mountPoint" && (rmdir "$mountPoint" 2>/dev/null || true) +EOF +)" +fi + +# Ask the user to set a root password, but only if the passwd command +# exists (i.e. when mutable user accounts are enabled). +if [[ -z $noRootPasswd ]] && [ -t 0 ]; then + if nixos-enter --root "$mountPoint" -c 'test -e /nix/var/nix/profiles/system/sw/bin/passwd'; then + set +e + nixos-enter --root "$mountPoint" -c 'echo "setting root password..." && /nix/var/nix/profiles/system/sw/bin/passwd' + exit_code=$? + set -e + + if [[ $exit_code != 0 ]]; then + echo "Setting a root password failed with the above printed error." + echo "You can set the root password manually by executing \`nixos-enter --root ${mountPoint@Q}\` and then running \`passwd\` in the shell of the new system." + exit $exit_code + fi + fi +fi + +echo "installation finished!" diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-version.sh b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh new file mode 100644 index 000000000000..39e34a3718cb --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh @@ -0,0 +1,31 @@ +#! @runtimeShell@ +# shellcheck shell=bash + +case "$1" in + -h|--help) + exec man nixos-version + exit 1 + ;; + --hash|--revision) + if ! [[ @revision@ =~ ^[0-9a-f]+$ ]]; then + echo "$0: Nixpkgs commit hash is unknown" >&2 + exit 1 + fi + echo "@revision@" + ;; + --configuration-revision) + if [[ "@configurationRevision@" =~ "@" ]]; then + echo "$0: configuration revision is unknown" >&2 + exit 1 + fi + echo "@configurationRevision@" + ;; + --json) + cat <<EOF +@json@ +EOF + ;; + *) + echo "@version@ (@codeName@)" + ;; +esac diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix new file mode 100644 index 000000000000..15e10128ac9a --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/tools.nix @@ -0,0 +1,266 @@ +# This module generates nixos-install, nixos-rebuild, +# nixos-generate-config, etc. + +{ config, lib, pkgs, ... }: + +with lib; + +let + makeProg = args: pkgs.substituteAll (args // { + dir = "bin"; + isExecutable = true; + nativeBuildInputs = [ + pkgs.installShellFiles + ]; + postInstall = '' + installManPage ${args.manPage} + ''; + }); + + nixos-build-vms = makeProg { + name = "nixos-build-vms"; + src = ./nixos-build-vms/nixos-build-vms.sh; + inherit (pkgs) runtimeShell; + manPage = ./manpages/nixos-build-vms.8; + }; + + nixos-install = makeProg { + name = "nixos-install"; + src = ./nixos-install.sh; + inherit (pkgs) runtimeShell; + nix = config.nix.package.out; + path = makeBinPath [ + pkgs.jq + nixos-enter + pkgs.util-linuxMinimal + ]; + manPage = ./manpages/nixos-install.8; + }; + + nixos-rebuild = pkgs.nixos-rebuild.override { nix = config.nix.package.out; }; + + nixos-generate-config = makeProg { + name = "nixos-generate-config"; + src = ./nixos-generate-config.pl; + perl = "${pkgs.perl.withPackages (p: [ p.FileSlurp ])}/bin/perl"; + hostPlatformSystem = pkgs.stdenv.hostPlatform.system; + detectvirt = "${config.systemd.package}/bin/systemd-detect-virt"; + btrfs = "${pkgs.btrfs-progs}/bin/btrfs"; + inherit (config.system.nixos-generate-config) configuration desktopConfiguration; + xserverEnabled = config.services.xserver.enable; + manPage = ./manpages/nixos-generate-config.8; + }; + + inherit (pkgs) nixos-option; + + nixos-version = makeProg { + name = "nixos-version"; + src = ./nixos-version.sh; + inherit (pkgs) runtimeShell; + inherit (config.system.nixos) version codeName revision; + inherit (config.system) configurationRevision; + json = builtins.toJSON ({ + nixosVersion = config.system.nixos.version; + } // optionalAttrs (config.system.nixos.revision != null) { + nixpkgsRevision = config.system.nixos.revision; + } // optionalAttrs (config.system.configurationRevision != null) { + configurationRevision = config.system.configurationRevision; + }); + manPage = ./manpages/nixos-version.8; + }; + + nixos-enter = makeProg { + name = "nixos-enter"; + src = ./nixos-enter.sh; + inherit (pkgs) runtimeShell; + path = makeBinPath [ + pkgs.util-linuxMinimal + ]; + manPage = ./manpages/nixos-enter.8; + }; + +in + +{ + + options.system.nixos-generate-config = { + configuration = mkOption { + internal = true; + type = types.str; + description = lib.mdDoc '' + The NixOS module that `nixos-generate-config` + saves to `/etc/nixos/configuration.nix`. + + This is an internal option. No backward compatibility is guaranteed. + Use at your own risk! + + Note that this string gets spliced into a Perl script. The perl + variable `$bootLoaderConfig` can be used to + splice in the boot loader configuration. + ''; + }; + + desktopConfiguration = mkOption { + internal = true; + type = types.listOf types.lines; + default = []; + description = lib.mdDoc '' + Text to preseed the desktop configuration that `nixos-generate-config` + saves to `/etc/nixos/configuration.nix`. + + This is an internal option. No backward compatibility is guaranteed. + Use at your own risk! + + Note that this string gets spliced into a Perl script. The perl + variable `$bootLoaderConfig` can be used to + splice in the boot loader configuration. + ''; + }; + }; + + options.system.disableInstallerTools = mkOption { + internal = true; + type = types.bool; + default = false; + description = lib.mdDoc '' + Disable nixos-rebuild, nixos-generate-config, nixos-installer + and other NixOS tools. This is useful to shrink embedded, + read-only systems which are not expected to be rebuild or + reconfigure themselves. Use at your own risk! + ''; + }; + + config = lib.mkIf (config.nix.enable && !config.system.disableInstallerTools) { + + system.nixos-generate-config.configuration = mkDefault '' + # Edit this configuration file to define what should be installed on + # your system. Help is available in the configuration.nix(5) man page, on + # https://search.nixos.org/options and in the NixOS manual (`nixos-help`). + + { config, lib, pkgs, ... }: + + { + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + $bootLoaderConfig + # networking.hostName = "nixos"; # Define your hostname. + # Pick only one of the below networking options. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + # networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. + + # Set your time zone. + # time.timeZone = "Europe/Amsterdam"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password\@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + # i18n.defaultLocale = "en_US.UTF-8"; + # console = { + # font = "Lat2-Terminus16"; + # keyMap = "us"; + # useXkbConfig = true; # use xkb.options in tty. + # }; + + $xserverConfig + + $desktopConfiguration + # Configure keymap in X11 + # services.xserver.xkb.layout = "us"; + # services.xserver.xkb.options = "eurosign:e,caps:escape"; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; + + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + + # Define a user account. Don't forget to set a password with ‘passwd’. + # users.users.alice = { + # isNormalUser = true; + # extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + # packages = with pkgs; [ + # firefox + # tree + # ]; + # }; + + # List packages installed in system profile. To search, run: + # \$ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system. + # + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "${config.system.nixos.release}"; # Did you read the comment? + + } + ''; + + environment.systemPackages = + [ nixos-build-vms + nixos-install + nixos-rebuild + nixos-generate-config + nixos-option + nixos-version + nixos-enter + ]; + + documentation.man.man-db.skipPackages = [ nixos-version ]; + + system.build = { + inherit nixos-install nixos-generate-config nixos-option nixos-rebuild nixos-enter; + }; + + }; + +} |