diff options
Diffstat (limited to 'nixos')
20 files changed, 382 insertions, 183 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2105.xml b/nixos/doc/manual/release-notes/rl-2105.xml index 6dd14d6051e40..3760c52d36366 100644 --- a/nixos/doc/manual/release-notes/rl-2105.xml +++ b/nixos/doc/manual/release-notes/rl-2105.xml @@ -93,6 +93,11 @@ <itemizedlist> <listitem> <para> + The <literal>systemConfig</literal> kernel parameter is no longer added to boot loader entries. It has been unused since September 2010, but if do have a system generation from that era, you will now be unable to boot into them. + </para> + </listitem> + <listitem> + <para> <literal>systemd-journal2gelf</literal> no longer parses json and expects the receiving system to handle it. How to achieve this with Graylog is described in this <link xlink:href="https://github.com/parse-nl/SystemdJournal2Gelf/issues/10">GitHub issue</link>. </para> </listitem> diff --git a/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix index 8159576a62ac7..123f487baf93c 100644 --- a/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix +++ b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix @@ -26,7 +26,7 @@ let # A clue for the kernel loading kernelParams = pkgs.writeText "kernel-params.txt" '' Kernel Parameters: - init=/boot/init systemConfig=/boot/init ${toString config.boot.kernelParams} + init=/boot/init ${toString config.boot.kernelParams} ''; # System wide nixpkgs config diff --git a/nixos/modules/installer/cd-dvd/system-tarball-pc.nix b/nixos/modules/installer/cd-dvd/system-tarball-pc.nix index f2af7dcde3d54..a79209d7dfeff 100644 --- a/nixos/modules/installer/cd-dvd/system-tarball-pc.nix +++ b/nixos/modules/installer/cd-dvd/system-tarball-pc.nix @@ -23,13 +23,13 @@ let label nixos MENU LABEL ^NixOS using nfsroot KERNEL bzImage - append ip=dhcp nfsroot=/home/pcroot systemConfig=${config.system.build.toplevel} init=${config.system.build.toplevel}/init rw + append ip=dhcp nfsroot=/home/pcroot init=${config.system.build.toplevel}/init rw # I don't know how to make this boot with nfsroot (using the initrd) label nixos_initrd MENU LABEL NixOS booting the poor ^initrd. KERNEL bzImage - append initrd=initrd ip=dhcp nfsroot=/home/pcroot systemConfig=${config.system.build.toplevel} init=${config.system.build.toplevel}/init rw + append initrd=initrd ip=dhcp nfsroot=/home/pcroot init=${config.system.build.toplevel}/init rw label memtest MENU LABEL ^${pkgs.memtest86.name} diff --git a/nixos/modules/misc/crashdump.nix b/nixos/modules/misc/crashdump.nix index 11dec37b3fae1..796078d7ef8c4 100644 --- a/nixos/modules/misc/crashdump.nix +++ b/nixos/modules/misc/crashdump.nix @@ -53,7 +53,7 @@ in ${pkgs.kexectools}/sbin/kexec -p /run/current-system/kernel \ --initrd=/run/current-system/initrd \ --reset-vga --console-vga \ - --command-line="systemConfig=$(readlink -f /run/current-system) init=$(readlink -f /run/current-system/init) irqpoll maxcpus=1 reset_devices ${kernelParams}" + --command-line="init=$(readlink -f /run/current-system/init) irqpoll maxcpus=1 reset_devices ${kernelParams}" ''; kernelParams = [ "crashkernel=${crashdump.reservedMemory}" diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix index da36ae68b3fc4..08ad90126b1d2 100644 --- a/nixos/modules/services/hardware/bluetooth.nix +++ b/nixos/modules/services/hardware/bluetooth.nix @@ -104,7 +104,7 @@ in # will in fact load the configuration file at /etc/bluetooth/main.conf # so force it here to avoid any ambiguity and things suddenly breaking # if/when the bluez derivation is changed. - args = [ "-f /etc/bluetooth/main.conf" ] + args = [ "-f" "/etc/bluetooth/main.conf" ] ++ optional hasDisabledPlugins "--noplugin=${concatStringsSep "," cfg.disabledPlugins}"; in diff --git a/nixos/modules/services/mail/mlmmj.nix b/nixos/modules/services/mail/mlmmj.nix index d58d93c4214c1..fd74f2dc5f07f 100644 --- a/nixos/modules/services/mail/mlmmj.nix +++ b/nixos/modules/services/mail/mlmmj.nix @@ -16,7 +16,14 @@ let alias = domain: list: "${list}: \"|${pkgs.mlmmj}/bin/mlmmj-receive -L ${listDir domain list}/\""; subjectPrefix = list: "[${list}]"; listAddress = domain: list: "${list}@${domain}"; - customHeaders = domain: list: [ "List-Id: ${list}" "Reply-To: ${list}@${domain}" ]; + customHeaders = domain: list: [ + "List-Id: ${list}" + "Reply-To: ${list}@${domain}" + "List-Post: <mailto:${list}@${domain}>" + "List-Help: <mailto:${list}+help@${domain}>" + "List-Subscribe: <mailto:${list}+subscribe@${domain}>" + "List-Unsubscribe: <mailto:${list}+unsubscribe@${domain}>" + ]; footer = domain: list: "To unsubscribe send a mail to ${list}+unsubscribe@${domain}"; createList = d: l: let ctlDir = listCtl d l; in @@ -110,17 +117,29 @@ in services.postfix = { enable = true; recipientDelimiter= "+"; - extraMasterConf = '' - mlmmj unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj}/bin/mlmmj-receive -F -L ${spoolDir}/$nexthop - ''; + masterConfig.mlmmj = { + type = "unix"; + private = true; + privileged = true; + chroot = false; + wakeup = 0; + command = "pipe"; + args = [ + "flags=ORhu" + "user=mlmmj" + "argv=${pkgs.mlmmj}/bin/mlmmj-receive" + "-F" + "-L" + "${spoolDir}/$nexthop" + ]; + }; extraAliases = concatMapLines (alias cfg.listDomain) cfg.mailLists; - extraConfig = '' - transport_maps = hash:${stateDir}/transports - virtual_alias_maps = hash:${stateDir}/virtuals - propagate_unmatched_extensions = virtual - ''; + extraConfig = "propagate_unmatched_extensions = virtual"; + + virtual = concatMapLines (virtual cfg.listDomain) cfg.mailLists; + transport = concatMapLines (transport cfg.listDomain) cfg.mailLists; }; environment.systemPackages = [ pkgs.mlmmj ]; @@ -129,10 +148,8 @@ in ${pkgs.coreutils}/bin/mkdir -p ${stateDir} ${spoolDir}/${cfg.listDomain} ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${spoolDir} ${concatMapLines (createList cfg.listDomain) cfg.mailLists} - echo "${concatMapLines (virtual cfg.listDomain) cfg.mailLists}" > ${stateDir}/virtuals - echo "${concatMapLines (transport cfg.listDomain) cfg.mailLists}" > ${stateDir}/transports - ${pkgs.postfix}/bin/postmap ${stateDir}/virtuals - ${pkgs.postfix}/bin/postmap ${stateDir}/transports + ${pkgs.postfix}/bin/postmap /etc/postfix/virtual + ${pkgs.postfix}/bin/postmap /etc/postfix/transport ''; systemd.services.mlmmj-maintd = { diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix index e67badfcd29eb..b19cd07325266 100644 --- a/nixos/modules/services/printing/cupsd.nix +++ b/nixos/modules/services/printing/cupsd.nix @@ -270,7 +270,7 @@ in drivers = mkOption { type = types.listOf types.path; default = []; - example = literalExample "with pkgs; [ gutenprint hplip splix cups-googlecloudprint ]"; + example = literalExample "with pkgs; [ gutenprint hplip splix ]"; description = '' CUPS drivers to use. Drivers provided by CUPS, cups-filters, Ghostscript and Samba are added unconditionally. If this list contains diff --git a/nixos/modules/services/web-apps/mastodon.nix b/nixos/modules/services/web-apps/mastodon.nix index 24aea356de4e8..ea7aebc3b12d5 100644 --- a/nixos/modules/services/web-apps/mastodon.nix +++ b/nixos/modules/services/web-apps/mastodon.nix @@ -111,7 +111,6 @@ in { group = lib.mkOption { description = '' Group under which mastodon runs. - If it is set to "mastodon", a group will be created. ''; type = lib.types.str; default = "mastodon"; @@ -555,10 +554,9 @@ in { }; }) (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package mastodonEnv ]) - (lib.mkIf cfg.configureNginx {${config.services.nginx.user}.extraGroups = [ cfg.user ];}) ]; - users.groups.mastodon = lib.mkIf (cfg.group == "mastodon") { }; + users.groups.${cfg.group}.members = lib.optional cfg.configureNginx config.services.nginx.user; }; meta.maintainers = with lib.maintainers; [ happy-river erictapen ]; diff --git a/nixos/modules/services/web-apps/moinmoin.nix b/nixos/modules/services/web-apps/moinmoin.nix index 3a876f75f4a48..7a54255a46efc 100644 --- a/nixos/modules/services/web-apps/moinmoin.nix +++ b/nixos/modules/services/web-apps/moinmoin.nix @@ -211,7 +211,7 @@ in environment = let penv = python.buildEnv.override { # setuptools: https://github.com/benoitc/gunicorn/issues/1716 - extraLibs = [ python.pkgs.gevent python.pkgs.setuptools pkg ]; + extraLibs = [ python.pkgs.eventlet python.pkgs.setuptools pkg ]; }; in { PYTHONPATH = "${dataDir}/${wikiIdent}/config:${penv}/${python.sitePackages}"; @@ -233,7 +233,7 @@ in ExecStart = ''${python.pkgs.gunicorn}/bin/gunicorn moin_wsgi \ --name gunicorn-${wikiIdent} \ --workers ${toString cfg.gunicorn.workers} \ - --worker-class gevent \ + --worker-class eventlet \ --bind unix:/run/moin/${wikiIdent}/gunicorn.sock ''; diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 23ebbdb7f71b0..de1c67235f491 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -602,6 +602,7 @@ in { "^~ /.well-known" = { priority = 210; extraConfig = '' + absolute_redirect off; location = /.well-known/carddav { return 301 /remote.php/dav; } diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh index 854684b87face..5ffffb95edb1b 100644 --- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh +++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh @@ -109,7 +109,7 @@ addEntry() { exit 1 fi fi - echo " APPEND systemConfig=$path init=$path/init $extraParams" + echo " APPEND init=$path/init $extraParams" } tmpFile="$target/extlinux/extlinux.conf.tmp.$$" diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 59f5638044fe9..e0167654748e1 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -102,10 +102,10 @@ if (stat($bootPath)->dev != stat("/nix/store")->dev) { # Discover information about the location of the bootPath struct(Fs => { - device => '$', - type => '$', - mount => '$', -}); + device => '$', + type => '$', + mount => '$', + }); sub PathInMount { my ($path, $mount) = @_; my @splitMount = split /\//, $mount; @@ -154,16 +154,16 @@ sub GetFs { return $bestFs; } struct (Grub => { - path => '$', - search => '$', -}); + path => '$', + search => '$', + }); my $driveid = 1; sub GrubFs { my ($dir) = @_; my $fs = GetFs($dir); my $path = substr($dir, length($fs->mount)); if (substr($path, 0, 1) ne "/") { - $path = "/$path"; + $path = "/$path"; } my $search = ""; @@ -251,8 +251,8 @@ my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n"; if ($grubVersion == 1) { $conf .= " - default $defaultEntry - timeout $timeout + default $defaultEntry + timeout $timeout "; if ($splashImage) { copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath: $!\n"; @@ -302,51 +302,51 @@ else { if ($copyKernels == 0) { $conf .= " - " . $grubStore->search; + " . $grubStore->search; } # FIXME: should use grub-mkconfig. $conf .= " - " . $grubBoot->search . " - if [ -s \$prefix/grubenv ]; then - load_env - fi - - # ‘grub-reboot’ sets a one-time saved entry, which we process here and - # then delete. - if [ \"\${next_entry}\" ]; then - set default=\"\${next_entry}\" - set next_entry= - save_env next_entry - set timeout=1 - else - set default=$defaultEntry - set timeout=$timeout - fi - - # Setup the graphics stack for bios and efi systems - if [ \"\${grub_platform}\" = \"efi\" ]; then - insmod efi_gop - insmod efi_uga - else - insmod vbe - fi + " . $grubBoot->search . " + if [ -s \$prefix/grubenv ]; then + load_env + fi + + # ‘grub-reboot’ sets a one-time saved entry, which we process here and + # then delete. + if [ \"\${next_entry}\" ]; then + set default=\"\${next_entry}\" + set next_entry= + save_env next_entry + set timeout=1 + else + set default=$defaultEntry + set timeout=$timeout + fi + + # Setup the graphics stack for bios and efi systems + if [ \"\${grub_platform}\" = \"efi\" ]; then + insmod efi_gop + insmod efi_uga + else + insmod vbe + fi "; if ($font) { copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath: $!\n"; $conf .= " - insmod font - if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then - insmod gfxterm - if [ \"\${grub_platform}\" = \"efi\" ]; then - set gfxmode=$gfxmodeEfi - set gfxpayload=$gfxpayloadEfi - else - set gfxmode=$gfxmodeBios - set gfxpayload=$gfxpayloadBios - fi - terminal_output gfxterm - fi + insmod font + if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then + insmod gfxterm + if [ \"\${grub_platform}\" = \"efi\" ]; then + set gfxmode=$gfxmodeEfi + set gfxpayload=$gfxpayloadEfi + else + set gfxmode=$gfxmodeBios + set gfxpayload=$gfxpayloadBios + fi + terminal_output gfxterm + fi "; } if ($splashImage) { @@ -356,21 +356,21 @@ else { if ($suffix eq ".jpg") { $suffix = ".jpeg"; } - if ($backgroundColor) { - $conf .= " - background_color '$backgroundColor' - "; - } + if ($backgroundColor) { + $conf .= " + background_color '$backgroundColor' + "; + } copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath: $!\n"; $conf .= " - insmod " . substr($suffix, 1) . " - if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then - set color_normal=white/black - set color_highlight=black/white - else - set menu_color_normal=cyan/blue - set menu_color_highlight=white/blue - fi + insmod " . substr($suffix, 1) . " + if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then + set color_normal=white/black + set color_highlight=black/white + else + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi "; } @@ -380,21 +380,21 @@ else { # Copy theme rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n"; $conf .= " - # Sets theme. - set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt - export theme - # Load theme fonts, if any - "; - - find( { wanted => sub { - if ($_ =~ /\.pf2$/i) { - $font = File::Spec->abs2rel($File::Find::name, $theme); - $conf .= " - loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font - "; - } - }, no_chdir => 1 }, $theme ); - } + # Sets theme. + set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt + export theme + # Load theme fonts, if any + "; + + find( { wanted => sub { + if ($_ =~ /\.pf2$/i) { + $font = File::Spec->abs2rel($File::Find::name, $theme); + $conf .= " + loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font + "; + } + }, no_chdir => 1 }, $theme ); + } } $conf .= "$extraConfig\n"; @@ -433,25 +433,25 @@ sub addEntry { # Include second initrd with secrets if (-e -x "$path/append-initrd-secrets") { - my $initrdName = basename($initrd); - my $initrdSecretsPath = "$bootPath/kernels/$initrdName-secrets"; - - mkpath(dirname($initrdSecretsPath), 0, 0755); - my $oldUmask = umask; - # Make sure initrd is not world readable (won't work if /boot is FAT) - umask 0137; - my $initrdSecretsPathTemp = File::Temp::mktemp("$initrdSecretsPath.XXXXXXXX"); - system("$path/append-initrd-secrets", $initrdSecretsPathTemp) == 0 or die "failed to create initrd secrets: $!\n"; - # Check whether any secrets were actually added - if (-e $initrdSecretsPathTemp && ! -z _) { - rename $initrdSecretsPathTemp, $initrdSecretsPath or die "failed to move initrd secrets into place: $!\n"; - $copied{$initrdSecretsPath} = 1; - $initrd .= " " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$initrdName-secrets"; - } else { - unlink $initrdSecretsPathTemp; - rmdir dirname($initrdSecretsPathTemp); - } - umask $oldUmask; + my $initrdName = basename($initrd); + my $initrdSecretsPath = "$bootPath/kernels/$initrdName-secrets"; + + mkpath(dirname($initrdSecretsPath), 0, 0755); + my $oldUmask = umask; + # Make sure initrd is not world readable (won't work if /boot is FAT) + umask 0137; + my $initrdSecretsPathTemp = File::Temp::mktemp("$initrdSecretsPath.XXXXXXXX"); + system("$path/append-initrd-secrets", $initrdSecretsPathTemp) == 0 or die "failed to create initrd secrets: $!\n"; + # Check whether any secrets were actually added + if (-e $initrdSecretsPathTemp && ! -z _) { + rename $initrdSecretsPathTemp, $initrdSecretsPath or die "failed to move initrd secrets into place: $!\n"; + $copied{$initrdSecretsPath} = 1; + $initrd .= " " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$initrdName-secrets"; + } else { + unlink $initrdSecretsPathTemp; + rmdir dirname($initrdSecretsPathTemp); + } + umask $oldUmask; } my $xen = -e "$path/xen.gz" ? copyToKernelsDir(Cwd::abs_path("$path/xen.gz")) : undef; @@ -459,9 +459,8 @@ sub addEntry { # FIXME: $confName my $kernelParams = - "systemConfig=" . Cwd::abs_path($path) . " " . - "init=" . Cwd::abs_path("$path/init") . " " . - readFile("$path/kernel-params"); + "init=" . Cwd::abs_path("$path/init") . " " . + readFile("$path/kernel-params"); my $xenParams = $xen && -e "$path/xen-params" ? readFile("$path/xen-params") : ""; if ($grubVersion == 1) { @@ -503,9 +502,9 @@ foreach my $link (@links) { my $date = strftime("%F", localtime(lstat($link)->mtime)); my $version = - -e "$link/nixos-version" - ? readFile("$link/nixos-version") - : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); + -e "$link/nixos-version" + ? readFile("$link/nixos-version") + : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); if ($cfgName) { $entryName = $cfgName; @@ -530,8 +529,8 @@ sub addProfile { sub nrFromGen { my ($x) = @_; $x =~ /\/\w+-(\d+)-link/; return $1; } my @links = sort - { nrFromGen($b) <=> nrFromGen($a) } - (glob "$profile-*-link"); + { nrFromGen($b) <=> nrFromGen($a) } + (glob "$profile-*-link"); my $curEntry = 0; foreach my $link (@links) { @@ -542,9 +541,9 @@ sub addProfile { } my $date = strftime("%F", localtime(lstat($link)->mtime)); my $version = - -e "$link/nixos-version" - ? readFile("$link/nixos-version") - : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); + -e "$link/nixos-version" + ? readFile("$link/nixos-version") + : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link); } @@ -566,7 +565,7 @@ $extraPrepareConfig =~ s/\@bootPath\@/$bootPath/g; # Run extraPrepareConfig in sh if ($extraPrepareConfig ne "") { - system((get("shell"), "-c", $extraPrepareConfig)); + system((get("shell"), "-c", $extraPrepareConfig)); } # write the GRUB config. @@ -627,13 +626,13 @@ foreach my $fn (glob "$bootPath/kernels/*") { # struct(GrubState => { - name => '$', - version => '$', - efi => '$', - devices => '$', - efiMountPoint => '$', - extraGrubInstallArgs => '@', -}); + name => '$', + version => '$', + efi => '$', + devices => '$', + efiMountPoint => '$', + extraGrubInstallArgs => '@', + }); # If you add something to the state file, only add it to the end # because it is read line-by-line. sub readGrubState { diff --git a/nixos/modules/system/boot/loader/init-script/init-script-builder.sh b/nixos/modules/system/boot/loader/init-script/init-script-builder.sh index 2a1ec479fea04..bd3fc64999da5 100644 --- a/nixos/modules/system/boot/loader/init-script/init-script-builder.sh +++ b/nixos/modules/system/boot/loader/init-script/init-script-builder.sh @@ -49,7 +49,6 @@ addEntry() { echo "#!/bin/sh" echo "# $name" echo "# created by init-script-builder.sh" - echo "export systemConfig=$(readlink -f $path)" echo "exec $stage2" )" diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index 97e824fe629ce..6bee900c68304 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -101,7 +101,7 @@ def write_entry(profile, generation, machine_id): entry_file = "@efiSysMountPoint@/loader/entries/nixos-generation-%d.conf" % (generation) generation_dir = os.readlink(system_dir(profile, generation)) tmp_path = "%s.tmp" % (entry_file) - kernel_params = "systemConfig=%s init=%s/init " % (generation_dir, generation_dir) + kernel_params = "init=%s/init " % generation_dir with open("%s/kernel-params" % (generation_dir)) as params_file: kernel_params = kernel_params + params_file.read() diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix index 8dd2ea20519a1..fa14d86e253df 100644 --- a/nixos/modules/system/boot/luksroot.nix +++ b/nixos/modules/system/boot/luksroot.nix @@ -56,7 +56,7 @@ let ykinfo -v 1>/dev/null 2>&1 if [ $? != 0 ]; then - echo -n "Waiting $secs seconds for Yubikey to appear..." + echo -n "Waiting $secs seconds for YubiKey to appear..." local success=false for try in $(seq $secs); do echo -n . @@ -118,7 +118,7 @@ let # Cryptsetup locking directory mkdir -p /run/cryptsetup - # For Yubikey salt storage + # For YubiKey salt storage mkdir -p /crypt-storage ${optionalString luks.gpgSupport '' @@ -218,7 +218,7 @@ let } ${optionalString (luks.yubikeySupport && (yubikey != null)) '' - # Yubikey + # YubiKey rbtohex() { ( od -An -vtx1 | tr -d ' \n' ) } @@ -244,7 +244,7 @@ let local new_k_luks mount -t ${yubikey.storage.fsType} ${yubikey.storage.device} /crypt-storage || \ - die "Failed to mount Yubikey salt storage device" + die "Failed to mount YubiKey salt storage device" salt="$(cat /crypt-storage${yubikey.storage.path} | sed -n 1p | tr -d '\n')" iterations="$(cat /crypt-storage${yubikey.storage.path} | sed -n 2p | tr -d '\n')" @@ -254,8 +254,27 @@ let for try in $(seq 3); do ${optionalString yubikey.twoFactor '' echo -n "Enter two-factor passphrase: " - read -r k_user - echo + k_user= + while true; do + if [ -e /crypt-ramfs/passphrase ]; then + echo "reused" + k_user=$(cat /crypt-ramfs/passphrase) + break + else + # Try reading it from /dev/console with a timeout + IFS= read -t 1 -r k_user + if [ -n "$k_user" ]; then + ${if luks.reusePassphrases then '' + # Remember it for the next device + echo -n "$k_user" > /crypt-ramfs/passphrase + '' else '' + # Don't save it to ramfs. We are very paranoid + ''} + echo + break + fi + fi + done ''} if [ ! -z "$k_user" ]; then @@ -268,6 +287,11 @@ let if [ $? == 0 ]; then opened=true + ${if luks.reusePassphrases then '' + # We don't rm here because we might reuse it for the next device + '' else '' + rm -f /crypt-ramfs/passphrase + ''} break else opened=false @@ -317,7 +341,7 @@ let if wait_yubikey ${toString yubikey.gracePeriod}; then do_open_yubikey else - echo "No yubikey found, falling back to non-yubikey open procedure" + echo "No YubiKey found, falling back to non-YubiKey open procedure" open_normally fi } @@ -665,8 +689,8 @@ in yubikey = mkOption { default = null; description = '' - The options to use for this LUKS device in Yubikey-PBA. - If null (the default), Yubikey-PBA will be disabled for this device. + The options to use for this LUKS device in YubiKey-PBA. + If null (the default), YubiKey-PBA will be disabled for this device. ''; type = with types; nullOr (submodule { @@ -674,13 +698,13 @@ in twoFactor = mkOption { default = true; type = types.bool; - description = "Whether to use a passphrase and a Yubikey (true), or only a Yubikey (false)."; + description = "Whether to use a passphrase and a YubiKey (true), or only a YubiKey (false)."; }; slot = mkOption { default = 2; type = types.int; - description = "Which slot on the Yubikey to challenge."; + description = "Which slot on the YubiKey to challenge."; }; saltLength = mkOption { @@ -704,7 +728,7 @@ in gracePeriod = mkOption { default = 10; type = types.int; - description = "Time in seconds to wait for the Yubikey."; + description = "Time in seconds to wait for the YubiKey."; }; /* TODO: Add to the documentation of the current module: @@ -779,9 +803,9 @@ in default = false; type = types.bool; description = '' - Enables support for authenticating with a Yubikey on LUKS devices. + Enables support for authenticating with a YubiKey on LUKS devices. See the NixOS wiki for information on how to properly setup a LUKS device - and a Yubikey to work with this feature. + and a YubiKey to work with this feature. ''; }; @@ -799,7 +823,7 @@ in assertions = [ { assertion = !(luks.gpgSupport && luks.yubikeySupport); - message = "Yubikey and GPG Card may not be used at the same time."; + message = "YubiKey and GPG Card may not be used at the same time."; } { assertion = !(luks.gpgSupport && luks.fido2Support); @@ -807,7 +831,7 @@ in } { assertion = !(luks.fido2Support && luks.yubikeySupport); - message = "FIDO2 and Yubikey may not be used at the same time."; + message = "FIDO2 and YubiKey may not be used at the same time."; } ]; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 444580bc0bed6..c31a20e540883 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -81,6 +81,7 @@ in corerad = handleTest ./corerad.nix {}; couchdb = handleTest ./couchdb.nix {}; cri-o = handleTestOn ["x86_64-linux"] ./cri-o.nix {}; + custom-ca = handleTest ./custom-ca.nix {}; deluge = handleTest ./deluge.nix {}; dhparams = handleTest ./dhparams.nix {}; dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {}; @@ -332,7 +333,6 @@ in redis = handleTest ./redis.nix {}; redmine = handleTest ./redmine.nix {}; restic = handleTest ./restic.nix {}; - ripgrep = handleTest ./ripgrep.nix {}; robustirc-bridge = handleTest ./robustirc-bridge.nix {}; roundcube = handleTest ./roundcube.nix {}; rspamd = handleTest ./rspamd.nix {}; diff --git a/nixos/tests/custom-ca.nix b/nixos/tests/custom-ca.nix new file mode 100644 index 0000000000000..67f7b3ff1f161 --- /dev/null +++ b/nixos/tests/custom-ca.nix @@ -0,0 +1,161 @@ +# Checks that `security.pki` options are working in curl and the main browser +# engines: Gecko (via Firefox), Chromium, QtWebEngine (Falkon) and WebKitGTK +# (via Midori). The test checks that certificates issued by a custom trusted +# CA are accepted but those from an unknown CA are rejected. + +import ./make-test-python.nix ({ pkgs, lib, ... }: + +let + makeCert = { caName, domain }: pkgs.runCommand "example-cert" + { buildInputs = [ pkgs.gnutls ]; } + '' + mkdir $out + + # CA cert template + cat >ca.template <<EOF + organization = "${caName}" + cn = "${caName}" + expiration_days = 365 + ca + cert_signing_key + crl_signing_key + EOF + + # server cert template + cat >server.template <<EOF + organization = "An example company" + cn = "${domain}" + expiration_days = 30 + dns_name = "${domain}" + encryption_key + signing_key + EOF + + # generate CA keypair + certtool \ + --generate-privkey \ + --key-type rsa \ + --sec-param High \ + --outfile $out/ca.key + certtool \ + --generate-self-signed \ + --load-privkey $out/ca.key \ + --template ca.template \ + --outfile $out/ca.crt + + # generate server keypair + certtool \ + --generate-privkey \ + --key-type rsa \ + --sec-param High \ + --outfile $out/server.key + certtool \ + --generate-certificate \ + --load-privkey $out/server.key \ + --load-ca-privkey $out/ca.key \ + --load-ca-certificate $out/ca.crt \ + --template server.template \ + --outfile $out/server.crt + ''; + + example-good-cert = makeCert + { caName = "Example good CA"; + domain = "good.example.com"; + }; + + example-bad-cert = makeCert + { caName = "Unknown CA"; + domain = "bad.example.com"; + }; + +in + +{ + name = "custom-ca"; + meta.maintainers = with lib.maintainers; [ rnhmjoj ]; + + enableOCR = true; + + machine = { pkgs, ... }: + { imports = [ ./common/user-account.nix ./common/x11.nix ]; + + # chromium-based browsers refuse to run as root + test-support.displayManager.auto.user = "alice"; + # browsers may hang with the default memory + virtualisation.memorySize = "500"; + + networking.hosts."127.0.0.1" = [ "good.example.com" "bad.example.com" ]; + security.pki.certificateFiles = [ "${example-good-cert}/ca.crt" ]; + + services.nginx.enable = true; + services.nginx.virtualHosts."good.example.com" = + { onlySSL = true; + sslCertificate = "${example-good-cert}/server.crt"; + sslCertificateKey = "${example-good-cert}/server.key"; + locations."/".extraConfig = "return 200 'It works!';"; + }; + services.nginx.virtualHosts."bad.example.com" = + { onlySSL = true; + sslCertificate = "${example-bad-cert}/server.crt"; + sslCertificateKey = "${example-bad-cert}/server.key"; + locations."/".extraConfig = "return 200 'It does not work!';"; + }; + + environment.systemPackages = with pkgs; + [ xdotool firefox chromium falkon midori ]; + }; + + testScript = '' + def execute_as(user: str, cmd: str) -> Tuple[int, str]: + """ + Run a shell command as a specific user. + """ + return machine.execute(f"sudo -u {user} {cmd}") + + + def wait_for_window_as(user: str, cls: str) -> None: + """ + Wait until a X11 window of a given user appears. + """ + + def window_is_visible(last_try: bool) -> bool: + ret, stdout = execute_as(user, f"xdotool search --onlyvisible --class {cls}") + if last_try: + machine.log(f"Last chance to match {cls} on the window list") + return ret == 0 + + with machine.nested("Waiting for a window to appear"): + retry(window_is_visible) + + + machine.start() + + with subtest("Good certificate is trusted in curl"): + machine.wait_for_unit("nginx") + machine.wait_for_open_port(443) + machine.succeed("curl -fv https://good.example.com") + + with subtest("Unknown CA is untrusted in curl"): + machine.fail("curl -fv https://bad.example.com") + + browsers = ["firefox", "chromium", "falkon", "midori"] + errors = ["Security Risk", "not private", "Certificate Error", "Security"] + + machine.wait_for_x() + for browser, error in zip(browsers, errors): + with subtest("Good certificate is trusted in " + browser): + execute_as( + "alice", f"env P11_KIT_DEBUG=trust {browser} https://good.example.com & >&2" + ) + wait_for_window_as("alice", browser) + machine.wait_for_text("It works!") + machine.screenshot("good" + browser) + execute_as("alice", "xdotool key ctrl+w") # close tab + + with subtest("Unknown CA is untrusted in " + browser): + execute_as("alice", f"{browser} https://bad.example.com & >&2") + machine.wait_for_text(error) + machine.screenshot("bad" + browser) + machine.succeed("pkill " + browser) + ''; +}) diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index 789add331b793..904ec17229e1c 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -325,10 +325,13 @@ let curl ] ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub - ++ optionals (bootLoader == "grub" && grubVersion == 2) [ - (pkgs.grub2.override { zfsSupport = true; }) - (pkgs.grub2_efi.override { zfsSupport = true; }) - ]; + ++ optionals (bootLoader == "grub" && grubVersion == 2) (let + zfsSupport = lib.any (x: x == "zfs") + (extraInstallerConfig.boot.supportedFilesystems or []); + in [ + (pkgs.grub2.override { inherit zfsSupport; }) + (pkgs.grub2_efi.override { inherit zfsSupport; }) + ]); nix.binaryCaches = mkForce [ ]; nix.extraOptions = '' @@ -398,9 +401,9 @@ let createPartitions = '' machine.succeed( "flock /dev/vda parted --script /dev/vda -- mklabel gpt" - + " mkpart ESP fat32 1M 50MiB" # /boot + + " mkpart ESP fat32 1M 100MiB" # /boot + " set 1 boot on" - + " mkpart primary linux-swap 50MiB 1024MiB" + + " mkpart primary linux-swap 100MiB 1024MiB" + " mkpart primary ext2 1024MiB -1MiB", # / "udevadm settle", "mkswap /dev/vda2 -L swap", diff --git a/nixos/tests/openldap.nix b/nixos/tests/openldap.nix index 392fae243467b..f1a39ad7dde2f 100644 --- a/nixos/tests/openldap.nix +++ b/nixos/tests/openldap.nix @@ -1,4 +1,9 @@ -{ pkgs, system ? builtins.currentSystem, ... }: let +{ pkgs ? (import ../.. { inherit system; config = { }; }) +, system ? builtins.currentSystem +, ... +}: + +let dbContents = '' dn: dc=example objectClass: domain @@ -16,7 +21,7 @@ ''; in { # New-style configuration - current = import ./make-test-python.nix { + current = import ./make-test-python.nix ({ pkgs, ... }: { inherit testScript; name = "openldap"; @@ -53,10 +58,10 @@ in { declarativeContents."dc=example" = dbContents; }; }; - }; + }) { inherit pkgs system; }; # Old-style configuration - oldOptions = import ./make-test-python.nix { + oldOptions = import ./make-test-python.nix ({ pkgs, ... }: { inherit testScript; name = "openldap"; @@ -72,10 +77,10 @@ in { declarativeContents."dc=example" = dbContents; }; }; - }; + }) { inherit system pkgs; }; # Manually managed configDir, for example if dynamic config is essential - manualConfigDir = import ./make-test-python.nix { + manualConfigDir = import ./make-test-python.nix ({ pkgs, ... }: { name = "openldap"; machine = { pkgs, ... }: { @@ -121,5 +126,5 @@ in { "systemctl restart openldap", ) '' + testScript; - }; + }) { inherit system pkgs; }; } diff --git a/nixos/tests/ripgrep.nix b/nixos/tests/ripgrep.nix deleted file mode 100644 index 3ff3bf4be1518..0000000000000 --- a/nixos/tests/ripgrep.nix +++ /dev/null @@ -1,13 +0,0 @@ -import ./make-test-python.nix ({ pkgs, ... }: { - name = "ripgrep"; - meta = with pkgs.lib.maintainers; { maintainers = [ nequissimus ]; }; - - nodes.ripgrep = { pkgs, ... }: { environment.systemPackages = [ pkgs.ripgrep ]; }; - - testScript = '' - ripgrep.succeed('echo "abc\nbcd\ncde" > /tmp/foo') - assert "bcd" in ripgrep.succeed("rg -N 'bcd' /tmp/foo") - assert "bcd\ncde" in ripgrep.succeed("rg -N 'cd' /tmp/foo") - assert "ripgrep ${pkgs.ripgrep.version}" in ripgrep.succeed("rg --version | head -1") - ''; -}) |