diff options
author | Frederik Rietdijk <fridh@fridh.nl> | 2020-11-01 10:11:12 +0100 |
---|---|---|
committer | Frederik Rietdijk <fridh@fridh.nl> | 2020-11-01 10:11:12 +0100 |
commit | 83dde6c52c72bbc941525e8688f97ec65240432d (patch) | |
tree | 252817588d902c5952cb49be3871ab9d882ceb29 /nixos | |
parent | b57adad0851ee7171676cfc168518fa23418d265 (diff) | |
parent | 7a8d5dc8a676a528186ea0f2ece97e832d784562 (diff) |
Merge staging-next into staging
Diffstat (limited to 'nixos')
47 files changed, 456 insertions, 123 deletions
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix index 6ca75f869f45c..af7a2e08220c1 100644 --- a/nixos/doc/manual/default.nix +++ b/nixos/doc/manual/default.nix @@ -63,6 +63,7 @@ let "--stringparam html.script './highlightjs/highlight.pack.js ./highlightjs/loader.js'" "--param xref.with.number.and.title 1" "--param toc.section.depth 0" + "--param generate.consistent.ids 1" "--stringparam admon.style ''" "--stringparam callout.graphics.extension .svg" "--stringparam current.docid manual" diff --git a/nixos/doc/manual/man-nixos-install.xml b/nixos/doc/manual/man-nixos-install.xml index b205e23096875..91542d37cbd55 100644 --- a/nixos/doc/manual/man-nixos-install.xml +++ b/nixos/doc/manual/man-nixos-install.xml @@ -50,6 +50,12 @@ </arg> <arg> + <group choice='req'> + <arg choice='plain'><option>--impure</option></arg> + </group> + </arg> + + <arg> <arg choice='plain'> <option>--channel</option> </arg> @@ -102,6 +108,12 @@ <arg> <arg choice='plain'> + <option>--keep-going</option> + </arg> + </arg> + + <arg> + <arg choice='plain'> <option>--help</option> </arg> </arg> @@ -297,6 +309,17 @@ </varlistentry> <varlistentry> <term> + <option>--keep-going</option> + </term> + <listitem> + <para> + Causes Nix to continue building derivations as far as possible + in the face of failed builds. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> <option>--help</option> </term> <listitem> diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml index c399c22eef558..01f113198eb92 100644 --- a/nixos/doc/manual/release-notes/rl-2009.xml +++ b/nixos/doc/manual/release-notes/rl-2009.xml @@ -1618,7 +1618,7 @@ services.transmission.settings.rpc-bind-address = "0.0.0.0"; nixpkgs. It was a work in progress to package the <link xlink:href="https://www.deepin.org/en/dde/">Deepin Desktop Environment (DDE)</link>, including libraries, tools and applications, and it was still - missing a service to lauch the desktop environment. It has shown + missing a service to launch the desktop environment. It has shown to no longer be a feasible goal due to reasons discussed in <link xlink:href="https://github.com/NixOS/nixpkgs/issues/94870">issue #94870</link>. The package <literal>netease-cloud-music</literal> has also been diff --git a/nixos/doc/manual/release-notes/rl-2103.xml b/nixos/doc/manual/release-notes/rl-2103.xml index 54a731b15bc29..2fc87154b2ce1 100644 --- a/nixos/doc/manual/release-notes/rl-2103.xml +++ b/nixos/doc/manual/release-notes/rl-2103.xml @@ -135,6 +135,14 @@ to <package>nextcloud20</package>. </para> </listitem> + <listitem> + <para> + NixOS now emits a deprecation warning if systemd's <literal>StartLimitInterval</literal> setting is used in a <literal>serviceConfig</literal> section instead of in a <literal>unitConfig</literal>; that setting is deprecated and now undocumented for the service section by systemd upstream, but still effective and somewhat buggy there, which can be confusing. See <link xlink:href="https://github.com/NixOS/nixpkgs/issues/45785">#45785</link> for details. + </para> + <para> + All services should use <xref linkend="opt-systemd.services._name_.startLimitIntervalSec" /> or <literal>StartLimitIntervalSec</literal> in <xref linkend="opt-systemd.services._name_.unitConfig" /> instead. + </para> + </listitem> </itemizedlist> </section> </section> diff --git a/nixos/lib/make-disk-image.nix b/nixos/lib/make-disk-image.nix index 8aa606a56af80..a4a488a1b3ea9 100644 --- a/nixos/lib/make-disk-image.nix +++ b/nixos/lib/make-disk-image.nix @@ -28,6 +28,9 @@ # partition of reasonable size is created in addition to the root partition. # For "legacy", the msdos partition table is used and a single large root # partition is created. + # For "legacy+gpt", the GPT partition table is used, a 1MiB no-fs partition for + # use by the bootloader is created, and a single large root partition is + # created. # For "hybrid", the GPT partition table is used and a mandatory ESP # partition of reasonable size is created in addition to the root partition. # Also a legacy MBR will be present. @@ -54,7 +57,7 @@ format ? "raw" }: -assert partitionTableType == "legacy" || partitionTableType == "efi" || partitionTableType == "hybrid" || partitionTableType == "none"; +assert partitionTableType == "legacy" || partitionTableType == "legacy+gpt" || partitionTableType == "efi" || partitionTableType == "hybrid" || partitionTableType == "none"; # We use -E offset=X below, which is only supported by e2fsprogs assert partitionTableType != "none" -> fsType == "ext4"; @@ -75,6 +78,7 @@ let format' = format; in let rootPartition = { # switch-case legacy = "1"; + "legacy+gpt" = "2"; efi = "2"; hybrid = "3"; }.${partitionTableType}; @@ -85,6 +89,16 @@ let format' = format; in let mklabel msdos \ mkpart primary ext4 1MiB -1 ''; + "legacy+gpt" = '' + parted --script $diskImage -- \ + mklabel gpt \ + mkpart no-fs 1MB 2MB \ + set 1 bios_grub on \ + align-check optimal 1 \ + mkpart primary ext4 2MB -1 \ + align-check optimal 2 \ + print + ''; efi = '' parted --script $diskImage -- \ mklabel gpt \ diff --git a/nixos/maintainers/scripts/ec2/amazon-image.nix b/nixos/maintainers/scripts/ec2/amazon-image.nix index b09f4ca47a3fc..0ecf07669a119 100644 --- a/nixos/maintainers/scripts/ec2/amazon-image.nix +++ b/nixos/maintainers/scripts/ec2/amazon-image.nix @@ -57,7 +57,7 @@ in { inherit (cfg) contents format name; pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package partitionTableType = if config.ec2.efi then "efi" - else if config.ec2.hvm then "legacy" + else if config.ec2.hvm then "legacy+gpt" else "none"; diskSize = cfg.sizeMB; fsType = "ext4"; diff --git a/nixos/maintainers/scripts/ec2/create-amis.sh b/nixos/maintainers/scripts/ec2/create-amis.sh index 89e24f2ccfd95..ec2eb53667901 100755 --- a/nixos/maintainers/scripts/ec2/create-amis.sh +++ b/nixos/maintainers/scripts/ec2/create-amis.sh @@ -1,13 +1,15 @@ #!/usr/bin/env nix-shell #!nix-shell -p awscli -p jq -p qemu -i bash +# shellcheck shell=bash # Uploads and registers NixOS images built from the # <nixos/release.nix> amazonImage attribute. Images are uploaded and # registered via a home region, and then copied to other regions. -# The home region requires an s3 bucket, and a "vmimport" IAM role -# with access to the S3 bucket. Configuration of the vmimport role is -# documented in +# The home region requires an s3 bucket, and an IAM role named "vmimport" +# (by default) with access to the S3 bucket. The name can be +# configured with the "service_role_name" variable. Configuration of the +# vmimport role is documented in # https://docs.aws.amazon.com/vm-import/latest/userguide/vmimport-image-import.html # set -x @@ -17,6 +19,7 @@ set -euo pipefail state_dir=$HOME/amis/ec2-images home_region=eu-west-1 bucket=nixos-amis +service_role_name=vmimport regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1 eu-north-1 us-east-1 us-east-2 us-west-1 us-west-2 @@ -64,7 +67,7 @@ image_logical_bytes=$(read_image_info .logical_bytes) # Derived attributes -image_logical_gigabytes=$((($image_logical_bytes-1)/1024/1024/1024+1)) # Round to the next GB +image_logical_gigabytes=$(((image_logical_bytes-1)/1024/1024/1024+1)) # Round to the next GB case "$image_system" in aarch64-linux) @@ -100,7 +103,7 @@ write_state() { local type=$2 local val=$3 - mkdir -p $state_dir + mkdir -p "$state_dir" echo "$val" > "$state_dir/$state_key.$type" } @@ -110,8 +113,8 @@ wait_for_import() { local state snapshot_id log "Waiting for import task $task_id to be completed" while true; do - read state progress snapshot_id < <( - aws ec2 describe-import-snapshot-tasks --region $region --import-task-ids "$task_id" | \ + read -r state progress snapshot_id < <( + aws ec2 describe-import-snapshot-tasks --region "$region" --import-task-ids "$task_id" | \ jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail | "\(.Status) \(.Progress) \(.SnapshotId)"' ) log " ... state=$state progress=$progress snapshot_id=$snapshot_id" @@ -125,6 +128,8 @@ wait_for_import() { ;; *) log "Unexpected snapshot import state: '${state}'" + log "Full response: " + aws ec2 describe-import-snapshot-tasks --region "$region" --import-task-ids "$task_id" >&2 exit 1 ;; esac @@ -138,8 +143,8 @@ wait_for_image() { log "Waiting for image $ami_id to be available" while true; do - read state < <( - aws ec2 describe-images --image-ids "$ami_id" --region $region | \ + read -r state < <( + aws ec2 describe-images --image-ids "$ami_id" --region "$region" | \ jq -r ".Images[].State" ) log " ... state=$state" @@ -163,7 +168,7 @@ make_image_public() { local region=$1 local ami_id=$2 - wait_for_image $region "$ami_id" + wait_for_image "$region" "$ami_id" log "Making image $ami_id public" @@ -177,27 +182,30 @@ upload_image() { local aws_path=${image_file#/} local state_key="$region.$image_label.$image_system" - local task_id=$(read_state "$state_key" task_id) - local snapshot_id=$(read_state "$state_key" snapshot_id) - local ami_id=$(read_state "$state_key" ami_id) + local task_id + task_id=$(read_state "$state_key" task_id) + local snapshot_id + snapshot_id=$(read_state "$state_key" snapshot_id) + local ami_id + ami_id=$(read_state "$state_key" ami_id) if [ -z "$task_id" ]; then log "Checking for image on S3" if ! aws s3 ls --region "$region" "s3://${bucket}/${aws_path}" >&2; then log "Image missing from aws, uploading" - aws s3 cp --region $region "$image_file" "s3://${bucket}/${aws_path}" >&2 + aws s3 cp --region "$region" "$image_file" "s3://${bucket}/${aws_path}" >&2 fi log "Importing image from S3 path s3://$bucket/$aws_path" - task_id=$(aws ec2 import-snapshot --disk-container "{ + task_id=$(aws ec2 import-snapshot --role-name "$service_role_name" --disk-container "{ \"Description\": \"nixos-image-${image_label}-${image_system}\", \"Format\": \"vhd\", \"UserBucket\": { \"S3Bucket\": \"$bucket\", \"S3Key\": \"$aws_path\" } - }" --region $region | jq -r '.ImportTaskId') + }" --region "$region" | jq -r '.ImportTaskId') write_state "$state_key" task_id "$task_id" fi @@ -221,16 +229,16 @@ upload_image() { --virtualization-type hvm ) - block_device_mappings+=(DeviceName=/dev/sdb,VirtualName=ephemeral0) - block_device_mappings+=(DeviceName=/dev/sdc,VirtualName=ephemeral1) - block_device_mappings+=(DeviceName=/dev/sdd,VirtualName=ephemeral2) - block_device_mappings+=(DeviceName=/dev/sde,VirtualName=ephemeral3) + block_device_mappings+=("DeviceName=/dev/sdb,VirtualName=ephemeral0") + block_device_mappings+=("DeviceName=/dev/sdc,VirtualName=ephemeral1") + block_device_mappings+=("DeviceName=/dev/sdd,VirtualName=ephemeral2") + block_device_mappings+=("DeviceName=/dev/sde,VirtualName=ephemeral3") ami_id=$( aws ec2 register-image \ --name "$image_name" \ --description "$image_description" \ - --region $region \ + --region "$region" \ --architecture $amazon_arch \ --block-device-mappings "${block_device_mappings[@]}" \ "${extra_flags[@]}" \ @@ -240,7 +248,7 @@ upload_image() { write_state "$state_key" ami_id "$ami_id" fi - make_image_public $region "$ami_id" + make_image_public "$region" "$ami_id" echo "$ami_id" } @@ -268,7 +276,7 @@ copy_to_region() { write_state "$state_key" ami_id "$ami_id" fi - make_image_public $region "$ami_id" + make_image_public "$region" "$ami_id" echo "$ami_id" } diff --git a/nixos/modules/config/fonts/fontdir.nix b/nixos/modules/config/fonts/fontdir.nix index 264d73ebafa53..c4bd3a077d339 100644 --- a/nixos/modules/config/fonts/fontdir.nix +++ b/nixos/modules/config/fonts/fontdir.nix @@ -8,7 +8,7 @@ let x11Fonts = pkgs.runCommand "X11-fonts" { preferLocalBuild = true; } '' mkdir -p "$out/share/X11/fonts" - font_regexp='.*\.\(ttf\|otf\|pcf\|pfa\|pfb\|bdf\)\(\.gz\)?' + font_regexp='.*\.\(ttf\|ttc\|otf\|pcf\|pfa\|pfb\|bdf\)\(\.gz\)?' find ${toString config.fonts.fonts} -regex "$font_regexp" \ -exec ln -sf -t "$out/share/X11/fonts" '{}' \; cd "$out/share/X11/fonts" diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index 90555f1458036..9d49d4055e431 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -64,7 +64,7 @@ while [ "$#" -gt 0 ]; do --no-bootloader) noBootLoader=1 ;; - --show-trace) + --show-trace|--impure|--keep-going) extraBuildFlags+=("$i") ;; --help) diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index cd21a1609c915..4e0f8ba718eba 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -468,7 +468,7 @@ in #minecraft = 114; # unused vault = 115; #ripped = 116; # unused - #murmur = 117; # unused + murmur = 117; foundationdb = 118; newrelic = 119; starbound = 120; diff --git a/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix b/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix index d2e7e8e18f94e..79d1ce5805457 100644 --- a/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix +++ b/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix @@ -25,19 +25,18 @@ in ]; config = mkIf cfg.enable { - systemd.services.hercules-ci-agent = { wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; path = [ config.nix.package ]; + startLimitBurst = 30 * 1000000; # practically infinite serviceConfig = { User = "hercules-ci-agent"; ExecStart = command; ExecStartPre = testCommand; Restart = "on-failure"; RestartSec = 120; - StartLimitBurst = 30 * 1000000; # practically infinite }; }; diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index 5056d50153f6d..f582b0592774f 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -69,11 +69,16 @@ in type = types.lines; default = ""; description = '' - Defines how users authenticate themselves to the server. By - default, "trust" access to local users will always be granted - along with any other custom options. If you do not want this, - set this option using "lib.mkForce" to override this - behaviour. + Defines how users authenticate themselves to the server. See the + <link xlink:href="https://www.postgresql.org/docs/current/auth-pg-hba-conf.html"> + PostgreSQL documentation for pg_hba.conf</link> + for details on the expected format of this option. By default, + peer based authentication will be used for users connecting + via the Unix socket, and md5 password authentication will be + used for users connecting via TCP. Any added rules will be + inserted above the default rules. If you'd like to replace the + default rules entirely, you can use <function>lib.mkForce</function> in your + module. ''; }; diff --git a/nixos/modules/services/databases/victoriametrics.nix b/nixos/modules/services/databases/victoriametrics.nix index 0af5d2adf3724..5b09115bb2fb0 100644 --- a/nixos/modules/services/databases/victoriametrics.nix +++ b/nixos/modules/services/databases/victoriametrics.nix @@ -40,10 +40,10 @@ let cfg = config.services.victoriametrics; in systemd.services.victoriametrics = { description = "VictoriaMetrics time series database"; after = [ "network.target" ]; + startLimitBurst = 5; serviceConfig = { Restart = "on-failure"; RestartSec = 1; - StartLimitBurst = 5; StateDirectory = "victoriametrics"; DynamicUser = true; ExecStart = '' diff --git a/nixos/modules/services/hardware/lcd.nix b/nixos/modules/services/hardware/lcd.nix index d78d742cd3185..dc8595ea60cde 100644 --- a/nixos/modules/services/hardware/lcd.nix +++ b/nixos/modules/services/hardware/lcd.nix @@ -151,14 +151,13 @@ in with lib; { description = "LCDproc - client"; after = [ "lcdd.service" ]; wantedBy = [ "lcd.target" ]; + # Allow restarting for eternity + startLimitIntervalSec = lib.mkIf cfg.client.restartForever 0; serviceConfig = serviceCfg // { ExecStart = "${pkg}/bin/lcdproc -f -c ${clientCfg}"; # If the server is being restarted at the same time, the client will # fail as it cannot connect, so space it out a bit. RestartSec = "5"; - # Allow restarting for eternity - StartLimitIntervalSec = lib.mkIf cfg.client.restartForever "0"; - StartLimitBurst = lib.mkIf cfg.client.restartForever "0"; }; }; }; diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix index 054ffa35050a9..9c2f78a755ddd 100644 --- a/nixos/modules/services/hardware/undervolt.nix +++ b/nixos/modules/services/hardware/undervolt.nix @@ -3,7 +3,12 @@ with lib; let cfg = config.services.undervolt; - cliArgs = lib.cli.toGNUCommandLineShell {} { + + mkPLimit = limit: window: + if (isNull limit && isNull window) then null + else assert asserts.assertMsg (!isNull limit && !isNull window) "Both power limit and window must be set"; + "${toString limit} ${toString window}"; + cliArgs = lib.cli.toGNUCommandLine {} { inherit (cfg) verbose temp @@ -21,6 +26,9 @@ let temp-bat = cfg.tempBat; temp-ac = cfg.tempAc; + + power-limit-long = mkPLimit cfg.p1.limit cfg.p1.window; + power-limit-short = mkPLimit cfg.p2.limit cfg.p2.window; }; in { @@ -104,6 +112,40 @@ in ''; }; + p1.limit = mkOption { + type = with types; nullOr int; + default = null; + description = '' + The P1 Power Limit in Watts. + Both limit and window must be set. + ''; + }; + p1.window = mkOption { + type = with types; nullOr (oneOf [ float int ]); + default = null; + description = '' + The P1 Time Window in seconds. + Both limit and window must be set. + ''; + }; + + p2.limit = mkOption { + type = with types; nullOr int; + default = null; + description = '' + The P2 Power Limit in Watts. + Both limit and window must be set. + ''; + }; + p2.window = mkOption { + type = with types; nullOr (oneOf [ float int ]); + default = null; + description = '' + The P2 Time Window in seconds. + Both limit and window must be set. + ''; + }; + useTimer = mkOption { type = types.bool; default = false; @@ -133,7 +175,7 @@ in serviceConfig = { Type = "oneshot"; Restart = "no"; - ExecStart = "${pkgs.undervolt}/bin/undervolt ${cliArgs}"; + ExecStart = "${pkgs.undervolt}/bin/undervolt ${toString cliArgs}"; }; }; diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index f5c5f795dc1b6..03e7e40e388e1 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -427,12 +427,12 @@ in wantedBy = [ "multi-user.target" ]; restartTriggers = [ cfg.configFile modulesDir ]; + startLimitIntervalSec = 60; # 1 min serviceConfig = { ExecStart = "${dovecotPkg}/sbin/dovecot -F"; ExecReload = "${dovecotPkg}/sbin/doveadm reload"; Restart = "on-failure"; RestartSec = "1s"; - StartLimitInterval = "1min"; RuntimeDirectory = [ "dovecot2" ]; }; diff --git a/nixos/modules/services/misc/autorandr.nix b/nixos/modules/services/misc/autorandr.nix index cf7fb5f78d3d5..dfb418af6edeb 100644 --- a/nixos/modules/services/misc/autorandr.nix +++ b/nixos/modules/services/misc/autorandr.nix @@ -37,9 +37,9 @@ in { description = "Autorandr execution hook"; after = [ "sleep.target" ]; + startLimitIntervalSec = 5; + startLimitBurst = 1; serviceConfig = { - StartLimitInterval = 5; - StartLimitBurst = 1; ExecStart = "${pkgs.autorandr}/bin/autorandr --batch --change --default ${cfg.defaultTarget}"; Type = "oneshot"; RemainAfterExit = false; diff --git a/nixos/modules/services/misc/cgminer.nix b/nixos/modules/services/misc/cgminer.nix index 7635c2a0f4e95..fa9c8c54509ea 100644 --- a/nixos/modules/services/misc/cgminer.nix +++ b/nixos/modules/services/misc/cgminer.nix @@ -126,12 +126,12 @@ in GPU_USE_SYNC_OBJECTS = "1"; }; + startLimitIntervalSec = 60; # 1 min serviceConfig = { ExecStart = "${pkgs.cgminer}/bin/cgminer --syslog --text-only --config ${cgminerConfig}"; User = cfg.user; RestartSec = "30s"; Restart = "always"; - StartLimitInterval = "1m"; }; }; diff --git a/nixos/modules/services/misc/safeeyes.nix b/nixos/modules/services/misc/safeeyes.nix index 6ecb0d13187c1..1e748195e41aa 100644 --- a/nixos/modules/services/misc/safeeyes.nix +++ b/nixos/modules/services/misc/safeeyes.nix @@ -32,14 +32,14 @@ in wantedBy = [ "graphical-session.target" ]; partOf = [ "graphical-session.target" ]; + startLimitIntervalSec = 350; + startLimitBurst = 10; serviceConfig = { ExecStart = '' ${pkgs.safeeyes}/bin/safeeyes ''; Restart = "on-failure"; RestartSec = 3; - StartLimitInterval = 350; - StartLimitBurst = 10; }; }; diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix index 98aaa9c0f030a..72428957109c6 100644 --- a/nixos/modules/services/monitoring/prometheus/default.nix +++ b/nixos/modules/services/monitoring/prometheus/default.nix @@ -45,7 +45,7 @@ let cmdlineArgs = cfg.extraFlags ++ [ "--storage.tsdb.path=${workingDir}/data/" - "--config.file=${prometheusYml}" + "--config.file=/run/prometheus/prometheus-substituted.yaml" "--web.listen-address=${cfg.listenAddress}:${builtins.toString cfg.port}" "--alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}" "--alertmanager.timeout=${toString cfg.alertmanagerTimeout}s" @@ -522,6 +522,45 @@ in { ''; }; + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/root/prometheus.env"; + description = '' + Environment file as defined in <citerefentry> + <refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum> + </citerefentry>. + + Secrets may be passed to the service without adding them to the + world-readable Nix store, by specifying placeholder variables as + the option value in Nix and setting these variables accordingly in the + environment file. + + Environment variables from this file will be interpolated into the + config file using envsubst with this syntax: + <literal>$ENVIRONMENT ''${VARIABLE}</literal> + + <programlisting> + # Example scrape config entry handling an OAuth bearer token + { + job_name = "home_assistant"; + metrics_path = "/api/prometheus"; + scheme = "https"; + bearer_token = "\''${HOME_ASSISTANT_BEARER_TOKEN}"; + [...] + } + </programlisting> + + <programlisting> + # Content of the environment file + HOME_ASSISTANT_BEARER_TOKEN=someoauthbearertoken + </programlisting> + + Note that this file needs to be available on the host on which + <literal>Prometheus</literal> is running. + ''; + }; + configText = mkOption { type = types.nullOr types.lines; default = null; @@ -662,12 +701,19 @@ in { systemd.services.prometheus = { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; + preStart = '' + ${lib.getBin pkgs.envsubst}/bin/envsubst -o "/run/prometheus/prometheus-substituted.yaml" \ + -i "${prometheusYml}" + ''; serviceConfig = { ExecStart = "${cfg.package}/bin/prometheus" + optionalString (length cmdlineArgs != 0) (" \\\n " + concatStringsSep " \\\n " cmdlineArgs); User = "prometheus"; Restart = "always"; + EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ]; + RuntimeDirectory = "prometheus"; + RuntimeDirectoryMode = "0700"; WorkingDirectory = workingDir; StateDirectory = cfg.stateDir; }; diff --git a/nixos/modules/services/monitoring/teamviewer.nix b/nixos/modules/services/monitoring/teamviewer.nix index 8d781d82d0864..ce9e57a187cdc 100644 --- a/nixos/modules/services/monitoring/teamviewer.nix +++ b/nixos/modules/services/monitoring/teamviewer.nix @@ -31,14 +31,14 @@ in after = [ "NetworkManager-wait-online.service" "network.target" ]; preStart = "mkdir -pv /var/lib/teamviewer /var/log/teamviewer"; + startLimitIntervalSec = 60; + startLimitBurst = 10; serviceConfig = { Type = "forking"; ExecStart = "${pkgs.teamviewer}/bin/teamviewerd -d"; PIDFile = "/run/teamviewerd.pid"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; Restart = "on-abort"; - StartLimitInterval = "60"; - StartLimitBurst = "10"; }; }; }; diff --git a/nixos/modules/services/network-filesystems/ceph.nix b/nixos/modules/services/network-filesystems/ceph.nix index d17959a6a3059..f2dc740fd88e9 100644 --- a/nixos/modules/services/network-filesystems/ceph.nix +++ b/nixos/modules/services/network-filesystems/ceph.nix @@ -28,6 +28,9 @@ let # Don't start services that are not yet initialized unitConfig.ConditionPathExists = "/var/lib/${stateDirectory}/keyring"; + startLimitBurst = + if daemonType == "osd" then 30 else if lib.elem daemonType ["mgr" "mds"] then 3 else 5; + startLimitIntervalSec = 60 * 30; # 30 mins serviceConfig = { LimitNOFILE = 1048576; @@ -39,8 +42,6 @@ let ProtectHome = "true"; ProtectSystem = "full"; Restart = "on-failure"; - StartLimitBurst = "5"; - StartLimitInterval = "30min"; StateDirectory = stateDirectory; User = "ceph"; Group = if daemonType == "osd" then "disk" else "ceph"; @@ -48,13 +49,10 @@ let -f --cluster ${clusterName} --id ${daemonId}''; } // optionalAttrs (daemonType == "osd") { ExecStartPre = ''${ceph.lib}/libexec/ceph/ceph-osd-prestart.sh --id ${daemonId} --cluster ${clusterName}''; - StartLimitBurst = "30"; RestartSec = "20s"; PrivateDevices = "no"; # osd needs disk access } // optionalAttrs ( daemonType == "mon") { RestartSec = "10"; - } // optionalAttrs (lib.elem daemonType ["mgr" "mds"]) { - StartLimitBurst = "3"; }; }); diff --git a/nixos/modules/services/networking/babeld.nix b/nixos/modules/services/networking/babeld.nix index e62c74d0069df..90395dbd3c54c 100644 --- a/nixos/modules/services/networking/babeld.nix +++ b/nixos/modules/services/networking/babeld.nix @@ -87,9 +87,37 @@ in description = "Babel routing daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - serviceConfig.ExecStart = "${pkgs.babeld}/bin/babeld -c ${configFile}"; + serviceConfig = { + ExecStart = "${pkgs.babeld}/bin/babeld -c ${configFile} -I /run/babeld/babeld.pid -S /var/lib/babeld/state"; + CapabilityBoundingSet = [ "CAP_NET_ADMIN" ]; + IPAddressAllow = [ "fe80::/64" "ff00::/8" "::1/128" "127.0.0.0/8" ]; + IPAddressDeny = "any"; + LockPersonality = true; + NoNewPrivileges = true; + MemoryDenyWriteExecute = true; + ProtectSystem = "strict"; + ProtectClock = true; + ProtectKernelTunables = false; # Couldn't write sysctl: Read-only file system + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictAddressFamilies = [ "AF_NETLINK" "AF_INET6" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RemoveIPC = true; + ProtectHome = true; + ProtectHostname = true; + PrivateMounts = true; + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = false; # kernel_route(ADD): Operation not permitted + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" ]; + UMask = "0177"; + RuntimeDirectory = "babeld"; + StateDirectory = "babeld"; + }; }; - }; - } diff --git a/nixos/modules/services/networking/blockbook-frontend.nix b/nixos/modules/services/networking/blockbook-frontend.nix index dde24522756af..ca323e495ec1d 100644 --- a/nixos/modules/services/networking/blockbook-frontend.nix +++ b/nixos/modules/services/networking/blockbook-frontend.nix @@ -158,15 +158,21 @@ let type = types.attrs; default = {}; example = literalExample '' { - alternative_estimate_fee = "whatthefee-disabled"; - alternative_estimate_fee_params = "{\"url\": \"https://whatthefee.io/data.json\", \"periodSeconds\": 60}"; - fiat_rates = "coingecko"; - fiat_rates_params = "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"bitcoin\", \"periodSeconds\": 60}"; - coin_shortcut = "BTC"; - coin_label = "Bitcoin"; - xpub_magic = 76067358; - xpub_magic_segwit_p2sh = 77429938; - xpub_magic_segwit_native = 78792518; + "alternative_estimate_fee" = "whatthefee-disabled"; + "alternative_estimate_fee_params" = "{\"url\": \"https://whatthefee.io/data.json\", \"periodSeconds\": 60}"; + "fiat_rates" = "coingecko"; + "fiat_rates_params" = "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"bitcoin\", \"periodSeconds\": 60}"; + "coin_shortcut" = "BTC"; + "coin_label" = "Bitcoin"; + "parse" = true; + "subversion" = ""; + "address_format" = ""; + "xpub_magic" = 76067358; + "xpub_magic_segwit_p2sh" = 77429938; + "xpub_magic_segwit_native" = 78792518; + "mempool_workers" = 8; + "mempool_sub_workers" = 2; + "block_addresses_to_keep" = 300; }''; description = '' Additional configurations to be appended to <filename>coin.conf</filename>. diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix index 5f8ac96b2292c..f116d6392ea7d 100644 --- a/nixos/modules/services/networking/cjdns.nix +++ b/nixos/modules/services/networking/cjdns.nix @@ -264,10 +264,10 @@ in '' ); + startLimitIntervalSec = 0; serviceConfig = { Type = "forking"; Restart = "always"; - StartLimitInterval = 0; RestartSec = 1; CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW CAP_SETUID"; ProtectSystem = true; diff --git a/nixos/modules/services/networking/dnsdist.nix b/nixos/modules/services/networking/dnsdist.nix index c48835e73612b..05c2bdef83e70 100644 --- a/nixos/modules/services/networking/dnsdist.nix +++ b/nixos/modules/services/networking/dnsdist.nix @@ -41,6 +41,7 @@ in { systemd.services.dnsdist = { wantedBy = [ "multi-user.target" ]; + startLimitIntervalSec = 0; serviceConfig = { DynamicUser = true; diff --git a/nixos/modules/services/networking/mullvad-vpn.nix b/nixos/modules/services/networking/mullvad-vpn.nix index cc98414257ca7..d9e6e57c92cc6 100644 --- a/nixos/modules/services/networking/mullvad-vpn.nix +++ b/nixos/modules/services/networking/mullvad-vpn.nix @@ -29,9 +29,9 @@ with lib; # Needed for ping "/run/wrappers" ]; + startLimitBurst = 5; + startLimitIntervalSec = 20; serviceConfig = { - StartLimitBurst = 5; - StartLimitIntervalSec = 20; ExecStart = "${pkgs.mullvad-vpn}/bin/mullvad-daemon -v --disable-stdout-timestamps"; Restart = "always"; RestartSec = 1; diff --git a/nixos/modules/services/networking/murmur.nix b/nixos/modules/services/networking/murmur.nix index b384f436861db..c6e5649ec4798 100644 --- a/nixos/modules/services/networking/murmur.nix +++ b/nixos/modules/services/networking/murmur.nix @@ -278,6 +278,10 @@ in home = "/var/lib/murmur"; createHome = true; uid = config.ids.uids.murmur; + group = "murmur"; + }; + users.groups.murmur = { + gid = config.ids.gids.murmur; }; systemd.services.murmur = { @@ -300,6 +304,7 @@ in RuntimeDirectory = "murmur"; RuntimeDirectoryMode = "0700"; User = "murmur"; + Group = "murmur"; }; }; }; diff --git a/nixos/modules/services/networking/namecoind.nix b/nixos/modules/services/networking/namecoind.nix index 16f85df2e77c8..4966ed2cac8dc 100644 --- a/nixos/modules/services/networking/namecoind.nix +++ b/nixos/modules/services/networking/namecoind.nix @@ -165,6 +165,8 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; + startLimitIntervalSec = 120; + startLimitBurst = 5; serviceConfig = { User = "namecoin"; Group = "namecoin"; @@ -176,8 +178,6 @@ in TimeoutStopSec = "60s"; TimeoutStartSec = "2s"; Restart = "always"; - StartLimitInterval = "120s"; - StartLimitBurst = "5"; }; preStart = optionalString (cfg.wallet != "${dataDir}/wallet.dat") '' diff --git a/nixos/modules/services/networking/nextdns.nix b/nixos/modules/services/networking/nextdns.nix index a633bff62ec7e..b070eeec894fe 100644 --- a/nixos/modules/services/networking/nextdns.nix +++ b/nixos/modules/services/networking/nextdns.nix @@ -28,9 +28,9 @@ in { environment = { SERVICE_RUN_MODE = "1"; }; + startLimitIntervalSec = 5; + startLimitBurst = 10; serviceConfig = { - StartLimitInterval = 5; - StartLimitBurst = 10; ExecStart = "${pkgs.nextdns}/bin/nextdns run ${escapeShellArgs config.services.nextdns.arguments}"; RestartSec = 120; LimitMEMLOCK = "infinity"; diff --git a/nixos/modules/services/networking/nix-store-gcs-proxy.nix b/nixos/modules/services/networking/nix-store-gcs-proxy.nix index 3f2ce5bca4da4..0012302db2e3c 100644 --- a/nixos/modules/services/networking/nix-store-gcs-proxy.nix +++ b/nixos/modules/services/networking/nix-store-gcs-proxy.nix @@ -42,9 +42,9 @@ in description = "A HTTP nix store that proxies requests to Google Storage"; wantedBy = ["multi-user.target"]; + startLimitIntervalSec = 10; serviceConfig = { RestartSec = 5; - StartLimitInterval = 10; ExecStart = '' ${pkgs.nix-store-gcs-proxy}/bin/nix-store-gcs-proxy \ --bucket-name ${cfg.bucketName} \ diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix index 3ecbd06ee416b..f33c350a257a9 100644 --- a/nixos/modules/services/networking/nsd.nix +++ b/nixos/modules/services/networking/nsd.nix @@ -916,14 +916,14 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; + startLimitBurst = 4; + startLimitIntervalSec = 5 * 60; # 5 mins serviceConfig = { ExecStart = "${nsdPkg}/sbin/nsd -d -c ${nsdEnv}/nsd.conf"; StandardError = "null"; PIDFile = pidFile; Restart = "always"; RestartSec = "4s"; - StartLimitBurst = 4; - StartLimitInterval = "5min"; }; preStart = '' diff --git a/nixos/modules/services/networking/supybot.nix b/nixos/modules/services/networking/supybot.nix index dc9fb31ffd0bf..7a62e04ec7c4b 100644 --- a/nixos/modules/services/networking/supybot.nix +++ b/nixos/modules/services/networking/supybot.nix @@ -103,6 +103,8 @@ in rm -f '${cfg.stateDir}/supybot.cfg.bak' ''; + startLimitIntervalSec = 5 * 60; # 5 min + startLimitBurst = 1; serviceConfig = { ExecStart = "${pyEnv}/bin/supybot ${cfg.stateDir}/supybot.cfg"; PIDFile = "/run/supybot.pid"; @@ -110,8 +112,6 @@ in Group = "supybot"; UMask = "0007"; Restart = "on-abort"; - StartLimitInterval = "5m"; - StartLimitBurst = "1"; NoNewPrivileges = true; PrivateDevices = true; diff --git a/nixos/modules/services/networking/tailscale.nix b/nixos/modules/services/networking/tailscale.nix index 4d6aeb75ebd15..4419c8a0602f8 100644 --- a/nixos/modules/services/networking/tailscale.nix +++ b/nixos/modules/services/networking/tailscale.nix @@ -17,6 +17,7 @@ in { }; config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.tailscale ]; # for the CLI systemd.services.tailscale = { description = "Tailscale client daemon"; @@ -24,10 +25,7 @@ in { wants = [ "network-pre.target" ]; wantedBy = [ "multi-user.target" ]; - unitConfig = { - StartLimitIntervalSec = 0; - StartLimitBurst = 0; - }; + startLimitIntervalSec = 0; serviceConfig = { ExecStart = diff --git a/nixos/modules/services/security/vault.nix b/nixos/modules/services/security/vault.nix index 6a8a3a93327eb..64622454b9dee 100644 --- a/nixos/modules/services/security/vault.nix +++ b/nixos/modules/services/security/vault.nix @@ -131,6 +131,8 @@ in restartIfChanged = false; # do not restart on "nixos-rebuild switch". It would seal the storage and disrupt the clients. + startLimitIntervalSec = 60; + startLimitBurst = 3; serviceConfig = { User = "vault"; Group = "vault"; @@ -145,8 +147,6 @@ in KillSignal = "SIGINT"; TimeoutStopSec = "30s"; Restart = "on-failure"; - StartLimitInterval = "60s"; - StartLimitBurst = 3; }; unitConfig.RequiresMountsFor = optional (cfg.storagePath != null) cfg.storagePath; diff --git a/nixos/modules/services/web-apps/moinmoin.nix b/nixos/modules/services/web-apps/moinmoin.nix index dc7abce2a5cb5..3a876f75f4a48 100644 --- a/nixos/modules/services/web-apps/moinmoin.nix +++ b/nixos/modules/services/web-apps/moinmoin.nix @@ -224,6 +224,8 @@ in chmod -R u+w ${dataDir}/${wikiIdent}/underlay ''; + startLimitIntervalSec = 30; + serviceConfig = { User = user; Group = group; @@ -237,7 +239,6 @@ in Restart = "on-failure"; RestartSec = "2s"; - StartLimitIntervalSec = "30s"; StateDirectory = "moin/${wikiIdent}"; StateDirectoryMode = "0750"; diff --git a/nixos/modules/services/web-apps/shiori.nix b/nixos/modules/services/web-apps/shiori.nix index 1817a2039352d..9083ddfa2206b 100644 --- a/nixos/modules/services/web-apps/shiori.nix +++ b/nixos/modules/services/web-apps/shiori.nix @@ -37,11 +37,60 @@ in { description = "Shiori simple bookmarks manager"; wantedBy = [ "multi-user.target" ]; + environment.SHIORI_DIR = "/var/lib/shiori"; + serviceConfig = { ExecStart = "${package}/bin/shiori serve --address '${address}' --port '${toString port}'"; + DynamicUser = true; - Environment = "SHIORI_DIR=/var/lib/shiori"; StateDirectory = "shiori"; + # As the RootDirectory + RuntimeDirectory = "shiori"; + + # Security options + + BindReadOnlyPaths = [ + "/nix/store" + + # For SSL certificates, and the resolv.conf + "/etc" + ]; + + CapabilityBoundingSet = ""; + + DeviceAllow = ""; + + LockPersonality = true; + + MemoryDenyWriteExecute = true; + + PrivateDevices = true; + PrivateUsers = true; + + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + + RestrictNamespaces = true; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + RestrictRealtime = true; + RestrictSUIDSGID = true; + + RootDirectory = "/run/shiori"; + + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = [ + "@system-service" + + "~@chown" "~@cpu-emulation" "~@debug" "~@ipc" "~@keyring" "~@memlock" + "~@module" "~@obsolete" "~@privileged" "~@process" "~@raw-io" + "~@resources" "~@setuid" + ]; }; }; }; diff --git a/nixos/modules/services/web-servers/caddy.nix b/nixos/modules/services/web-servers/caddy.nix index 72bf9a9a1f448..297b732733927 100644 --- a/nixos/modules/services/web-servers/caddy.nix +++ b/nixos/modules/services/web-servers/caddy.nix @@ -24,6 +24,10 @@ let ${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${adaptedConfig} ${tlsJSON} > $out ''; in { + imports = [ + (mkRemovedOptionModule [ "services" "caddy" "agree" ] "this option is no longer necessary for Caddy 2") + ]; + options.services.caddy = { enable = mkEnableOption "Caddy web server"; @@ -66,12 +70,6 @@ in { description = "Email address (for Let's Encrypt certificate)"; }; - agree = mkOption { - default = false; - type = types.bool; - description = "Agree to Let's Encrypt Subscriber Agreement"; - }; - dataDir = mkOption { default = "/var/lib/caddy"; type = types.path; @@ -103,6 +101,8 @@ in { after = [ "network-online.target" ]; wants = [ "network-online.target" ]; # systemd-networkd-wait-online.service wantedBy = [ "multi-user.target" ]; + startLimitIntervalSec = 14400; + startLimitBurst = 10; serviceConfig = { ExecStart = "${cfg.package}/bin/caddy run --config ${configJSON}"; ExecReload = "${cfg.package}/bin/caddy reload --config ${configJSON}"; @@ -110,8 +110,6 @@ in { User = "caddy"; Group = "caddy"; Restart = "on-abnormal"; - StartLimitIntervalSec = 14400; - StartLimitBurst = 10; AmbientCapabilities = "cap_net_bind_service"; CapabilityBoundingSet = "cap_net_bind_service"; NoNewPrivileges = true; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 631e92fd6e955..c0c2f27a00ef9 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -693,6 +693,8 @@ in ${cfg.preStart} ${execCommand} -t ''; + + startLimitIntervalSec = 60; serviceConfig = { ExecStart = execCommand; ExecReload = [ @@ -701,7 +703,6 @@ in ]; Restart = "always"; RestartSec = "10s"; - StartLimitInterval = "1min"; # User and group User = cfg.user; Group = cfg.group; diff --git a/nixos/modules/services/web-servers/traefik.nix b/nixos/modules/services/web-servers/traefik.nix index 4ab7307c3b671..3d29199dd4549 100644 --- a/nixos/modules/services/web-servers/traefik.nix +++ b/nixos/modules/services/web-servers/traefik.nix @@ -136,6 +136,8 @@ in { description = "Traefik web server"; after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; + startLimitIntervalSec = 86400; + startLimitBurst = 5; serviceConfig = { ExecStart = "${cfg.package}/bin/traefik --configfile=${staticConfigFile}"; @@ -143,8 +145,6 @@ in { User = "traefik"; Group = cfg.group; Restart = "on-failure"; - StartLimitInterval = 86400; - StartLimitBurst = 5; AmbientCapabilities = "cap_net_bind_service"; CapabilityBoundingSet = "cap_net_bind_service"; NoNewPrivileges = true; diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 55d3e742ef7cd..9e971671c474e 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -678,14 +678,14 @@ in script = "${cfg.displayManager.job.execCmd}"; + # Stop restarting if the display manager stops (crashes) 2 times + # in one minute. Starting X typically takes 3-4s. + startLimitIntervalSec = 30; + startLimitBurst = 3; serviceConfig = { Restart = "always"; RestartSec = "200ms"; SyslogIdentifier = "display-manager"; - # Stop restarting if the display manager stops (crashes) 2 times - # in one minute. Starting X typically takes 3-4s. - StartLimitInterval = "30s"; - StartLimitBurst = "3"; }; }; diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index 47689b2a4700a..3b01bc00bafa2 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -648,11 +648,13 @@ let "RapidCommit" "ForceDHCPv6PDOtherInformation" "PrefixDelegationHint" + "RouteMetric" ]) (assertValueOneOf "UseDNS" boolValues) (assertValueOneOf "UseNTP" boolValues) (assertValueOneOf "RapidCommit" boolValues) (assertValueOneOf "ForceDHCPv6PDOtherInformation" boolValues) + (assertInt "RouteMetric") ]; sectionDHCPServer = checkUnitConfig "DHCPServer" [ diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index f7c2940049e56..e5cafe237cd53 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -120,7 +120,7 @@ eval "exec $logOutFd>&1 $logErrFd>&2" if test -w /dev/kmsg; then tee -i < /tmp/stage-1-init.log.fifo /proc/self/fd/"$logOutFd" | while read -r line; do if test -n "$line"; then - echo "<7>stage-1-init: $line" > /dev/kmsg + echo "<7>stage-1-init: [$(date)] $line" > /dev/kmsg fi done & else @@ -356,6 +356,7 @@ mountFS() { case $options in *x-nixos.autoresize*) if [ "$fsType" = ext2 -o "$fsType" = ext3 -o "$fsType" = ext4 ]; then + modprobe "$fsType" echo "resizing $device..." e2fsck -fp "$device" resize2fs "$device" diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix index 5addc6f9ca44d..4154389b2ce5f 100644 --- a/nixos/modules/system/boot/systemd-unit-options.nix +++ b/nixos/modules/system/boot/systemd-unit-options.nix @@ -210,12 +210,21 @@ in rec { ''; }; + startLimitBurst = mkOption { + type = types.int; + description = '' + Configure unit start rate limiting. Units which are started + more than startLimitBurst times within an interval time + interval are not permitted to start any more. + ''; + }; + startLimitIntervalSec = mkOption { type = types.int; description = '' Configure unit start rate limiting. Units which are started - more than burst times within an interval time interval are - not permitted to start any more. + more than startLimitBurst times within an interval time + interval are not permitted to start any more. ''; }; @@ -245,8 +254,7 @@ in rec { serviceConfig = mkOption { default = {}; example = - { StartLimitInterval = 10; - RestartSec = 5; + { RestartSec = 5; }; type = types.addCheck (types.attrsOf unitOption) checkService; description = '' diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 74d6957678f56..c22264b3e92dd 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -243,6 +243,8 @@ let OnFailure = toString config.onFailure; } // optionalAttrs (options.startLimitIntervalSec.isDefined) { StartLimitIntervalSec = toString config.startLimitIntervalSec; + } // optionalAttrs (options.startLimitBurst.isDefined) { + StartLimitBurst = toString config.startLimitBurst; }; }; }; @@ -884,14 +886,25 @@ in config = { - warnings = concatLists (mapAttrsToList (name: service: - let - type = service.serviceConfig.Type or ""; - restart = service.serviceConfig.Restart or "no"; - in optional - (type == "oneshot" && (restart == "always" || restart == "on-success")) - "Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'") - cfg.services); + warnings = concatLists ( + mapAttrsToList + (name: service: + let + type = service.serviceConfig.Type or ""; + restart = service.serviceConfig.Restart or "no"; + hasDeprecated = builtins.hasAttr "StartLimitInterval" service.serviceConfig; + in + concatLists [ + (optional (type == "oneshot" && (restart == "always" || restart == "on-success")) + "Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'" + ) + (optional hasDeprecated + "Service '${name}.service' uses the attribute 'StartLimitInterval' in the Service section, which is deprecated. See https://github.com/NixOS/nixpkgs/issues/45786." + ) + ] + ) + cfg.services + ); system.build.units = cfg.units; diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 20d48add71293..44cb60809452c 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -48,7 +48,7 @@ in ]; boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" ]; boot.initrd.availableKernelModules = [ "ixgbevf" "ena" "nvme" ]; - boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" ]; + boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" "random.trust_cpu=on" ]; # Prevent the nouveau kernel module from being loaded, as it # interferes with the nvidia/nvidia-uvm modules needed for CUDA. diff --git a/nixos/tests/firefox.nix b/nixos/tests/firefox.nix index 7071baceba739..07e25bd4ca72d 100644 --- a/nixos/tests/firefox.nix +++ b/nixos/tests/firefox.nix @@ -11,26 +11,105 @@ import ./make-test-python.nix ({ pkgs, esr ? false, ... }: { environment.systemPackages = (if esr then [ pkgs.firefox-esr ] else [ pkgs.firefox ]) ++ [ pkgs.xdotool ]; + + # Need some more memory to record audio. + virtualisation.memorySize = "500"; + + # Create a virtual sound device, with mixing + # and all, for recording audio. + boot.kernelModules = [ "snd-aloop" ]; + sound.enable = true; + sound.extraConfig = '' + pcm.!default { + type plug + slave.pcm pcm.dmixer + } + pcm.dmixer { + type dmix + ipc_key 1 + slave { + pcm "hw:Loopback,0,0" + rate 48000 + periods 128 + period_time 0 + period_size 1024 + buffer_size 8192 + } + } + pcm.recorder { + type hw + card "Loopback" + device 1 + subdevice 0 + } + ''; + + systemd.services.audio-recorder = { + description = "Record NixOS test audio to /tmp/record.wav"; + script = "${pkgs.alsaUtils}/bin/arecord -D recorder -f S16_LE -r48000 /tmp/record.wav"; + }; + }; testScript = '' + from contextlib import contextmanager + + + @contextmanager + def audio_recording(machine: Machine) -> None: + """ + Perform actions while recording the + machine audio output. + """ + machine.systemctl("start audio-recorder") + yield + machine.systemctl("stop audio-recorder") + + + def wait_for_sound(machine: Machine) -> None: + """ + Wait until any sound has been emitted. + """ + machine.wait_for_file("/tmp/record.wav") + while True: + # Get at most 2M of the recording + machine.execute("tail -c 2M /tmp/record.wav > /tmp/last") + # Get the exact size + size = int(machine.succeed("stat -c '%s' /tmp/last").strip()) + # Compare it against /dev/zero using `cmp` (skipping 50B of WAVE header). + # If some non-NULL bytes are found it returns 1. + status, output = machine.execute( + f"cmp -i 50 -n {size - 50} /tmp/last /dev/zero 2>&1" + ) + if status == 1: + break + machine.sleep(2) + + machine.wait_for_x() - with subtest("wait until Firefox has finished loading the Valgrind docs page"): + with subtest("Wait until Firefox has finished loading the Valgrind docs page"): machine.execute( "xterm -e 'firefox file://${pkgs.valgrind.doc}/share/doc/valgrind/html/index.html' &" ) machine.wait_for_window("Valgrind") machine.sleep(40) + with subtest("Check whether Firefox can play sound"): + with audio_recording(machine): + machine.succeed( + "firefox file://${pkgs.sound-theme-freedesktop}/share/sounds/freedesktop/stereo/phone-incoming-call.oga &" + ) + wait_for_sound(machine) + machine.copy_from_vm("/tmp/record.wav") + + with subtest("Close sound test tab"): + machine.execute("xdotool key ctrl+w") + with subtest("Close default browser prompt"): machine.execute("xdotool key space") - with subtest("Hide default browser window"): - machine.sleep(2) - machine.execute("xdotool key F12") - - with subtest("wait until Firefox draws the developer tool panel"): + with subtest("Wait until Firefox draws the developer tool panel"): machine.sleep(10) machine.succeed("xwininfo -root -tree | grep Valgrind") machine.screenshot("screen") |