at 15.09-beta 7.5 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 49 echo -n "$kernelParams" > $out/kernel-params 50 51 ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd 52 53 ln -s ${config.hardware.firmware}/lib/firmware $out/firmware 54 ''} 55 56 echo "$activationScript" > $out/activate 57 substituteInPlace $out/activate --subst-var out 58 chmod u+x $out/activate 59 unset activationScript 60 61 cp ${config.system.build.bootStage2} $out/init 62 substituteInPlace $out/init --subst-var-by systemConfig $out 63 64 ln -s ${config.system.build.etc}/etc $out/etc 65 ln -s ${config.system.path} $out/sw 66 ln -s "$systemd" $out/systemd 67 68 echo -n "$configurationName" > $out/configuration-name 69 echo -n "systemd ${toString config.systemd.package.interfaceVersion}" > $out/init-interface-version 70 echo -n "$nixosVersion" > $out/nixos-version 71 echo -n "$system" > $out/system 72 73 mkdir $out/fine-tune 74 childCount=0 75 for i in $children; do 76 childCount=$(( childCount + 1 )) 77 ln -s $i $out/fine-tune/child-$childCount 78 done 79 80 mkdir $out/bin 81 substituteAll ${./switch-to-configuration.pl} $out/bin/switch-to-configuration 82 chmod +x $out/bin/switch-to-configuration 83 84 echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies 85 86 ${config.system.extraSystemBuilderCmds} 87 ''; 88 89 # Handle assertions 90 91 failed = map (x: x.message) (filter (x: !x.assertion) config.assertions); 92 93 showWarnings = res: fold (w: x: builtins.trace "warning: ${w}" x) res config.warnings; 94 95 # Putting it all together. This builds a store path containing 96 # symlinks to the various parts of the built configuration (the 97 # kernel, systemd units, init scripts, etc.) as well as a script 98 # `switch-to-configuration' that activates the configuration and 99 # makes it bootable. 100 baseSystem = showWarnings ( 101 if [] == failed then pkgs.stdenv.mkDerivation { 102 name = "nixos-${config.system.nixosVersion}"; 103 preferLocalBuild = true; 104 allowSubstitutes = false; 105 buildCommand = systemBuilder; 106 107 inherit (pkgs) utillinux coreutils; 108 systemd = config.systemd.package; 109 110 inherit children; 111 kernelParams = config.boot.kernelParams; 112 installBootLoader = 113 config.system.build.installBootLoader 114 or "echo 'Warning: do not know how to make this configuration bootable; please enable a boot loader.' 1>&2; true"; 115 activationScript = config.system.activationScripts.script; 116 nixosVersion = config.system.nixosVersion; 117 118 configurationName = config.boot.loader.grub.configurationName; 119 120 # Needed by switch-to-configuration. 121 perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl"; 122 } else throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failed)}"); 123 124 # Replace runtime dependencies 125 system = fold ({ oldDependency, newDependency }: drv: 126 pkgs.replaceDependency { inherit oldDependency newDependency drv; } 127 ) baseSystem config.system.replaceRuntimeDependencies; 128 129in 130 131{ 132 options = { 133 134 system.build = mkOption { 135 internal = true; 136 default = {}; 137 description = '' 138 Attribute set of derivations used to setup the system. 139 ''; 140 }; 141 142 nesting.children = mkOption { 143 default = []; 144 description = '' 145 Additional configurations to build. 146 ''; 147 }; 148 149 nesting.clone = mkOption { 150 default = []; 151 description = '' 152 Additional configurations to build based on the current 153 configuration which then has a lower priority. 154 ''; 155 }; 156 157 system.boot.loader.id = mkOption { 158 internal = true; 159 default = ""; 160 description = '' 161 Id string of the used bootloader. 162 ''; 163 }; 164 165 system.boot.loader.kernelFile = mkOption { 166 internal = true; 167 default = pkgs.stdenv.platform.kernelTarget; 168 type = types.str; 169 description = '' 170 Name of the kernel file to be passed to the bootloader. 171 ''; 172 }; 173 174 system.copySystemConfiguration = mkOption { 175 type = types.bool; 176 default = false; 177 description = '' 178 If enabled, copies the NixOS configuration file 179 <literal>$NIXOS_CONFIG</literal> (usually 180 <filename>/etc/nixos/configuration.nix</filename>) 181 to the system store path. 182 ''; 183 }; 184 185 system.extraSystemBuilderCmds = mkOption { 186 type = types.lines; 187 internal = true; 188 default = ""; 189 description = '' 190 This code will be added to the builder creating the system store path. 191 ''; 192 }; 193 194 system.extraDependencies = mkOption { 195 type = types.listOf types.package; 196 default = []; 197 description = '' 198 A list of packages that should be included in the system 199 closure but not otherwise made available to users. This is 200 primarily used by the installation tests. 201 ''; 202 }; 203 204 system.replaceRuntimeDependencies = mkOption { 205 default = []; 206 example = lib.literalExample "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { ... }; }) ]"; 207 type = types.listOf (types.submodule ( 208 { options, ... }: { 209 options.original = mkOption { 210 type = types.package; 211 description = "The original package to override."; 212 }; 213 214 options.replacement = mkOption { 215 type = types.package; 216 description = "The replacement package."; 217 }; 218 }) 219 ); 220 apply = map ({ original, replacement, ... }: { 221 oldDependency = original; 222 newDependency = replacement; 223 }); 224 description = '' 225 List of packages to override without doing a full rebuild. 226 The original derivation and replacement derivation must have the same 227 name length, and ideally should have close-to-identical directory layout. 228 ''; 229 }; 230 231 }; 232 233 234 config = { 235 236 system.extraSystemBuilderCmds = 237 optionalString 238 config.system.copySystemConfiguration 239 "cp ${maybeEnv "NIXOS_CONFIG" "/etc/nixos/configuration.nix"} $out"; 240 241 system.build.toplevel = system; 242 243 }; 244 245}