dcf40f7c24
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 |
||
---|---|---|
.. | ||
activation | ||
boot | ||
etc |