at 25.11-pre 24 kB view raw
1#! @perl@ 2 3use strict; 4use Cwd 'abs_path'; 5use File::Spec; 6use File::Path; 7use File::Basename; 8use File::Slurp; 9use File::stat; 10use Config::IniFiles; 11 12umask(0022); 13 14sub uniq { 15 my %seen; 16 my @res = (); 17 foreach my $s (@_) { 18 if (!defined $seen{$s}) { 19 $seen{$s} = 1; 20 push @res, $s; 21 } 22 } 23 return @res; 24} 25 26sub runCommand { 27 my ($cmd) = @_; 28 open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n"; 29 my @ret = <FILE>; 30 close FILE; 31 return ($?, @ret); 32} 33 34# Process the command line. 35my $outDir = "/etc/nixos"; 36my $rootDir = ""; # = / 37my $force = 0; 38my $noFilesystems = 0; 39my $flake = 0; 40my $showHardwareConfig = 0; 41my $kernel = "lts"; 42 43if (-e "/etc/nixos-generate-config.conf") { 44 my $cfg = new Config::IniFiles -file => "/etc/nixos-generate-config.conf"; 45 $outDir = $cfg->val("Defaults", "Directory") // $outDir; 46 if (defined $cfg->val("Defaults", "RootDirectory")) { 47 $rootDir = $cfg->val("Defaults", "RootDirectory"); 48 $rootDir =~ s/\/*$//; # remove trailing slashes 49 $rootDir = File::Spec->rel2abs($rootDir); # resolve absolute path 50 } 51 $kernel = $cfg->val("Defaults", "Kernel") // $kernel; 52} 53 54for (my $n = 0; $n < scalar @ARGV; $n++) { 55 my $arg = $ARGV[$n]; 56 if ($arg eq "--help") { 57 exec "man nixos-generate-config" or die; 58 } 59 elsif ($arg eq "--dir") { 60 $n++; 61 $outDir = $ARGV[$n]; 62 die "$0: ‘--dir’ requires an argument\n" unless defined $outDir; 63 } 64 elsif ($arg eq "--root") { 65 $n++; 66 $rootDir = $ARGV[$n]; 67 die "$0: ‘--root’ requires an argument\n" unless defined $rootDir; 68 die "$0: no need to specify `/` with `--root`, it is the default\n" if $rootDir eq "/"; 69 $rootDir =~ s/\/*$//; # remove trailing slashes 70 $rootDir = File::Spec->rel2abs($rootDir); # resolve absolute path 71 } 72 elsif ($arg eq "--force") { 73 $force = 1; 74 } 75 elsif ($arg eq "--no-filesystems") { 76 $noFilesystems = 1; 77 } 78 elsif ($arg eq "--show-hardware-config") { 79 $showHardwareConfig = 1; 80 } 81 elsif ($arg eq "--flake") { 82 $flake = 1; 83 } 84 elsif ($arg eq "--kernel") { 85 $n++; 86 $kernel = $ARGV[$n]; 87 die "$0: ‘--kernel’ requires an argument\n" unless defined $kernel; 88 } 89 else { 90 die "$0: unrecognized argument ‘$arg’\n"; 91 } 92} 93 94die "$0: invalid kernel: '$kernel'" unless $kernel eq "lts" || $kernel eq "latest"; 95 96my @attrs = (); 97my @kernelModules = (); 98my @initrdKernelModules = (); 99my @initrdAvailableKernelModules = (); 100my @modulePackages = (); 101my @imports; 102 103 104sub debug { 105 return unless defined $ENV{"DEBUG"}; 106 print STDERR @_; 107} 108 109 110# nixpkgs.system 111push @attrs, "nixpkgs.hostPlatform = lib.mkDefault \"@hostPlatformSystem@\";"; 112 113 114my $cpuinfo = read_file "/proc/cpuinfo"; 115 116 117sub hasCPUFeature { 118 my $feature = shift; 119 return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m; 120} 121 122 123sub cpuManufacturer { 124 my $id = shift; 125 return $cpuinfo =~ /^vendor_id\s*:.* $id$/m; 126} 127 128# Virtualization support? 129push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; 130push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; 131 132 133# Look at the PCI devices and add necessary modules. Note that most 134# modules are auto-detected so we don't need to list them here. 135# However, some are needed in the initrd to boot the system. 136 137my $videoDriver; 138 139sub pciCheck { 140 my $path = shift; 141 my $vendor = read_file "$path/vendor"; chomp $vendor; 142 my $device = read_file "$path/device"; chomp $device; 143 my $class = read_file "$path/class"; chomp $class; 144 145 my $module; 146 if (-e "$path/driver/module") { 147 $module = basename `readlink -f $path/driver/module`; 148 chomp $module; 149 } 150 151 debug "$path: $vendor $device $class"; 152 debug " $module" if defined $module; 153 debug "\n"; 154 155 if (defined $module) { 156 # See the bottom of https://pciids.sourceforge.net/pci.ids for 157 # device classes. 158 if (# Mass-storage controller. Definitely important. 159 $class =~ /^0x01/ || 160 161 # Firewire controller. A disk might be attached. 162 $class =~ /^0x0c00/ || 163 164 # USB controller. Needed if we want to use the 165 # keyboard when things go wrong in the initrd. 166 $class =~ /^0x0c03/ 167 ) 168 { 169 push @initrdAvailableKernelModules, $module; 170 } 171 } 172 173 # broadcom STA driver (wl.ko) 174 # list taken from http://www.broadcom.com/docs/linux_sta/README.txt 175 if ($vendor eq "0x14e4" && 176 ($device eq "0x4311" || $device eq "0x4312" || $device eq "0x4313" || 177 $device eq "0x4315" || $device eq "0x4327" || $device eq "0x4328" || 178 $device eq "0x4329" || $device eq "0x432a" || $device eq "0x432b" || 179 $device eq "0x432c" || $device eq "0x432d" || $device eq "0x4353" || 180 $device eq "0x4357" || $device eq "0x4358" || $device eq "0x4359" || 181 $device eq "0x4331" || $device eq "0x43a0" || $device eq "0x43b1" 182 ) ) 183 { 184 push @modulePackages, "config.boot.kernelPackages.broadcom_sta"; 185 push @kernelModules, "wl"; 186 } 187 188 # broadcom FullMac driver 189 # list taken from 190 # https://wireless.wiki.kernel.org/en/users/Drivers/brcm80211#brcmfmac 191 if ($vendor eq "0x14e4" && 192 ($device eq "0x43a3" || $device eq "0x43df" || $device eq "0x43ec" || 193 $device eq "0x43d3" || $device eq "0x43d9" || $device eq "0x43e9" || 194 $device eq "0x43ba" || $device eq "0x43bb" || $device eq "0x43bc" || 195 $device eq "0xaa52" || $device eq "0x43ca" || $device eq "0x43cb" || 196 $device eq "0x43cc" || $device eq "0x43c3" || $device eq "0x43c4" || 197 $device eq "0x43c5" 198 ) ) 199 { 200 # we need e.g. brcmfmac43602-pcie.bin 201 push @imports, "(modulesPath + \"/hardware/network/broadcom-43xx.nix\")"; 202 } 203 204 # In case this is a virtio scsi device, we need to explicitly make this available. 205 if ($vendor eq "0x1af4" && ($device eq "0x1004" || $device eq "0x1048") ) { 206 push @initrdAvailableKernelModules, "virtio_scsi"; 207 } 208 209 # Can't rely on $module here, since the module may not be loaded 210 # due to missing firmware. Ideally we would check modules.pcimap 211 # here. 212 push @attrs, "networking.enableIntel2200BGFirmware = true;" if 213 $vendor eq "0x8086" && 214 ($device eq "0x1043" || $device eq "0x104f" || $device eq "0x4220" || 215 $device eq "0x4221" || $device eq "0x4223" || $device eq "0x4224"); 216 217 push @attrs, "networking.enableIntel3945ABGFirmware = true;" if 218 $vendor eq "0x8086" && 219 ($device eq "0x4229" || $device eq "0x4230" || 220 $device eq "0x4222" || $device eq "0x4227"); 221 222 # Assume that all NVIDIA cards are supported by the NVIDIA driver. 223 # There may be exceptions (e.g. old cards). 224 # FIXME: do we want to enable an unfree driver here? 225 #$videoDriver = "nvidia" if $vendor eq "0x10de" && $class =~ /^0x03/; 226} 227 228foreach my $path (glob "/sys/bus/pci/devices/*") { 229 pciCheck $path; 230} 231 232# Idem for USB devices. 233 234sub usbCheck { 235 my $path = shift; 236 my $class = read_file "$path/bInterfaceClass"; chomp $class; 237 my $subclass = read_file "$path/bInterfaceSubClass"; chomp $subclass; 238 my $protocol = read_file "$path/bInterfaceProtocol"; chomp $protocol; 239 240 my $module; 241 if (-e "$path/driver/module") { 242 $module = basename `readlink -f $path/driver/module`; 243 chomp $module; 244 } 245 246 debug "$path: $class $subclass $protocol"; 247 debug " $module" if defined $module; 248 debug "\n"; 249 250 if (defined $module) { 251 if (# Mass-storage controller. Definitely important. 252 $class eq "08" || 253 254 # Keyboard. Needed if we want to use the 255 # keyboard when things go wrong in the initrd. 256 ($class eq "03" && $protocol eq "01") 257 ) 258 { 259 push @initrdAvailableKernelModules, $module; 260 } 261 } 262} 263 264foreach my $path (glob "/sys/bus/usb/devices/*") { 265 if (-e "$path/bInterfaceClass") { 266 usbCheck $path; 267 } 268} 269 270 271# Add the modules for all block and MMC devices. 272foreach my $path (glob "/sys/class/{block,mmc_host}/*") { 273 my $module; 274 if (-e "$path/device/driver/module") { 275 $module = basename `readlink -f $path/device/driver/module`; 276 chomp $module; 277 push @initrdAvailableKernelModules, $module; 278 } 279} 280 281# Add bcache module, if needed. 282my @bcacheDevices = glob("/dev/bcache*"); 283@bcacheDevices = grep(!m#dev/bcachefs.*#, @bcacheDevices); 284if (scalar @bcacheDevices > 0) { 285 push @initrdAvailableKernelModules, "bcache"; 286} 287 288# Prevent unbootable systems if LVM snapshots are present at boot time. 289if (`lsblk -o TYPE` =~ "lvm") { 290 push @initrdKernelModules, "dm-snapshot"; 291} 292 293my $virt = `@detectvirt@`; 294chomp $virt; 295 296 297# Check if we're a VirtualBox guest. If so, enable the guest 298# additions. 299if ($virt eq "oracle") { 300 push @attrs, "virtualisation.virtualbox.guest.enable = true;" 301} 302 303# Check if we're a Parallels guest. If so, enable the guest additions. 304# It is blocked by https://github.com/systemd/systemd/pull/23859 305if ($virt eq "parallels") { 306 push @attrs, "hardware.parallels.enable = true;"; 307 push @attrs, "nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ \"prl-tools\" ];"; 308} 309 310# Likewise for QEMU. 311if ($virt eq "qemu" || $virt eq "kvm" || $virt eq "bochs") { 312 push @imports, "(modulesPath + \"/profiles/qemu-guest.nix\")"; 313} 314 315# Also for Hyper-V. 316if ($virt eq "microsoft") { 317 push @attrs, "virtualisation.hypervGuest.enable = true;" 318} 319 320 321# Pull in NixOS configuration for containers. 322if ($virt eq "systemd-nspawn") { 323 push @attrs, "boot.isContainer = true;"; 324} 325 326 327# Check if we're on bare metal, not in a VM/container. 328if ($virt eq "none") { 329 # Provide firmware for devices that are not detected by this script. 330 push @imports, "(modulesPath + \"/installer/scan/not-detected.nix\")"; 331 332 # Update the microcode. 333 push @attrs, "hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "AuthenticAMD"; 334 push @attrs, "hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "GenuineIntel"; 335} 336 337# For a device name like /dev/sda1, find a more stable path like 338# /dev/disk/by-uuid/X or /dev/disk/by-label/Y. 339sub findStableDevPath { 340 my ($dev) = @_; 341 return $dev if substr($dev, 0, 1) ne "/"; 342 return $dev unless -e $dev; 343 344 my $st = stat($dev) or return $dev; 345 346 foreach my $dev2 (glob("/dev/stratis/*/*"), glob("/dev/disk/by-uuid/*"), glob("/dev/mapper/*"), glob("/dev/disk/by-label/*")) { 347 my $st2 = stat($dev2) or next; 348 return $dev2 if $st->rdev == $st2->rdev; 349 } 350 351 return $dev; 352} 353 354push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];" if $videoDriver; 355 356# Generate the swapDevices option from the currently activated swap 357# devices. 358my @swaps = read_file("/proc/swaps", err_mode => 'carp'); 359my @swapDevices; 360if (@swaps) { 361 shift @swaps; 362 foreach my $swap (@swaps) { 363 my @fields = split ' ', $swap; 364 my $swapFilename = $fields[0]; 365 my $swapType = $fields[1]; 366 next unless -e $swapFilename; 367 my $dev = findStableDevPath $swapFilename; 368 if ($swapType =~ "partition") { 369 # zram devices are more likely created by configuration.nix, so 370 # ignore them here 371 next if ($swapFilename =~ /^\/dev\/zram/); 372 push @swapDevices, "{ device = \"$dev\"; }"; 373 } elsif ($swapType =~ "file") { 374 # swap *files* are more likely specified in configuration.nix, so 375 # ignore them here. 376 } else { 377 die "Unsupported swap type: $swapType\n"; 378 } 379 } 380} 381 382 383# Generate the fileSystems option from the currently mounted 384# filesystems. 385sub in { 386 my ($d1, $d2) = @_; 387 return $d1 eq $d2 || substr($d1, 0, length($d2) + 1) eq "$d2/"; 388} 389 390my $fileSystems; 391my %fsByDev; 392my $useSwraid = 0; 393foreach my $fs (read_file("/proc/self/mountinfo")) { 394 chomp $fs; 395 my @fields = split / /, $fs; 396 my $mountPoint = $fields[4]; 397 $mountPoint =~ s/\\040/ /g; # account for mount points with spaces in the name (\040 is the escape character) 398 $mountPoint =~ s/\\011/\t/g; # account for mount points with tabs in the name (\011 is the escape character) 399 next unless -d $mountPoint; 400 my @mountOptions = split /,/, $fields[5]; 401 402 next if !in($mountPoint, $rootDir); 403 $mountPoint = substr($mountPoint, length($rootDir)); # strip the root directory (e.g. /mnt) 404 $mountPoint = "/" if $mountPoint eq ""; 405 406 # Skip special filesystems. 407 next if in($mountPoint, "/proc") || in($mountPoint, "/dev") || in($mountPoint, "/sys") || in($mountPoint, "/run") || $mountPoint eq "/var/lib/nfs/rpc_pipefs"; 408 409 # Skip the optional fields. 410 my $n = 6; $n++ while $fields[$n] ne "-"; $n++; 411 my $fsType = $fields[$n]; 412 my $device = $fields[$n + 1]; 413 my @superOptions = split /,/, $fields[$n + 2]; 414 $device =~ s/\\040/ /g; # account for devices with spaces in the name (\040 is the escape character) 415 $device =~ s/\\011/\t/g; # account for mount points with tabs in the name (\011 is the escape character) 416 417 # Skip the read-only bind-mount on /nix/store. 418 next if $mountPoint eq "/nix/store" && (grep { $_ eq "rw" } @superOptions) && (grep { $_ eq "ro" } @mountOptions); 419 420 # Maybe this is a bind-mount of a filesystem we saw earlier? 421 if (defined $fsByDev{$fields[2]}) { 422 # Make sure this isn't a btrfs subvolume. 423 my $msg = `@btrfs@ subvol show $rootDir$mountPoint`; 424 if ($? != 0 || $msg =~ /ERROR:/s) { 425 my $path = $fields[3]; $path = "" if $path eq "/"; 426 my $base = $fsByDev{$fields[2]}; 427 $base = "" if $base eq "/"; 428 $fileSystems .= <<EOF; 429 fileSystems.\"$mountPoint\" = 430 { device = \"$base$path\"; 431 fsType = \"none\"; 432 options = \[ \"bind\" \]; 433 }; 434 435EOF 436 next; 437 } 438 } 439 $fsByDev{$fields[2]} = $mountPoint; 440 441 # We don't know how to handle FUSE filesystems. 442 if ($fsType eq "fuseblk" || $fsType eq "fuse") { 443 print STDERR "warning: don't know how to emit ‘fileSystem’ option for FUSE filesystem ‘$mountPoint’\n"; 444 next; 445 } 446 447 # Is this a mount of a loopback device? 448 my @extraOptions; 449 if ($device =~ /\/dev\/loop(\d+)/) { 450 my $loopnr = $1; 451 my $backer = read_file "/sys/block/loop$loopnr/loop/backing_file"; 452 if (defined $backer) { 453 chomp $backer; 454 $device = $backer; 455 push @extraOptions, "loop"; 456 } 457 } 458 459 # Is this a btrfs filesystem? 460 if ($fsType eq "btrfs") { 461 my ($status, @info) = runCommand("@btrfs@ subvol show $rootDir$mountPoint"); 462 if ($status != 0 || join("", @info) =~ /ERROR:/) { 463 die "Failed to retrieve subvolume info for $mountPoint\n"; 464 } 465 my @ids = join("\n", @info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s; 466 if ($#ids > 0) { 467 die "Btrfs subvol name for $mountPoint listed multiple times in mount\n" 468 } elsif ($#ids == 0) { 469 my @paths = join("", @info) =~ m/^([^\n]*)/; 470 if ($#paths > 0) { 471 die "Btrfs returned multiple paths for a single subvolume id, mountpoint $mountPoint\n"; 472 } elsif ($#paths != 0) { 473 die "Btrfs did not return a path for the subvolume at $mountPoint\n"; 474 } 475 push @extraOptions, "subvol=$paths[0]"; 476 } 477 } 478 479 # Preserve umask (fmask, dmask) settings for vfat filesystems. 480 # (The default is to mount these world-readable, but that's a security risk 481 # for the EFI System Partition.) 482 if ($fsType eq "vfat") { 483 for (@superOptions) { 484 if ($_ =~ /fmask|dmask/) { 485 push @extraOptions, $_; 486 } 487 } 488 } 489 490 # is this a stratis fs? 491 my $stableDevPath = findStableDevPath $device; 492 my $stratisPool; 493 if ($stableDevPath =~ qr#/dev/stratis/(.*)/.*#) { 494 my $poolName = $1; 495 my ($header, @lines) = split "\n", qx/stratis pool list/; 496 my $uuidIndex = index $header, 'UUID'; 497 my ($line) = grep /^$poolName /, @lines; 498 $stratisPool = substr $line, $uuidIndex - 32, 36; 499 } 500 501 # Don't emit tmpfs entry for /tmp, because it most likely comes from the 502 # boot.tmp.useTmpfs option in configuration.nix (managed declaratively). 503 next if ($mountPoint eq "/tmp" && $fsType eq "tmpfs"); 504 505 # This should work for single and multi-device systems. 506 # still needs subvolume support 507 if ($fsType eq "bcachefs") { 508 my ($status, @info) = runCommand("bcachefs fs usage $rootDir$mountPoint"); 509 my $UUID = $info[0]; 510 511 if ($status == 0 && $UUID =~ /^Filesystem:[ \t\n]*([0-9a-z-]+)/) { 512 $stableDevPath = "UUID=$1"; 513 } else { 514 print STDERR "warning: can't find bcachefs mount UUID falling back to device-path"; 515 } 516 } 517 518 # Emit the filesystem. 519 $fileSystems .= <<EOF; 520 fileSystems.\"$mountPoint\" = 521 { device = \"$stableDevPath\"; 522 fsType = \"$fsType\"; 523EOF 524 525 if (scalar @extraOptions > 0) { 526 $fileSystems .= <<EOF; 527 options = \[ ${\join " ", map { "\"" . $_ . "\"" } uniq(@extraOptions)} \]; 528EOF 529 } 530 531 if ($stratisPool) { 532 $fileSystems .= <<EOF; 533 stratis.poolUuid = "$stratisPool"; 534EOF 535 } 536 537 $fileSystems .= <<EOF; 538 }; 539 540EOF 541 542 # If this filesystem is on a LUKS device, then add a 543 # boot.initrd.luks.devices entry. 544 if (-e $device) { 545 my $deviceName = basename(abs_path($device)); 546 my $dmUuid = read_file("/sys/class/block/$deviceName/dm/uuid", err_mode => 'quiet'); 547 if ($dmUuid =~ /^CRYPT-LUKS/) 548 { 549 my @slaves = glob("/sys/class/block/$deviceName/slaves/*"); 550 if (scalar @slaves == 1) { 551 my $slave = "/dev/" . basename($slaves[0]); 552 if (-e $slave) { 553 my $dmName = read_file("/sys/class/block/$deviceName/dm/name"); 554 chomp $dmName; 555 # Ensure to add an entry only once 556 my $luksDevice = " boot.initrd.luks.devices.\"$dmName\".device"; 557 if ($fileSystems !~ /^\Q$luksDevice\E/m) { 558 $fileSystems .= "$luksDevice = \"${\(findStableDevPath $slave)}\";\n\n"; 559 } 560 } 561 } 562 } 563 if (-e "/sys/class/block/$deviceName/md/uuid") { 564 $useSwraid = 1; 565 } 566 } 567} 568if ($useSwraid) { 569 push @attrs, "boot.swraid.enable = true;\n\n"; 570} 571 572 573# Generate the hardware configuration file. 574 575sub toNixStringList { 576 my $res = ""; 577 foreach my $s (@_) { 578 $res .= " \"$s\""; 579 } 580 return $res; 581} 582sub toNixList { 583 my $res = ""; 584 foreach my $s (@_) { 585 $res .= " $s"; 586 } 587 return $res; 588} 589 590sub multiLineList { 591 my $indent = shift; 592 return " [ ]" if !@_; 593 my $res = "\n${indent}[ "; 594 my $first = 1; 595 foreach my $s (@_) { 596 $res .= "$indent " if !$first; 597 $first = 0; 598 $res .= "$s\n"; 599 } 600 $res .= "$indent]"; 601 return $res; 602} 603 604my $initrdAvailableKernelModules = toNixStringList(uniq @initrdAvailableKernelModules); 605my $initrdKernelModules = toNixStringList(uniq @initrdKernelModules); 606my $kernelModules = toNixStringList(uniq @kernelModules); 607my $modulePackages = toNixList(uniq @modulePackages); 608 609my $fsAndSwap = ""; 610if (!$noFilesystems) { 611 $fsAndSwap = "\n$fileSystems "; 612 $fsAndSwap .= "swapDevices =" . multiLineList(" ", @swapDevices) . ";\n"; 613} 614 615my $networkingDhcpConfig = generateNetworkingDhcpConfig(); 616 617my $hwConfig = <<EOF; 618# Do not modify this file! It was generated by ‘nixos-generate-config’ 619# and may be overwritten by future invocations. Please make changes 620# to /etc/nixos/configuration.nix instead. 621{ config, lib, pkgs, modulesPath, ... }: 622 623{ 624 imports =${\multiLineList(" ", @imports)}; 625 626 boot.initrd.availableKernelModules = [$initrdAvailableKernelModules ]; 627 boot.initrd.kernelModules = [$initrdKernelModules ]; 628 boot.kernelModules = [$kernelModules ]; 629 boot.extraModulePackages = [$modulePackages ]; 630$fsAndSwap 631$networkingDhcpConfig 632${\join "", (map { " $_\n" } (uniq @attrs))}} 633EOF 634 635sub generateNetworkingDhcpConfig { 636 # FIXME disable networking.useDHCP by default when switching to networkd. 637 my $config = <<EOF; 638 # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 639 # (the default) this is the recommended approach. When using systemd-networkd it's 640 # still possible to use this option, but it's recommended to use it in conjunction 641 # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. 642 networking.useDHCP = lib.mkDefault true; 643EOF 644 645 foreach my $path (glob "/sys/class/net/*") { 646 my $dev = basename($path); 647 if ($dev ne "lo") { 648 $config .= " # networking.interfaces.$dev.useDHCP = lib.mkDefault true;\n"; 649 } 650 } 651 652 return $config; 653} 654 655sub generateXserverConfig { 656 my $xserverEnabled = "@xserverEnabled@"; 657 658 my $config = ""; 659 if ($xserverEnabled eq "1") { 660 $config = <<EOF; 661 # Enable the X11 windowing system. 662 services.xserver.enable = true; 663EOF 664 } else { 665 $config = <<EOF; 666 # Enable the X11 windowing system. 667 # services.xserver.enable = true; 668EOF 669 } 670} 671 672if ($showHardwareConfig) { 673 print STDOUT $hwConfig; 674} else { 675 if ($outDir eq "/etc/nixos") { 676 $outDir = "$rootDir$outDir"; 677 } else { 678 $outDir = File::Spec->rel2abs($outDir); 679 $outDir =~ s/\/*$//; # remove trailing slashes 680 } 681 682 my $fn = "$outDir/hardware-configuration.nix"; 683 print STDERR "writing $fn...\n"; 684 mkpath($outDir, 0, 0755); 685 write_file($fn, $hwConfig); 686 687 $fn = "$outDir/flake.nix"; 688 if ($flake) { 689 if ($force || ! -e $fn) { 690 print STDERR "writing $fn...\n"; 691 mkpath($outDir, 0, 0755); 692 write_file($fn, <<EOF); 693 @flake@ 694EOF 695 } else { 696 print STDERR "warning: not overwriting existing $fn\n"; 697 } 698 } 699 700 # Generate a basic configuration.nix, unless one already exists. 701 $fn = "$outDir/configuration.nix"; 702 if ($force || ! -e $fn) { 703 print STDERR "writing $fn...\n"; 704 705 my $bootLoaderConfig = ""; 706 if (-e "/sys/firmware/efi/efivars") { 707 $bootLoaderConfig = <<EOF; 708 # Use the systemd-boot EFI boot loader. 709 boot.loader.systemd-boot.enable = true; 710 boot.loader.efi.canTouchEfiVariables = true; 711EOF 712 } elsif (-e "/boot/extlinux") { 713 $bootLoaderConfig = <<EOF; 714 # Use the extlinux boot loader. (NixOS wants to enable GRUB by default) 715 boot.loader.grub.enable = false; 716 # Enables the generation of /boot/extlinux/extlinux.conf 717 boot.loader.generic-extlinux-compatible.enable = true; 718EOF 719 } elsif ($virt ne "systemd-nspawn") { 720 $bootLoaderConfig = <<EOF; 721 # Use the GRUB 2 boot loader. 722 boot.loader.grub.enable = true; 723 # boot.loader.grub.efiSupport = true; 724 # boot.loader.grub.efiInstallAsRemovable = true; 725 # boot.loader.efi.efiSysMountPoint = "/boot/efi"; 726 # Define on which hard drive you want to install Grub. 727 # boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only 728EOF 729 } 730 731 if ($kernel eq "latest") { 732 $bootLoaderConfig .= <<EOF; 733 734 # Use latest kernel. 735 boot.kernelPackages = pkgs.linuxPackages_latest; 736EOF 737 } 738 739 my $networkingDhcpConfig = generateNetworkingDhcpConfig(); 740 741 my $xserverConfig = generateXserverConfig(); 742 743 (my $desktopConfiguration = <<EOF)=~s/^/ /gm; 744@desktopConfiguration@ 745EOF 746 747 write_file($fn, <<EOF); 748@configuration@ 749EOF 750 print STDERR "For more hardware-specific settings, see https://github.com/NixOS/nixos-hardware.\n" 751 } else { 752 print STDERR "warning: not overwriting existing $fn\n"; 753 } 754} 755 756# workaround for a bug in substituteAll