at 17.09-beta 8.1 kB view raw
1{ config, lib, pkgs, modules, baseModules, ... }: 2 3with lib; 4 5let 6 7 8 # This attribute is responsible for creating boot entries for 9 # child configuration. They are only (directly) accessible 10 # when the parent configuration is boot default. For example, 11 # you can provide an easy way to boot the same configuration 12 # as you use, but with another kernel 13 # !!! fix this 14 cloner = inheritParent: list: 15 map (childConfig: 16 (import ../../../lib/eval-config.nix { 17 inherit baseModules; 18 modules = 19 (optionals inheritParent modules) 20 ++ [ ./no-clone.nix ] 21 ++ [ childConfig ]; 22 }).config.system.build.toplevel 23 ) list; 24 25 children = 26 cloner false config.nesting.children 27 ++ cloner true config.nesting.clone; 28 29 30 systemBuilder = 31 let 32 kernelPath = "${config.boot.kernelPackages.kernel}/" + 33 "${config.system.boot.loader.kernelFile}"; 34 in '' 35 mkdir $out 36 37 # Containers don't have their own kernel or initrd. They boot 38 # directly into stage 2. 39 ${optionalString (!config.boot.isContainer) '' 40 if [ ! -f ${kernelPath} ]; then 41 echo "The bootloader cannot find the proper kernel image." 42 echo "(Expecting ${kernelPath})" 43 false 44 fi 45 46 ln -s ${kernelPath} $out/kernel 47 ln -s ${config.system.modulesTree} $out/kernel-modules 48 ${optionalString (pkgs.stdenv.platform.kernelDTB or false) '' 49 ln -s ${config.boot.kernelPackages.kernel}/dtbs $out/dtbs 50 ''} 51 52 echo -n "$kernelParams" > $out/kernel-params 53 54 ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd 55 56 ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out 57 58 ln -s ${config.hardware.firmware}/lib/firmware $out/firmware 59 ''} 60 61 echo "$activationScript" > $out/activate 62 substituteInPlace $out/activate --subst-var out 63 chmod u+x $out/activate 64 unset activationScript 65 66 cp ${config.system.build.bootStage2} $out/init 67 substituteInPlace $out/init --subst-var-by systemConfig $out 68 69 ln -s ${config.system.build.etc}/etc $out/etc 70 ln -s ${config.system.path} $out/sw 71 ln -s "$systemd" $out/systemd 72 73 echo -n "$configurationName" > $out/configuration-name 74 echo -n "systemd ${toString config.systemd.package.interfaceVersion}" > $out/init-interface-version 75 echo -n "$nixosLabel" > $out/nixos-version 76 echo -n "$system" > $out/system 77 78 mkdir $out/fine-tune 79 childCount=0 80 for i in $children; do 81 childCount=$(( childCount + 1 )) 82 ln -s $i $out/fine-tune/child-$childCount 83 done 84 85 mkdir $out/bin 86 substituteAll ${./switch-to-configuration.pl} $out/bin/switch-to-configuration 87 chmod +x $out/bin/switch-to-configuration 88 89 echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies 90 91 ${config.system.extraSystemBuilderCmds} 92 ''; 93 94 # Handle assertions 95 96 failed = map (x: x.message) (filter (x: !x.assertion) config.assertions); 97 98 showWarnings = res: fold (w: x: builtins.trace "warning: ${w}" x) res config.warnings; 99 100 # Putting it all together. This builds a store path containing 101 # symlinks to the various parts of the built configuration (the 102 # kernel, systemd units, init scripts, etc.) as well as a script 103 # `switch-to-configuration' that activates the configuration and 104 # makes it bootable. 105 baseSystem = showWarnings ( 106 if [] == failed then pkgs.stdenvNoCC.mkDerivation { 107 name = let hn = config.networking.hostName; 108 nn = if (hn != "") then hn else "unnamed"; 109 in "nixos-system-${nn}-${config.system.nixosLabel}"; 110 preferLocalBuild = true; 111 allowSubstitutes = false; 112 buildCommand = systemBuilder; 113 114 inherit (pkgs) utillinux coreutils; 115 systemd = config.systemd.package; 116 117 inherit children; 118 kernelParams = config.boot.kernelParams; 119 installBootLoader = 120 config.system.build.installBootLoader 121 or "echo 'Warning: do not know how to make this configuration bootable; please enable a boot loader.' 1>&2; true"; 122 activationScript = config.system.activationScripts.script; 123 nixosLabel = config.system.nixosLabel; 124 125 configurationName = config.boot.loader.grub.configurationName; 126 127 # Needed by switch-to-configuration. 128 perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl"; 129 } else throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failed)}"); 130 131 # Replace runtime dependencies 132 system = fold ({ oldDependency, newDependency }: drv: 133 pkgs.replaceDependency { inherit oldDependency newDependency drv; } 134 ) baseSystem config.system.replaceRuntimeDependencies; 135 136in 137 138{ 139 options = { 140 141 system.build = mkOption { 142 internal = true; 143 default = {}; 144 type = types.attrs; 145 description = '' 146 Attribute set of derivations used to setup the system. 147 ''; 148 }; 149 150 nesting.children = mkOption { 151 default = []; 152 description = '' 153 Additional configurations to build. 154 ''; 155 }; 156 157 nesting.clone = mkOption { 158 default = []; 159 description = '' 160 Additional configurations to build based on the current 161 configuration which then has a lower priority. 162 ''; 163 }; 164 165 system.boot.loader.id = mkOption { 166 internal = true; 167 default = ""; 168 description = '' 169 Id string of the used bootloader. 170 ''; 171 }; 172 173 system.boot.loader.kernelFile = mkOption { 174 internal = true; 175 default = pkgs.stdenv.platform.kernelTarget; 176 type = types.str; 177 description = '' 178 Name of the kernel file to be passed to the bootloader. 179 ''; 180 }; 181 182 system.copySystemConfiguration = mkOption { 183 type = types.bool; 184 default = false; 185 description = '' 186 If enabled, copies the NixOS configuration file 187 (usually <filename>/etc/nixos/configuration.nix</filename>) 188 and links it from the resulting system 189 (getting to <filename>/run/current-system/configuration.nix</filename>). 190 Note that only this single file is copied, even if it imports others. 191 ''; 192 }; 193 194 system.extraSystemBuilderCmds = mkOption { 195 type = types.lines; 196 internal = true; 197 default = ""; 198 description = '' 199 This code will be added to the builder creating the system store path. 200 ''; 201 }; 202 203 system.extraDependencies = mkOption { 204 type = types.listOf types.package; 205 default = []; 206 description = '' 207 A list of packages that should be included in the system 208 closure but not otherwise made available to users. This is 209 primarily used by the installation tests. 210 ''; 211 }; 212 213 system.replaceRuntimeDependencies = mkOption { 214 default = []; 215 example = lib.literalExample "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { }; }) ]"; 216 type = types.listOf (types.submodule ( 217 { options, ... }: { 218 options.original = mkOption { 219 type = types.package; 220 description = "The original package to override."; 221 }; 222 223 options.replacement = mkOption { 224 type = types.package; 225 description = "The replacement package."; 226 }; 227 }) 228 ); 229 apply = map ({ original, replacement, ... }: { 230 oldDependency = original; 231 newDependency = replacement; 232 }); 233 description = '' 234 List of packages to override without doing a full rebuild. 235 The original derivation and replacement derivation must have the same 236 name length, and ideally should have close-to-identical directory layout. 237 ''; 238 }; 239 240 }; 241 242 243 config = { 244 245 system.extraSystemBuilderCmds = 246 optionalString 247 config.system.copySystemConfiguration 248 ''ln -s '${import ../../../lib/from-env.nix "NIXOS_CONFIG" <nixos-config>}' \ 249 "$out/configuration.nix" 250 ''; 251 252 system.build.toplevel = system; 253 254 }; 255 256}