2013-10-11 13:44:32 +01:00
|
|
|
|
#! @perl@
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
2014-05-08 20:00:06 +01:00
|
|
|
|
use Cwd 'abs_path';
|
2008-01-30 14:16:38 +00:00
|
|
|
|
use File::Spec;
|
2013-10-11 13:44:32 +01:00
|
|
|
|
use File::Path;
|
2008-01-30 14:16:38 +00:00
|
|
|
|
use File::Basename;
|
2013-10-11 13:44:32 +01:00
|
|
|
|
use File::Slurp;
|
2014-05-08 20:00:06 +01:00
|
|
|
|
use File::stat;
|
2013-10-11 13:44:32 +01:00
|
|
|
|
|
|
|
|
|
|
2013-10-11 16:17:26 +01:00
|
|
|
|
sub uniq {
|
|
|
|
|
my %seen;
|
|
|
|
|
my @res = ();
|
|
|
|
|
foreach my $s (@_) {
|
|
|
|
|
if (!defined $seen{$s}) {
|
|
|
|
|
$seen{$s} = 1;
|
|
|
|
|
push @res, $s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return @res;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-31 17:18:13 +01:00
|
|
|
|
sub runCommand {
|
|
|
|
|
my ($cmd) = @_;
|
2014-08-31 00:30:56 +01:00
|
|
|
|
open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n";
|
2014-08-31 17:18:13 +01:00
|
|
|
|
my @ret = <FILE>;
|
|
|
|
|
close FILE;
|
|
|
|
|
return ($?, @ret);
|
|
|
|
|
}
|
2013-10-11 16:17:26 +01:00
|
|
|
|
|
2013-10-11 13:44:32 +01:00
|
|
|
|
# Process the command line.
|
|
|
|
|
my $outDir = "/etc/nixos";
|
2013-10-13 14:44:50 +01:00
|
|
|
|
my $rootDir = ""; # = /
|
|
|
|
|
my $force = 0;
|
2013-10-23 14:55:27 +01:00
|
|
|
|
my $noFilesystems = 0;
|
2013-10-23 15:42:34 +01:00
|
|
|
|
my $showHardwareConfig = 0;
|
2013-10-11 13:44:32 +01:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2013-10-13 14:44:50 +01:00
|
|
|
|
elsif ($arg eq "--root") {
|
|
|
|
|
$n++;
|
|
|
|
|
$rootDir = $ARGV[$n];
|
|
|
|
|
die "$0: ‘--root’ requires an argument\n" unless defined $rootDir;
|
|
|
|
|
$rootDir =~ s/\/*$//; # remove trailing slashes
|
|
|
|
|
}
|
|
|
|
|
elsif ($arg eq "--force") {
|
|
|
|
|
$force = 1;
|
|
|
|
|
}
|
2013-10-23 14:55:27 +01:00
|
|
|
|
elsif ($arg eq "--no-filesystems") {
|
|
|
|
|
$noFilesystems = 1;
|
|
|
|
|
}
|
2013-10-23 15:42:34 +01:00
|
|
|
|
elsif ($arg eq "--show-hardware-config") {
|
|
|
|
|
$showHardwareConfig = 1;
|
|
|
|
|
}
|
2013-10-11 13:44:32 +01:00
|
|
|
|
else {
|
|
|
|
|
die "$0: unrecognized argument ‘$arg’\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
|
|
|
|
|
2009-08-04 09:50:02 +01:00
|
|
|
|
my @attrs = ();
|
2008-01-30 14:16:38 +00:00
|
|
|
|
my @kernelModules = ();
|
|
|
|
|
my @initrdKernelModules = ();
|
2010-12-09 19:08:33 +00:00
|
|
|
|
my @modulePackages = ();
|
2014-01-06 14:30:44 +00:00
|
|
|
|
my @imports = ("<nixpkgs/nixos/modules/installer/scan/not-detected.nix>");
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
|
|
|
|
|
2008-02-08 15:59:15 +00:00
|
|
|
|
sub debug {
|
|
|
|
|
return unless defined $ENV{"DEBUG"};
|
|
|
|
|
print STDERR @_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-10-11 14:43:04 +01:00
|
|
|
|
my $cpuinfo = read_file "/proc/cpuinfo";
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub hasCPUFeature {
|
|
|
|
|
my $feature = shift;
|
|
|
|
|
return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Detect the number of CPU cores.
|
|
|
|
|
my $cpus = scalar (grep {/^processor\s*:/} (split '\n', $cpuinfo));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 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.
|
|
|
|
|
|
2011-03-18 13:52:09 +00:00
|
|
|
|
my $videoDriver;
|
2008-01-30 14:32:02 +00:00
|
|
|
|
|
2008-01-30 14:16:38 +00:00
|
|
|
|
sub pciCheck {
|
|
|
|
|
my $path = shift;
|
2014-04-08 14:13:27 +01:00
|
|
|
|
my $vendor = read_file "$path/vendor"; chomp $vendor;
|
|
|
|
|
my $device = read_file "$path/device"; chomp $device;
|
|
|
|
|
my $class = read_file "$path/class"; chomp $class;
|
2013-10-11 13:44:32 +01:00
|
|
|
|
|
2008-01-30 14:16:38 +00:00
|
|
|
|
my $module;
|
|
|
|
|
if (-e "$path/driver/module") {
|
|
|
|
|
$module = basename `readlink -f $path/driver/module`;
|
|
|
|
|
chomp $module;
|
|
|
|
|
}
|
2013-10-11 13:44:32 +01:00
|
|
|
|
|
2008-02-08 15:59:15 +00:00
|
|
|
|
debug "$path: $vendor $device $class";
|
|
|
|
|
debug " $module" if defined $module;
|
|
|
|
|
debug "\n";
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
|
|
|
|
if (defined $module) {
|
|
|
|
|
# See the bottom of http://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/
|
|
|
|
|
)
|
|
|
|
|
{
|
2013-10-13 14:41:58 +01:00
|
|
|
|
push @initrdAvailableKernelModules, $module;
|
2008-01-30 14:16:38 +00:00
|
|
|
|
}
|
2008-01-30 14:32:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-09 19:08:33 +00:00
|
|
|
|
# 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" ||
|
2014-05-08 14:22:01 +01:00
|
|
|
|
$device eq "0x4357" || $device eq "0x4358" || $device eq "0x4359" ||
|
|
|
|
|
$device eq "0x4331" || $device eq "0x43a0" || $device eq "0x43b1"
|
|
|
|
|
) )
|
2010-12-09 19:08:33 +00:00
|
|
|
|
{
|
2010-12-18 17:56:04 +00:00
|
|
|
|
push @modulePackages, "config.boot.kernelPackages.broadcom_sta";
|
2010-12-09 19:08:33 +00:00
|
|
|
|
push @kernelModules, "wl";
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-30 14:32:02 +00:00
|
|
|
|
# Can't rely on $module here, since the module may not be loaded
|
|
|
|
|
# due to missing firmware. Ideally we would check modules.pcimap
|
|
|
|
|
# here.
|
2009-08-04 09:50:02 +01:00
|
|
|
|
push @attrs, "networking.enableIntel2200BGFirmware = true;" if
|
2009-01-25 15:48:59 +00:00
|
|
|
|
$vendor eq "0x8086" &&
|
2008-01-30 14:32:02 +00:00
|
|
|
|
($device eq "0x1043" || $device eq "0x104f" || $device eq "0x4220" ||
|
|
|
|
|
$device eq "0x4221" || $device eq "0x4223" || $device eq "0x4224");
|
2008-01-30 14:50:25 +00:00
|
|
|
|
|
2009-08-04 09:50:02 +01:00
|
|
|
|
push @attrs, "networking.enableIntel3945ABGFirmware = true;" if
|
2009-01-25 15:48:59 +00:00
|
|
|
|
$vendor eq "0x8086" &&
|
2008-02-04 10:39:06 +00:00
|
|
|
|
($device eq "0x4229" || $device eq "0x4230" ||
|
|
|
|
|
$device eq "0x4222" || $device eq "0x4227");
|
|
|
|
|
|
2008-01-30 14:53:06 +00:00
|
|
|
|
# Assume that all NVIDIA cards are supported by the NVIDIA driver.
|
|
|
|
|
# There may be exceptions (e.g. old cards).
|
2014-04-08 14:13:27 +01:00
|
|
|
|
# FIXME: do we want to enable an unfree driver here?
|
2014-05-08 19:20:12 +01:00
|
|
|
|
#$videoDriver = "nvidia" if $vendor eq "0x10de" && $class =~ /^0x03/;
|
2008-01-30 14:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach my $path (glob "/sys/bus/pci/devices/*") {
|
|
|
|
|
pciCheck $path;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-29 11:58:54 +01:00
|
|
|
|
push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];" if $videoDriver;
|
2013-10-11 15:05:31 +01:00
|
|
|
|
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
|
|
|
|
# Idem for USB devices.
|
|
|
|
|
|
|
|
|
|
sub usbCheck {
|
|
|
|
|
my $path = shift;
|
2014-04-08 14:13:27 +01:00
|
|
|
|
my $class = read_file "$path/bInterfaceClass"; chomp $class;
|
|
|
|
|
my $subclass = read_file "$path/bInterfaceSubClass"; chomp $subclass;
|
|
|
|
|
my $protocol = read_file "$path/bInterfaceProtocol"; chomp $protocol;
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
|
|
|
|
my $module;
|
|
|
|
|
if (-e "$path/driver/module") {
|
|
|
|
|
$module = basename `readlink -f $path/driver/module`;
|
|
|
|
|
chomp $module;
|
|
|
|
|
}
|
2013-10-11 13:44:32 +01:00
|
|
|
|
|
2008-02-08 15:59:15 +00:00
|
|
|
|
debug "$path: $class $subclass $protocol";
|
|
|
|
|
debug " $module" if defined $module;
|
|
|
|
|
debug "\n";
|
2013-10-11 13:44:32 +01:00
|
|
|
|
|
2008-01-30 14:16:38 +00:00
|
|
|
|
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")
|
|
|
|
|
)
|
|
|
|
|
{
|
2013-10-13 14:41:58 +01:00
|
|
|
|
push @initrdAvailableKernelModules, $module;
|
2008-01-30 14:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach my $path (glob "/sys/bus/usb/devices/*") {
|
|
|
|
|
if (-e "$path/bInterfaceClass") {
|
|
|
|
|
usbCheck $path;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-01-06 20:09:53 +00:00
|
|
|
|
# Add the modules for all block devices.
|
|
|
|
|
foreach my $path (glob "/sys/class/block/*") {
|
|
|
|
|
my $module;
|
|
|
|
|
if (-e "$path/device/driver/module") {
|
|
|
|
|
$module = basename `readlink -f $path/device/driver/module`;
|
|
|
|
|
chomp $module;
|
2013-10-13 14:41:58 +01:00
|
|
|
|
push @initrdAvailableKernelModules, $module;
|
2010-01-06 20:09:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-04-30 10:17:30 +01:00
|
|
|
|
my $virt = `systemd-detect-virt`;
|
|
|
|
|
chomp $virt;
|
2014-03-30 16:26:43 +01:00
|
|
|
|
|
|
|
|
|
|
2012-03-16 01:57:23 +00:00
|
|
|
|
# Check if we're a VirtualBox guest. If so, enable the guest
|
|
|
|
|
# additions.
|
2014-04-30 10:17:30 +01:00
|
|
|
|
if ($virt eq "oracle") {
|
2012-03-16 01:57:23 +00:00
|
|
|
|
push @attrs, "services.virtualbox.enable = true;"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-03-30 16:26:43 +01:00
|
|
|
|
# Likewise for QEMU.
|
2014-04-30 10:17:30 +01:00
|
|
|
|
if ($virt eq "qemu" || $virt eq "kvm" || $virt eq "bochs") {
|
2014-03-30 16:26:43 +01:00
|
|
|
|
push @imports, "<nixpkgs/nixos/modules/profiles/qemu-guest.nix>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-05-08 20:00:06 +01:00
|
|
|
|
# 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/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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-10-11 16:17:26 +01:00
|
|
|
|
# Generate the swapDevices option from the currently activated swap
|
|
|
|
|
# devices.
|
2013-10-11 15:05:31 +01:00
|
|
|
|
my @swaps = read_file("/proc/swaps");
|
|
|
|
|
shift @swaps;
|
|
|
|
|
my @swapDevices;
|
|
|
|
|
foreach my $swap (@swaps) {
|
|
|
|
|
$swap =~ /^(\S+)\s/;
|
2014-05-08 20:00:06 +01:00
|
|
|
|
next unless -e $1;
|
|
|
|
|
my $dev = findStableDevPath $1;
|
|
|
|
|
push @swapDevices, "{ device = \"$dev\"; }";
|
2013-10-11 15:05:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-10-11 16:17:26 +01:00
|
|
|
|
# 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/";
|
|
|
|
|
}
|
2008-01-30 14:16:38 +00:00
|
|
|
|
|
2013-10-11 16:17:26 +01:00
|
|
|
|
my $fileSystems;
|
|
|
|
|
my %fsByDev;
|
|
|
|
|
foreach my $fs (read_file("/proc/self/mountinfo")) {
|
|
|
|
|
chomp $fs;
|
|
|
|
|
my @fields = split / /, $fs;
|
|
|
|
|
my $mountPoint = $fields[4];
|
|
|
|
|
next unless -d $mountPoint;
|
|
|
|
|
my @mountOptions = split /,/, $fields[5];
|
|
|
|
|
|
2013-10-13 14:44:50 +01:00
|
|
|
|
next if !in($mountPoint, $rootDir);
|
|
|
|
|
$mountPoint = substr($mountPoint, length($rootDir)); # strip the root directory (e.g. /mnt)
|
|
|
|
|
$mountPoint = "/" if $mountPoint eq "";
|
|
|
|
|
|
2013-10-11 16:17:26 +01:00
|
|
|
|
# Skip special filesystems.
|
2014-02-19 15:56:25 +00:00
|
|
|
|
next if in($mountPoint, "/proc") || in($mountPoint, "/dev") || in($mountPoint, "/sys") || in($mountPoint, "/run") || $mountPoint eq "/var/lib/nfs/rpc_pipefs";
|
2014-05-08 20:01:34 +01:00
|
|
|
|
next if $mountPoint eq "/var/setuid-wrappers";
|
2013-10-11 16:17:26 +01:00
|
|
|
|
|
|
|
|
|
# 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];
|
|
|
|
|
|
|
|
|
|
# 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]}) {
|
2014-08-31 00:30:56 +01:00
|
|
|
|
# Make sure this isn't a btrfs subvolume
|
|
|
|
|
my ($status, @msg) = runCommand("btrfs subvol show $rootDir$mountPoint");
|
|
|
|
|
if (join("", @msg) =~ /ERROR:/) {
|
|
|
|
|
my $path = $fields[3]; $path = "" if $path eq "/";
|
|
|
|
|
my $base = $fsByDev{$fields[2]};
|
|
|
|
|
$base = "" if $base eq "/";
|
|
|
|
|
$fileSystems .= <<EOF;
|
2013-10-11 16:24:30 +01:00
|
|
|
|
fileSystems.\"$mountPoint\" =
|
2014-05-08 20:02:40 +01:00
|
|
|
|
{ device = \"$base$path\";
|
2013-10-11 16:24:30 +01:00
|
|
|
|
fsType = \"none\";
|
|
|
|
|
options = \"bind\";
|
|
|
|
|
};
|
2013-10-11 16:17:26 +01:00
|
|
|
|
|
|
|
|
|
EOF
|
2014-08-31 00:30:56 +01:00
|
|
|
|
next;
|
|
|
|
|
}
|
2013-10-11 16:17:26 +01:00
|
|
|
|
}
|
2013-10-11 16:24:30 +01:00
|
|
|
|
$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;
|
|
|
|
|
}
|
2013-10-11 16:17:26 +01:00
|
|
|
|
|
|
|
|
|
# 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";
|
2008-01-30 14:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-11 16:17:26 +01:00
|
|
|
|
|
2014-08-31 17:18:13 +01:00
|
|
|
|
# Is this a btrfs filesystem?
|
|
|
|
|
if ($fsType eq "btrfs") {
|
2014-08-30 23:33:44 +01:00
|
|
|
|
my ($status, @id_info) = runCommand("btrfs subvol show $rootDir$mountPoint");
|
2014-08-31 00:30:56 +01:00
|
|
|
|
if ($status != 0 || join("", @msg) =~ /ERROR:/) {
|
2014-08-30 23:33:44 +01:00
|
|
|
|
die "Failed to retreive subvolume info for $mountPoint\n";
|
2014-08-31 17:18:13 +01:00
|
|
|
|
}
|
2014-08-30 23:33:44 +01:00
|
|
|
|
my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/;
|
|
|
|
|
if ($#ids > 0) {
|
2014-08-31 17:18:13 +01:00
|
|
|
|
die "Btrfs subvol name for $mountPoint listed multiple times in mount\n"
|
2014-08-30 23:33:44 +01:00
|
|
|
|
} elsif ($#ids == 0) {
|
|
|
|
|
my ($status, @path_info) = runCommand("btrfs subvol list $rootDir$mountPoint");
|
|
|
|
|
if ($status != 0) {
|
|
|
|
|
die "Failed to find $mountPoint subvolume id from btrfs\n";
|
|
|
|
|
}
|
|
|
|
|
my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\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]";
|
2014-08-31 17:18:13 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-11 16:17:26 +01:00
|
|
|
|
# Emit the filesystem.
|
|
|
|
|
$fileSystems .= <<EOF;
|
2013-10-11 16:24:30 +01:00
|
|
|
|
fileSystems.\"$mountPoint\" =
|
2014-05-08 20:00:06 +01:00
|
|
|
|
{ device = \"${\(findStableDevPath $device)}\";
|
2013-10-11 16:24:30 +01:00
|
|
|
|
fsType = \"$fsType\";
|
2014-02-19 16:13:21 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
if (scalar @extraOptions > 0) {
|
|
|
|
|
$fileSystems .= <<EOF;
|
|
|
|
|
options = \"${\join ",", uniq(@extraOptions)}\";
|
|
|
|
|
EOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$fileSystems .= <<EOF;
|
2013-10-11 16:24:30 +01:00
|
|
|
|
};
|
2013-10-11 16:17:26 +01:00
|
|
|
|
|
|
|
|
|
EOF
|
2008-01-30 14:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-11 16:17:26 +01:00
|
|
|
|
|
|
|
|
|
# Generate the hardware configuration file.
|
|
|
|
|
|
2008-01-30 14:16:38 +00:00
|
|
|
|
sub toNixExpr {
|
|
|
|
|
my $res = "";
|
|
|
|
|
foreach my $s (@_) {
|
|
|
|
|
$res .= " \"$s\"";
|
|
|
|
|
}
|
|
|
|
|
return $res;
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-25 15:48:59 +00:00
|
|
|
|
sub multiLineList {
|
|
|
|
|
my $indent = shift;
|
2014-05-08 20:00:06 +01:00
|
|
|
|
return " [ ]" if !@_;
|
2013-10-11 15:05:31 +01:00
|
|
|
|
$res = "\n${indent}[ ";
|
|
|
|
|
my $first = 1;
|
2009-01-25 15:48:59 +00:00
|
|
|
|
foreach my $s (@_) {
|
2013-10-11 15:05:31 +01:00
|
|
|
|
$res .= "$indent " if !$first;
|
|
|
|
|
$first = 0;
|
|
|
|
|
$res .= "$s\n";
|
2009-01-25 15:48:59 +00:00
|
|
|
|
}
|
2013-10-11 15:05:31 +01:00
|
|
|
|
$res .= "$indent]";
|
2009-01-25 15:48:59 +00:00
|
|
|
|
return $res;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-13 14:41:58 +01:00
|
|
|
|
my $initrdAvailableKernelModules = toNixExpr(uniq @initrdAvailableKernelModules);
|
2013-10-11 16:17:26 +01:00
|
|
|
|
my $kernelModules = toNixExpr(uniq @kernelModules);
|
|
|
|
|
my $modulePackages = toNixExpr(uniq @modulePackages);
|
2012-03-16 01:57:23 +00:00
|
|
|
|
|
2013-10-23 14:55:27 +01:00
|
|
|
|
my $fsAndSwap = "";
|
|
|
|
|
if (!$noFilesystems) {
|
|
|
|
|
$fsAndSwap = "\n${fileSystems} ";
|
2013-10-23 15:00:39 +01:00
|
|
|
|
$fsAndSwap .= "swapDevices =" . multiLineList(" ", @swapDevices) . ";\n";
|
2013-10-23 14:55:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-23 15:42:34 +01:00
|
|
|
|
my $hwConfig = <<EOF;
|
2013-10-11 13:44:32 +01:00
|
|
|
|
# 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.
|
2012-03-10 14:35:31 +00:00
|
|
|
|
{ config, pkgs, ... }:
|
2010-09-25 10:32:37 +01:00
|
|
|
|
|
2008-01-30 14:16:38 +00:00
|
|
|
|
{
|
2013-10-23 15:00:39 +01:00
|
|
|
|
imports =${\multiLineList(" ", @imports)};
|
2010-09-25 10:32:37 +01:00
|
|
|
|
|
2013-10-13 14:41:58 +01:00
|
|
|
|
boot.initrd.availableKernelModules = [$initrdAvailableKernelModules ];
|
2011-03-18 13:52:09 +00:00
|
|
|
|
boot.kernelModules = [$kernelModules ];
|
|
|
|
|
boot.extraModulePackages = [$modulePackages ];
|
2013-10-23 14:55:27 +01:00
|
|
|
|
$fsAndSwap
|
2009-06-17 11:41:17 +01:00
|
|
|
|
nix.maxJobs = $cpus;
|
2013-10-11 16:17:26 +01:00
|
|
|
|
${\join "", (map { " $_\n" } (uniq @attrs))}}
|
2008-01-30 14:16:38 +00:00
|
|
|
|
EOF
|
2013-10-11 13:44:32 +01:00
|
|
|
|
|
2013-10-11 15:05:31 +01:00
|
|
|
|
|
2013-10-23 15:42:34 +01:00
|
|
|
|
if ($showHardwareConfig) {
|
|
|
|
|
print STDOUT $hwConfig;
|
|
|
|
|
} else {
|
|
|
|
|
$outDir = "$rootDir$outDir";
|
|
|
|
|
|
|
|
|
|
my $fn = "$outDir/hardware-configuration.nix";
|
2013-10-11 14:35:41 +01:00
|
|
|
|
print STDERR "writing $fn...\n";
|
2013-10-23 15:42:34 +01:00
|
|
|
|
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";
|
2013-10-11 14:35:41 +01:00
|
|
|
|
|
2013-10-23 15:42:34 +01:00
|
|
|
|
my $bootloaderConfig;
|
|
|
|
|
if (-e "/sys/firmware/efi/efivars") {
|
|
|
|
|
$bootLoaderConfig = <<EOF;
|
2013-10-11 14:35:41 +01:00
|
|
|
|
# Use the gummiboot efi boot loader.
|
|
|
|
|
boot.loader.gummiboot.enable = true;
|
|
|
|
|
boot.loader.efi.canTouchEfiVariables = true;
|
|
|
|
|
EOF
|
2013-10-23 15:42:34 +01:00
|
|
|
|
} else {
|
|
|
|
|
$bootLoaderConfig = <<EOF;
|
2013-10-11 14:35:41 +01:00
|
|
|
|
# Use the GRUB 2 boot loader.
|
|
|
|
|
boot.loader.grub.enable = true;
|
|
|
|
|
boot.loader.grub.version = 2;
|
|
|
|
|
# Define on which hard drive you want to install Grub.
|
|
|
|
|
# boot.loader.grub.device = "/dev/sda";
|
|
|
|
|
EOF
|
2013-10-23 15:42:34 +01:00
|
|
|
|
}
|
2013-10-11 14:35:41 +01:00
|
|
|
|
|
2014-11-01 17:27:54 +00:00
|
|
|
|
# Generate a random 32-bit value to use as the host id
|
|
|
|
|
open my $rnd, "<", "/dev/urandom" or die $!;
|
|
|
|
|
read $rnd, $hostIdBin, 4;
|
|
|
|
|
close $rnd;
|
|
|
|
|
|
|
|
|
|
# Convert the 32-bit value to a hex string
|
|
|
|
|
my $hostIdHex = unpack("H*", $hostIdBin);
|
|
|
|
|
|
2013-10-23 15:42:34 +01:00
|
|
|
|
write_file($fn, <<EOF);
|
2013-10-11 14:35:41 +01:00
|
|
|
|
# Edit this configuration file to define what should be installed on
|
|
|
|
|
# your system. Help is available in the configuration.nix(5) man page
|
|
|
|
|
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
|
|
|
|
|
|
|
|
|
{ config, pkgs, ... }:
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
imports =
|
|
|
|
|
[ # Include the results of the hardware scan.
|
|
|
|
|
./hardware-configuration.nix
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$bootLoaderConfig
|
|
|
|
|
# networking.hostName = "nixos"; # Define your hostname.
|
2014-11-01 17:27:54 +00:00
|
|
|
|
networking.hostId = "$hostIdHex";
|
2013-10-11 14:35:41 +01:00
|
|
|
|
# networking.wireless.enable = true; # Enables wireless.
|
|
|
|
|
|
|
|
|
|
# Select internationalisation properties.
|
|
|
|
|
# i18n = {
|
|
|
|
|
# consoleFont = "lat9w-16";
|
|
|
|
|
# consoleKeyMap = "us";
|
|
|
|
|
# defaultLocale = "en_US.UTF-8";
|
|
|
|
|
# };
|
|
|
|
|
|
2014-03-08 18:56:47 +00:00
|
|
|
|
# List packages installed in system profile. To search by name, run:
|
2014-06-12 20:18:21 +01:00
|
|
|
|
# \$ nix-env -qaP | grep wget
|
2014-03-08 18:56:47 +00:00
|
|
|
|
# environment.systemPackages = with pkgs; [
|
|
|
|
|
# wget
|
|
|
|
|
# ];
|
|
|
|
|
|
2013-10-11 14:35:41 +01:00
|
|
|
|
# List services that you want to enable:
|
|
|
|
|
|
|
|
|
|
# Enable the OpenSSH daemon.
|
|
|
|
|
# services.openssh.enable = true;
|
|
|
|
|
|
|
|
|
|
# Enable CUPS to print documents.
|
|
|
|
|
# services.printing.enable = true;
|
|
|
|
|
|
|
|
|
|
# Enable the X11 windowing system.
|
|
|
|
|
# services.xserver.enable = true;
|
|
|
|
|
# services.xserver.layout = "us";
|
|
|
|
|
# services.xserver.xkbOptions = "eurosign:e";
|
|
|
|
|
|
|
|
|
|
# Enable the KDE Desktop Environment.
|
|
|
|
|
# services.xserver.displayManager.kdm.enable = true;
|
|
|
|
|
# services.xserver.desktopManager.kde4.enable = true;
|
2014-03-08 18:56:47 +00:00
|
|
|
|
|
2014-04-30 15:39:56 +01:00
|
|
|
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
2014-03-08 18:56:47 +00:00
|
|
|
|
# users.extraUsers.guest = {
|
2014-08-15 01:07:43 +01:00
|
|
|
|
# isNormalUser = true;
|
2014-03-08 18:56:47 +00:00
|
|
|
|
# uid = 1000;
|
|
|
|
|
# };
|
|
|
|
|
|
2013-10-11 14:35:41 +01:00
|
|
|
|
}
|
|
|
|
|
EOF
|
2013-10-23 15:42:34 +01:00
|
|
|
|
} else {
|
|
|
|
|
print STDERR "warning: not overwriting existing $fn\n";
|
|
|
|
|
}
|
2013-10-11 14:35:41 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-06 10:57:52 +00:00
|
|
|
|
# workaround for a bug in substituteAll
|