The bcachefs-wait-devices@.service unit can be added as a Wants
dependency to a .mount units to wait until every device in the
filesystem is initialized before doing the mount.
A later commit will add the bcachefs-wait-devices@.service unit to
the initrd. Since it references sbin/bcachefs, so we need to add it
to the initrd. Note that sbin/bcachefs is just a symlink to the actual
executable in bin so nothing is duplicated.
When systemd is used in stage 1 (boot.initrd.systemd.enable), the device
units are activated before the stage 2 units are loaded, so the
network-addresses-*.service are never started.
To avoid this, in addition to the wantedBy dependency, we use udev rules
with SYSTEMD_WANTS to trigger the services directly.
This key is an alias for net.ipv4.ip_forward. The kernel default is
already 0, so emitting `=0` from sysctl.d is at best a no-op.
It is actively harmful when systemd-networkd manages forwarding via
`networkd.conf [Network] IPv4Forwarding=yes`: on a cold boot
systemd-sysctl runs before networkd and networkd's write wins, but on
a `nixos-rebuild switch` that restarts both services (any systemd
package change does, since kernel.poweroff_cmd in 60-nixos.conf
follows the systemd store path) the ordering is undefined and sysctl
can run last, silently flipping a router back to ip_forward=0.
Only emit the sysctl when at least one interface has proxyARP=true,
matching every other in-tree setter of this key (nat, docker,
tailscale, netbird, ...) which only ever write `true`. The previous
value was already mkDefault, so nothing could have been relying on it
to force forwarding off anyway.
Reverts #481473, fixes#509254
Turns out this breaks scripted networking with systemd stage 1. Even
if we assumed that systemd stage 1 wasn't now the default, I still
think that makes this worthy of a revert, in the absence of a fix. But
now that systemd stage 1 is the default, this is also a channel
blocker.
The problem is that wantedBy = [ "foo.device" ]; doesn't work as
hoped. If the device appears in stage 1, then the systemd device unit
becomes active in stage 1 without pulling in any dependency for
configuring it (because that only exists in stage 2). When we
transition to stage 2, systemd maintains its information about unit
state between stages and remembers that the device units were already
active. They do not become reactivated, and consequently their new
stage 2 dependencies do not get pulled in.
The fix is probably to do this with SYSTEMD_WANTS= in udev rules,
rather than with wantedBy. The udev rules will re-fire during stage 2,
though I'm not 100% clear on exactly which events that includes
(e.g. if we'll get new add events or if we need to look for a
different ACTION or anything like that). This is going to require some
experimentation and testing that I don't have time for today.
Given that this is addressing a channel blocker, I think this revert
should be merged if a fix can't be merged instead before the next
unstable-small eval. In either case, staging-nixos should be merged to
master right after.
This service is essentially a random sleep() call that old software that
is unable to properly handle modern hardware initialisation being
asynchronous can use to *mostly* get by.
Over the years is has caused so many issues in NixOS, like introducing
long delays in the boot process[1], complete deadlocks[2] and even failures
when reloading services or activating a new configuration[3].
systemd has been discouraging its use since 2011 (15 years ago!), then
it officially deprecated it in 2018 and since 2020 it started to show on
every boot a huge wall of text calling out all the offending services
that still use it.
Around 2021 we managed to fix around 15 NixOS modules[4] that were
relying on systemd-udev-settle and practically ZFS[5] was the only
remaining one. However, since then, people have actually started to
bring it back with new services[6][7][8]. This is not acceptable.
So, to prevent any more (lazy) uses of systemd-udev-settle, we stop
providing the systemd-udev-settle.service unit entirely. For existing
modules that unfortunately still need it, we replace it with the command
`udevadm settle --timeout=180`, which is all that the service does.
Hopefully this will also increase the awareness that it's bad and
something to be fixed.
Note: I tested this change using
- `nixosTests.zfs`,
- `nixosTests.ifstate`,
- `nixosTests.misc`,
- `nixosTests.openvswitch`,
- `nixosTests.predictable-interface-names`
- `nixosTests.nvidia-container-toolkit`
and making sure that none of the 165 packages that provide upstream
units (via the `systemd.packages` option) had a dependency on
systemd-udev-settle.service.
[1]: https://github.com/NixOS/nixpkgs/pull/25311
[2]: https://github.com/NixOS/nixpkgs/issues/107341
[3]: https://github.com/NixOS/nixpkgs/pull/113804
[4]: https://github.com/NixOS/nixpkgs/issues/73095
[5]: https://github.com/openzfs/zfs/issues/10891
[6]: https://github.com/NixOS/nixpkgs/pull/257525#discussion_r1442702970
[7]: https://github.com/NixOS/nixpkgs/pull/460075
[8]: https://github.com/NixOS/nixpkgs/pull/284507
stage-1.nix had mkRenamedOptionModule from boot.initrd.mdadmConf to
boot.swraid.mdadmConf. Move it to tasks/swraid.nix where the target
option is defined.
NixOS has traditionally enabled the `ext` family of file systems by
default. Originally, when switching to systemd initrd, we wanted to
transition to making this explicit so that initrds could be made
without `ext`. The problem is that anyone with `fsType = "auto";` for
an `ext` file system in initrd will fail to boot, which is not really
an acceptable regression as we switch to systemd initrd by default.
By removing `default = "auto"` from `fsType`, we rule out the vast
majority of these regressions as eval errors, since most users of
`fsType = "auto"` for ext file systems are using it because of the
default value.
In hindsight, this is probably what #225352 was really about.
This adds a target that groups together all the services of the
scripted backend. It has no role during the boot, but provides
a quick way to reset the network configuration.
For example, if addresses/routes are added/removed or an interface has
been stopped manually, running
systemctl restart networking-scripted.target
will undo all the changes.
This change solves some big design flaws in the scripted networking
backend.
1. When the module was reworked in 072c1dcc4a to use the new systemd
targets, network-setup.service was used to:
a. order the services and link network.target to the boot sequence
b. perform some perform final network configuration, specifically
setting the default gateways and nameservers (/etc/resolv.conf).
Later (ec00b4bb11) however, network-setup.service was made
optional: if resolvconf is not used and a default gateway is not set,
the service is not be defined (because it would result in an empty
script). Doing so, however, has the unintended effect of unlinking
network.target from multi-uset.target, meaning no network
configuration at all is performed.
Note: this can be easily seen by adding `networking.resolvconf.enable
= false` to the nixosTests.networking.scripted.static test.
2. The network-addresses-*.service are linked to network.target, which,
in turn, is linked to multi-uset.target. This means that if a
hardware interface is not found, the boot will hang until this
service times out (issue #154737).
To solve issue 1. this change removes network-target entirely while
- moving the default gateway setup into the relative
network-addresses-*.service unit;
- moving the nameservers setup into networking.localCommands;
(incidentally, this also fixes issue #445496)
- directly linking network.target to multi-user.target.
To solve issue 2. this removes the Wants=network.target dependency of
network-addresses-*.service and solely relies on the underlying
interface unit (*-netdev.service for virtual, *.device for physical) to
start the service.
Note: for NixOS containers, the dependency is kept, because the .device
unit are not available in this case.
Finally, if an interface is the default gateway, network-online.target
is added as an extra dependency, so the target is not reached until the
interface has been plugged in and configured.
This module disables the activation scripts that would normally create
`/usr/bin/env` and `/bin/sh` (and their parent directories). When
systemd is used in the initrd, the absence of these directories causes
2 problems:
- During switch-root, base_filesystem_create_fd() creates an empty /usr
directory. Later at stage2, systemd's initialize_runtime() aborts
booting with "Refusing to run in unsupported environment where /usr/
is not populated."
- Once /usr/bin is restored (by the fix above), base_filesystem_create_fd()
creates a symlink /bin -> /usr/bin. systemd-fstab-generator then
canonicalizes the /bin fstab entry through this symlink, producing a
duplicate usr-bin.mount.
We create both /sysroot/usr/bin and /sysroot/bin via initrd tmpfiles
to prevent both issues.
Resolves NixOS#462556
Co-authored-by: Lin Yinfeng <lin.yinfeng@outlook.com>
Otherwise we crash like:
… while selecting an attribute
at /nix/store/0b202s06rfm1vlyai37gd0zmzxg59qj0-source/nixos/modules/tasks/filesystems/zfs.nix:827:48:
826| lib.mkDefault (
827| config.security.wrapperDir + "/" + config.services.mail.sendmailSetuidWrapper.program
| ^
828| )
error: expected a set but found null: null
Update the name and documentation to make it clear it's a matter of
"when" not "if".
This change was recommended in 2023 but noone followed up:
https://github.com/NixOS/nixpkgs/pull/208037#issuecomment-1688855654
(I never used this and have suffered no dataloss, but might as well make
this small improvement while I notice the currently dire situation.)
As per 12e77fdc3f that set it to true:
> This may currently be necessary, especially if your pools have not
> been correctly imported with a proper host id configuration (which
> is probably true for 99% of current NixOS ZFS users). Once host id
> configuration becomes mandatory when using ZFS in NixOS and we are
> sure that most users have updated their configurations and rebooted
> at least once, we should disable force-import by default. Probably,
> this shouldn't be done before the next stable release.
A couple stable releases have come and gone since 2014!
Let's remove this armed and aimed footgun.
Ideally, the module does not set a non-LTS kernel by default, which we
have been able to do since 6.18 was labeled LTS. This should have been
done before 6.19 became `latest` to avoid having people upgraded to
6.19 and then downgraded to 6.18, but we just missed that. Shouldn't
be a problem if we rectify it quickly.