In some cases like we've noticed in https://github.com/NixOS/nixpkgs/issues/76169,
having duplicate packages in systemd.packages like
```
systemd.packages = [ gnome-shell gnome-shell gnome-session ];
```
breaks.
Here we use an associative array to ensure no
duplicate paths when we symlink all the units listed
in systemd.packages.
This fixes the dhcpcd issue in https://github.com/NixOS/nixpkgs/issues/76969,
which was exposed by https://github.com/NixOS/nixpkgs/pull/75031
introducing changes in the module ordering and therefore option ordering
too.
The dhcpcd issue would also be fixable by explicitly putting
dhcpcd's paths before others, however it makes more sense for systemd's
default paths to be after all others by default, since they should only
be a fallback, which is how binary finding will work if they come after.
When using a modified systemd-package (e.g. to test a patch), it's
recommended to use the `systemd.package`-option to avoid rebuilding all packages
that somehow depend on systemd.
With this change, the modified package is also used by `systemd-nspawn@`
units.
A centralized list for these renames is not good because:
- It breaks disabledModules for modules that have a rename defined
- Adding/removing renames for a module means having to find them in the
central file
- Merge conflicts due to multiple people editing the central file
The options at `systemd.network` (`links`, `netdevs` and `networks`) are
directly mapped to the three different unit types of `systemd-networkd(8)`.
However there's also the option `systemd.network.units` which is
basically used as a container for generated unit-configs that are linked
to `/etc/systemd/networkd`[1].
This should not be exposed to the user as it's unclear whether or not it
should be used directly which can be pretty confusing which is why I decided to
declare this option as internal (including all sub-options as `internal`
doesn't seem to be propagated to submodules).
[1] 9db75ed88f/nixos/modules/system/boot/networkd.nix (L933-L937)
Previously, socket units wouldn't be restarted if they were
changed. To restart the socket, the service the socket is attached
to needs to be stopped first before the socket can be restarted.
This adds an `extraConfig` option to timesyncd for setting additional
options in `/etc/systemd/timesyncd.conf`.
This is similar to things like `services.journald.extraConfig` and
`services.logind.extraConfig`.
This has been there since v209 [1]
```
The interface name to use. This option has lower precedence than NamePolicy=, so for this setting to take effect, NamePolicy= must either be unset, empty, disabled, or all policies configured there must fail. Also see the example below with "Name=dmz0".
Note that specifying a name that the kernel might use for another interface (for example "eth0") is dangerous because the name assignment done by udev will race with the assignment done by the kernel, and only one interface may use the name. Depending on the order of operations, either udev or the kernel will win, making the naming unpredictable. It is best to use some different prefix, for example "internal0"/"external0" or "lan0"/"lan1"/"lan3".
```
[1] 43b3a5ef61
Adding `systemd-importd` to the build, so that `machinectl`s `import-.*`
may actually do anything. Currently they fail with
```
Failed to transfer image: The name org.freedesktop.import1 was not provided by any .service files
```
as `systemd-importd` is not built. Also registers the regarding dbus
api and service in the systemd module.
Both options were introduced in systemd v243[1]. Those options can be
used to ensure that LinkLocalAddressing is only configured for a given
interface if DHCPv4 fails. To quote `systemd.network(5)`:
```
If "fallback" or "ipv4-fallback" is specified, then an IPv4
link-local address is configured only when DHCPv4 fails. If "fallback", an IPv6 link-local
address is always configured, and if "ipv4-fallback", the address is not configured. Note
that, the fallback mechanism works only when DHCPv4 client is enabled, that is, it requires
"DHCP=yes" or "DHCP=ipv4".
```
[1] 8bc17bb3f7
GDM now specifies ordering between `plymouth-quit` and `display-manager`:
9be5321097
This causes an ordering cycle between GDM and plymouth-quit which can result in
systemd breaking GDM:
```
plymouth-quit.service: Job display-manager.service/start deleted to break
ordering cycle starting with plymouth-quit.service/start
```
Not sure how often this triggers, as I've run my system with plymouth and
9be5321097 without any issues. But I did catch a VM doing this.
NOTE: I also tried to remove the ordering in GDM to see if plymouth managed to
live longer, but it didn't seem to help. So I opted to stick as close to
upstream (upstream GDM specifies ordering, but plymouth does not).
Images generated with nixos-install will be supported by machinectl
problem is that systemd-nspawn's private usersns feature clashes
with DynamicUser and RuntimeDirectory features, which causes NixOS
images to not boot. There is an upstream issue for this
https://github.com/systemd/systemd/issues/13622
In #68792 it was discovered that /dev/fuse doesn't have
wordl-read-writeable permissions anymore. The cause of this is that the
tmpfiles examples in systemd were reorganized and split into more files.
We thus lost some of the configuration we were depending on.
In this commit some of the new tmpfiles configuration that are
applicable to us are added which also makes wtmp/lastlog in the pam
module not necessary anymore.
Rationale for the new tmpfile configs:
- `journal-nowcow.conf`: Contains chattr +C for journald logs which
makes sense on copy-on-write filesystems like Btrfs. Other filesystems
shouldn't do anything funny when that flag is set.
- `static-nodes-permissions.conf`: Contains some permission overrides
for some device nodes like audio, loop, tun, fuse and kvm.
- `systemd-nspawn.conf`: Makes sure `/var/lib/machines` exists and old
snapshots are properly removed.
- `systemd-tmp.conf`: Removes systemd services related private tmp
folders and temporary coredump files.
- `var.conf`: Creates some useful directories in `/var` which we would
create anyway at some point. Also includes
`/var/log/{wtmp,btmp,lastlog}`.
Fixes#68792.
The new systemd in 19.09 gives an "Access Denied" error when doing
"systemctl daemon-reexec" on an 19.03 system. The fix is to use the
previous systemctl to signal the daemon to re-exec itself. This
ensures that users don't have to reboot when upgrading from NixOS
19.03 to 19.09.
Pretty useful for laptops. I use them with:
```
services.logind.lidSwitch = "suspend-then-hibernate";
environment.etc."systemd/sleep.conf".text = "HibernateDelaySec=8h";
```
boot.kernelPackages: check for conflicts
It's currently possible to set conflicting `boot.kernelPackages` several times.
Nixos now warns when this is the case instead of just picking one.
systemd provides two sysctl snippets, 50-coredump.conf and
50-default.conf.
These enable:
- Loose reverse path filtering
- Source route filtering
- `fq_codel` as a packet scheduler (this helps to fight bufferbloat)
This also configures the kernel to pass coredumps to `systemd-coredump`.
These sysctl snippets can be found in `/etc/sysctl.d/50-*.conf`,
and overridden via `boot.kernel.sysctl`
(which will place the parameters in `/etc/sysctl.d/60-nixos.conf`.
Let's start using these, like other distros already do for quite some
time, and remove those duplicate `boot.kernel.sysctl` options we
previously did set.
In the case of rp_filter (which systemd would set to 2 (loose)), make
our overrides to "1" more explicit.
Add support for custom device-tree files, and applying overlays to them.
This is useful for supporting non-discoverable hardware, such as sensors
attached to GPIO pins on a Raspberry Pi.
This adds handling for WASM binaries to binfmt’s emulatedSystems. To
enable, add this to your configuration:
boot.binfmt.emulatedSystems = [ "wasm32-wasi" ];
After rebuilding with nixos-rebuild switch, you can run wasm binaries
directly.
This is a refactor of how resolvconf is managed on NixOS. We split it
into a separate service which is enabled internally depending on whether
we want /etc/resolv.conf to be managed by it. Various services now take
advantage of those configuration options.
We also now use systemd instead of activation scripts to update
resolv.conf.
NetworkManager now uses the right option for rc-manager DNS
automatically, so the configuration option shouldn't be exposed.
This is needed for tcrypt and the benchmark subcommand. If enabled,
it is also used to unlock LUKS2 volumes and therefore the kernel modules
providing this feature need to be available in our initrd.
Fixes#42163. #54019.
Somewhen between systemd v239 and v242 upstream decided to no longer run
a few system services with `DyanmicUser=1` but failed to provide a
migration path for all the state those services left behind.
For the case of systemd-timesync the state has to be moved from
/var/lib/private/systemd/timesync to /var/lib/systemd/timesync if
/var/lib/systemd/timesync is currently a symlink.
We only do this if the stateVersion is still below 19.09 to avoid
starting to have an ever growing activation script for (then) ancient
systemd migrations that are no longer required.
See https://github.com/systemd/systemd/issues/12131 for details about
the missing migration path and related discussion.
This change was only a temporary workaround and isn't required anymore,
since /etc/systemd/system/system.slice should not be present on any
recent NixOS system (which makes this change a no-op).
This reverts commit 7098b0fcdf.
Currently if you want to properly chroot a systemd service, you could do
it using BindReadOnlyPaths=/nix/store or use a separate derivation which
gathers the runtime closure of the service you want to chroot. The
former is the easier method and there is also a method directly offered
by systemd, called ProtectSystem, which still leaves the whole store
accessible. The latter however is a bit more involved, because you need
to bind-mount each store path of the runtime closure of the service you
want to chroot.
This can be achieved using pkgs.closureInfo and a small derivation that
packs everything into a systemd unit, which later can be added to
systemd.packages.
However, this process is a bit tedious, so the changes here implement
this in a more generic way.
Now if you want to chroot a systemd service, all you need to do is:
{
systemd.services.myservice = {
description = "My Shiny Service";
wantedBy = [ "multi-user.target" ];
confinement.enable = true;
serviceConfig.ExecStart = "${pkgs.myservice}/bin/myservice";
};
}
If more than the dependencies for the ExecStart* and ExecStop* (which
btw. also includes script and {pre,post}Start) need to be in the chroot,
it can be specified using the confinement.packages option. By default
(which uses the full-apivfs confinement mode), a user namespace is set
up as well and /proc, /sys and /dev are mounted appropriately.
In addition - and by default - a /bin/sh executable is provided, which
is useful for most programs that use the system() C library call to
execute commands via shell.
Unfortunately, there are a few limitations at the moment. The first
being that DynamicUser doesn't work in conjunction with tmpfs, because
systemd seems to ignore the TemporaryFileSystem option if DynamicUser is
enabled. I started implementing a workaround to do this, but I decided
to not include it as part of this pull request, because it needs a lot
more testing to ensure it's consistent with the behaviour without
DynamicUser.
The second limitation/issue is that RootDirectoryStartOnly doesn't work
right now, because it only affects the RootDirectory option and doesn't
include/exclude the individual bind mounts or the tmpfs.
A quirk we do have right now is that systemd tries to create a /usr
directory within the chroot, which subsequently fails. Fortunately, this
is just an ugly error and not a hard failure.
The changes also come with a changelog entry for NixOS 19.03, which is
why I asked for a vote of the NixOS 19.03 stable maintainers whether to
include it (I admit it's a bit late a few days before official release,
sorry for that):
@samueldr:
Via pull request comment[1]:
+1 for backporting as this only enhances the feature set of nixos,
and does not (at a glance) change existing behaviours.
Via IRC:
new feature: -1, tests +1, we're at zero, self-contained, with no
global effects without actively using it, +1, I think it's good
@lheckemann:
Via pull request comment[2]:
I'm neutral on backporting. On the one hand, as @samueldr says,
this doesn't change any existing functionality. On the other hand,
it's a new feature and we're well past the feature freeze, which
AFAIU is intended so that new, potentially buggy features aren't
introduced in the "stabilisation period". It is a cool feature
though? :)
A few other people on IRC didn't have opposition either against late
inclusion into NixOS 19.03:
@edolstra: "I'm not against it"
@Infinisil: "+1 from me as well"
@grahamc: "IMO its up to the RMs"
So that makes +1 from @samueldr, 0 from @lheckemann, 0 from @edolstra
and +1 from @Infinisil (even though he's not a release manager) and no
opposition from anyone, which is the reason why I'm merging this right
now.
I also would like to thank @Infinisil, @edolstra and @danbst for their
reviews.
[1]: https://github.com/NixOS/nixpkgs/pull/57519#issuecomment-477322127
[2]: https://github.com/NixOS/nixpkgs/pull/57519#issuecomment-477548395
Currently, if you want to properly chroot a systemd service, you could
do it using BindReadOnlyPaths=/nix/store (which is not what I'd call
"properly", because the whole store is still accessible) or use a
separate derivation that gathers the runtime closure of the service you
want to chroot. The former is the easier method and there is also a
method directly offered by systemd, called ProtectSystem, which still
leaves the whole store accessible. The latter however is a bit more
involved, because you need to bind-mount each store path of the runtime
closure of the service you want to chroot.
This can be achieved using pkgs.closureInfo and a small derivation that
packs everything into a systemd unit, which later can be added to
systemd.packages. That's also what I did several times[1][2] in the
past.
However, this process got a bit tedious, so I decided that it would be
generally useful for NixOS, so this very implementation was born.
Now if you want to chroot a systemd service, all you need to do is:
{
systemd.services.yourservice = {
description = "My Shiny Service";
wantedBy = [ "multi-user.target" ];
chroot.enable = true;
serviceConfig.ExecStart = "${pkgs.myservice}/bin/myservice";
};
}
If more than the dependencies for the ExecStart* and ExecStop* (which
btw. also includes "script" and {pre,post}Start) need to be in the
chroot, it can be specified using the chroot.packages option. By
default (which uses the "full-apivfs"[3] confinement mode), a user
namespace is set up as well and /proc, /sys and /dev are mounted
appropriately.
In addition - and by default - a /bin/sh executable is provided as well,
which is useful for most programs that use the system() C library call
to execute commands via shell. The shell providing /bin/sh is dash
instead of the default in NixOS (which is bash), because it's way more
lightweight and after all we're chrooting because we want to lower the
attack surface and it should be only used for "/bin/sh -c something".
Prior to submitting this here, I did a first implementation of this
outside[4] of nixpkgs, which duplicated the "pathSafeName" functionality
from systemd-lib.nix, just because it's only a single line.
However, I decided to just re-use the one from systemd here and
subsequently made it available when importing systemd-lib.nix, so that
the systemd-chroot implementation also benefits from fixes to that
functionality (which is now a proper function).
Unfortunately, we do have a few limitations as well. The first being
that DynamicUser doesn't work in conjunction with tmpfs, because it
already sets up a tmpfs in a different path and simply ignores the one
we define. We could probably solve this by detecting it and try to
bind-mount our paths to that different path whenever DynamicUser is
enabled.
The second limitation/issue is that RootDirectoryStartOnly doesn't work
right now, because it only affects the RootDirectory option and not the
individual bind mounts or our tmpfs. It would be helpful if systemd
would have a way to disable specific bind mounts as well or at least
have some way to ignore failures for the bind mounts/tmpfs setup.
Another quirk we do have right now is that systemd tries to create a
/usr directory within the chroot, which subsequently fails. Fortunately,
this is just an ugly error and not a hard failure.
[1]: https://github.com/headcounter/shabitica/blob/3bb01728a0237ad5e7/default.nix#L43-L62
[2]: https://github.com/aszlig/avonc/blob/dedf29e092481a33dc/nextcloud.nix#L103-L124
[3]: The reason this is called "full-apivfs" instead of just "full" is
to make room for a *real* "full" confinement mode, which is more
restrictive even.
[4]: https://github.com/aszlig/avonc/blob/92a20bece4df54625e/systemd-chroot.nix
Signed-off-by: aszlig <aszlig@nix.build>