One of the module that already supports the systemd-confinement module
is public-inbox. However with the changes to support DynamicUser and
ProtectSystem, the module will now fail at runtime if confinement is
enabled (it's optional and you'll need to override it via another
module).
The reason is that the RootDirectory is set to /var/empty in the
public-inbox module, which doesn't work well with the InaccessiblePaths
directive we now use to support DynamicUser/ProtectSystem.
To make this issue more visible, I decided to just change the priority
of the RootDirectory option definiton the default override priority so
that whenever another different option is defined, we'll get a conflict
at evaluation time.
Signed-off-by: aszlig <aszlig@nix.build>
Our more thorough parametrised tests uncovered that with the changes for
supporting DynamicUser, we now have the situation that for static users
the root directory within the confined environment is now writable for
the user in question.
This is obviously not what we want and I'd consider that a regression.
However while discussing this with @ju1m and my suggestion being to
set TemporaryFileSystem to "/" (as we had previously), they had an even
better idea[1]:
> The goal is to deny write access to / to non-root users,
>
> * TemporaryFileSystem=/ gives us that through the ownership of / by
> root (instead of the service's user inherited from
> RuntimeDirectory=).
> * ProtectSystem=strict gives us that by mounting / read-only (while
> keeping its ownership to the service's user).
>
> To avoid the incompatibilities of TemporaryFileSystem=/ mentioned
> above, I suggest to mount / read-only in all cases with
> ReadOnlyPaths = [ "+/" ]:
>
> ...
>
> I guess this would require at least two changes to the current tests:
>
> 1. to no longer expect root to be able to write to some paths (like
> /bin) (at least not without first remounting / in read-write
> mode).
> 2. to no longer expect non-root users to fail to write to certain
> paths with a "permission denied" error code, but with a
> "read-only file system" error code.
I like the solution with ReadOnlyPaths even more because it further
reduces the attack surface if the user is root. In chroot-only mode this
is especially useful, since if there are no other bind-mounted paths
involved in the unit configuration, the whole file system within the
confined environment is read-only.
[1]: https://github.com/NixOS/nixpkgs/pull/289593#discussion_r1586794215
Signed-off-by: aszlig <aszlig@nix.build>
Otherwise, setting services.caddy.enableReload to false fails in a very bad fashion:
The reload command still gets executed, but fails:
```
Apr 26 21:23:01 n1-rk1 systemd[1]: Reloading Caddy...
Apr 26 21:23:01 n1-rk1 caddy[70793]: {"level":"info","ts":1714166581.733018,"msg":"using provided configuration","config_file":"/etc/caddy/caddy_config","config_adapter":"caddyfile"}
Apr 26 21:23:01 n1-rk1 caddy[70793]: {"level":"warn","ts":1714166581.7353032,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/caddy_config","line":3}
Apr 26 21:23:01 n1-rk1 caddy[70793]: Error: sending configuration to instance: performing request: Post "http://localhost:2019/load": dial tcp [::1]:2019: connect: connection refused
Apr 26 21:23:01 n1-rk1 systemd[1]: caddy.service: Control process exited, code=exited, status=1/FAILURE
Apr 26 21:23:01 n1-rk1 systemd[1]: Reload failed for Caddy.
```
… and the server is not restarted either, as a ExecReload= command is
specified.
Fix this, by only setting ExecReload if the reload exists.
The first empty string is still necessary to reset the old option.
Add missing http:// scheme. Without it pixiecore logs this and never
contacts the API server:
[DHCP] Couldn't get bootspec for [REDACTED_MAC_ADDR]: Get "localhost:8080/v1/boot/[REDACTED_MAC_ADDR]": unsupported protocol scheme "localhost"
This adds an implementation of switch-to-configuration that allows for
closer interaction with the lifecycle of systemd units by using DBus
APIs directly instead of using systemctl. It is disabled by default, but
can be enabled by specifying `{ system.switch = { enable = false; enableNg = true; }; }`.