Open mbiebl opened 2 years ago
Yeah, I had a similar thought. Or maybe we should allow tmpfiles snippets to be specified in unit files, and systemd would execute them (through some helper service probably) when starting the unit.
Let's not add complex stuff like this for such weak cases as #21317. If people don't want systemd-resolved to take over /etc/resolv.conf then great, but they should then declare what else is owning that file.
You don't resolve issues of ownership by not owning the file at all.
Let's not add complex stuff like this for such weak cases as #21317. If people don't want systemd-resolved to take over /etc/resolv.conf then great, but they should then declare what else is owning that file.
I think it's a valid use case.
You don't resolve issues of ownership by not owning the file at all.
systemd-resolved claiming the file when it is not even enabled is just plain and simple wrong.
That said, this is just a specific use case.
This disconnect between .service units and their corresponding tmpfiles has bugged me for a while.
It would be nice to have resolved be able to overwrite the file as well if enabled. On Arch resolv.conf is empty in the initial rootfs when installing and users always have to create the resolved symlink manually on top of enabling resolved. It'd be nice if enabling resolved implied installing the symlink as well.
I am pretty sure we should not put emphasis on associating system resources with services. Instead focus on making service resources truly service associated in the first place.
i.e. RuntimeDirectory=, StateDirectory=, … are a much better approach to most of what tmpfiles.d is used for. this is stuff with very clear semantics, and a much more focused usecase. It pushes people towards doing the right thing.
Hence, instead of adding glue between tmpfiles.d and services: don't. Just make people use RuntimeDirectory= and suchlike, it should cover 80% of what people misuse tmpfiles.d for.
The way I see it, tmpfiles.d should only be used for truly system-scoped files. If I however look into the files fedora packages actually install it's mostly packaged scoped files, and they really shouldn't use it for that. on my system here, it's colord, cups, gluster, hplip, httpd, iscsi, libgpod, podman, ppp, … that put daemon-specific stuff in tmpfiles snippets, that could as well just be RuntimeDirectory= + StateDirectory= stuff. (And i stopped looking, it's really the vast majority).
It would be nice to have resolved be able to overwrite the file as well if enabled.
Nah resolved is a consumer of the file happily, too. resolved is very defensively put together to be either provider or consumer, depending how you choose to create the symlink. Overriding that is breaking that ownership rule, and we shouldn't do that, given that we expressly support both scenarios: where we consume and where we provide that file.
Well, problem is, that RuntimeDirectory is not flexible enough (you can't even modify permissions). Sometimes services need more then just a runtime directory and its fixed semantics. That's the real world. RuntimeDirectory only works for the most trivial of cases.
Instead focus on making service resources truly service associated in the first place.
Right, that's exactly what is proposed here.
Well, problem is, that RuntimeDirectory is not flexible enough (you can't even modify permissions).
You can! RuntimeDirectoryMode= exists. What else do you need?
Sometimes services need more then just a runtime directory and its fixed semantics. That's the real world.
Yeah, for stuff that wants to manage stuff that belongs to the system special rules apply, but I am not sure we need to add additional infra for that: if your software can't accept ownership concepts, then that's OK but things won't be automatic and people shouldn't expect otherwise.
Instead focus on making service resources truly service associated in the first place.
Right, that's exactly what is proposed here.
No? You want to manage system resources in tmpfiles.d and bind that to service enablement/runtime, and I am not convinced that's desirable.
I am suggesting to move things that are currently managed as system resources into service scope, i.e. stop using tmpfiles.d at all, but only operate in directories specific to the services.
Well, problem is, that RuntimeDirectory is not flexible enough (you can't even modify permissions).
You can! RuntimeDirectoryMode= exists. What else do you need?
You can't A common use case is a shared runtime directory between different services which use a common group.
I am suggesting to move things that are currently managed as system resources into service scope, i.e. stop using tmpfiles.d at all, but only operate in directories specific to the services.
If tmpfiles snippets are supported inside a .service unit (as @keszybz suggested), that would work fine for me as well. It's just a different way of implementing it.
Well, problem is, that RuntimeDirectory is not flexible enough (you can't even modify permissions).
You can! RuntimeDirectoryMode= exists. What else do you need?
Multiple runtime directories is another example.
You can't A common use case is a shared runtime directory between different services which use a common group.
So you mean ownership, not permissions. Group ownership works fine though, too? Just use Group=? What am I missing?
Multiple runtime directories is another example.
Works fine, just specify as many as you want?
So you mean ownership, not permissions. Group ownership works fine though, too? Just use Group=? What am I missing?
You don't necessarily want the service executed as another User or Group, you just want to change the ownership of certain directories.
Example: you want a service which sets up the directories (not necessarily in /run or any of the hard-coded paths) with proper ownership and permissions for other services/programs being able to access them. The service itself could e.g. itself need root privs so.
As said RuntimeDirectory is often simply not flexible enough.
RuntimeDirectoryMode=
If I'm not mistaken, this applies to all directories specified via RuntimeDirectory=.
Last time I used RuntimeDirectory=, it also brutally removed the directory when the service was stopped. This doesn't work if you have multiple services/apps using the same directories
You don't necessarily want the service executed as another User or Group, you just want to change the ownership of certain directories.
Example: you want a service which sets up the directories (not necessarily in /run or any of the hard-coded paths) with proper ownership and permissions for other services/programs being able to access them. The service itself could e.g. itself need root privs so
The way this is covered is through ExecStart=!
. i.e. if the service shall be invoked as root even though there's a user associated with it, then declare this via the !
. This is for example the case if services intend to drop privs on their own.
As said RuntimeDirectory is often simply not flexible enough.
So far the cases you listed are all covered afaics.
But yes, there are certainly cases where RuntimeDirectory= cannot express what people want. But I'd say it's OK if those cases are not as pretty, because what you are doing then is simply not pretty, we shouldn't hide that. We should push people towards not doing things like that, and having clear concepts of services, users and directories and how they belong together.
As I mentioned I am pretty sure RuntimeDirectory= (and related settings) if properly used can cover 80% of the cases tmpfiles.d is currently used for. The 20% exist, but I am not convinced it's worth adding "pretty glue" for them. They should be a bit ugly and less smooth, so that people stop doing things that way.
Last time I used RuntimeDirectory=, it also brutally removed the directory when the service was stopped. This doesn't work if you have multiple services/apps using the same directories
RuntimeDirectoryPreserve=
btw, if you really want you can already embed tmpfiles.d snippets in your own unit. Add a helper unit like this:
[Unit]
Description=Preparation for My Service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-tmpfiles --create --remove -
StandardInputText= \
w /run/foo 0755 root root - "bar" \
…
And then pull that in from your service
So far the cases you listed are all covered afaics.
Nope, not really. But I guess you've already made up your mind, so its pointless to discuss this. Of course we could wish the world was prettier and ignore existing software and hope they would all behave the same, but they often don't.
As I mentioned I am pretty sure RuntimeDirectory= (and related settings) if properly used can cover 80% of the cases tmpfiles.d is currently used for. The 20% exist, but I am not convinced it's worth adding "pretty glue" for them. They should be a bit ugly and less smooth, so that people stop doing things that way.
I quickly checked the Debian archive. According to codesearch.debian.net we have a 100 packages using RuntimeDirectory. On the other hand we have 173 packages installing 185 tmpfiles. And there is a good bunch of services that run ExecStartPre=install -d (or a variation thereof).
So either all of those software maintainers are too stupid to understand the documentation, our documentation sucks or simply RuntimeDirectory= doesn't meet their needs.
I will agree with you that the RuntimeDirectory= feature set is not well advertised. I should probably do a blog story about it, i.e. pointing people to the fact that RuntimeDirectoryMode= RuntimeDirectoryPreserve= exists, and that ExecStart=! exists and is useful for this.
btw, if you really want you can already embed tmpfiles.d snippets in your own unit. Add a helper unit like this:
[Unit] Description=Preparation for My Service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/systemd-tmpfiles --create --remove - StandardInputText= \ w /run/foo 0755 root root - "bar" \ …
And then pull that in from your service
Well, aside from requiring a lot of boilerplate this is also super ugly. I don't consider this a "solution".
It would be nice to have resolved be able to overwrite the file as well if enabled. On Arch resolv.conf is empty in the initial rootfs when installing and users always have to create the resolved symlink manually on top of enabling resolved. It'd be nice if enabling resolved implied installing the symlink as well.
Empty file is not really useful. I think it might be workaround for what I am trying to fix in MR #21317. If it were missing, which is functionally equivalent, my proposal would solve that. Can you find a reason for empty file in its package changelog?
So you mean ownership, not permissions. Group ownership works fine though, too? Just use Group=? What am I missing?
You don't necessarily want the service executed as another User or Group, you just want to change the ownership of certain directories.
Example: you want a service which sets up the directories (not necessarily in /run or any of the hard-coded paths) with proper ownership and permissions for other services/programs being able to access them. The service itself could e.g. itself need root privs so.
As said RuntimeDirectory is often simply not flexible enough.
Adding idmapping support for runtime and state directory is on my to-do list and I should get to it next month. That will make ownership issues moot.
In 250 i also added support for src:dst via symlinks, so that different services can use the same resource even using different names.
Many packages nowadays use a tmpfile to setup their runtime files. There are cases though, where a package is installed, but the corresponding service is not enabled, yet the tmpfile is processed during boot and where this can problems or is simply unnecessary. For a recent case, see #21317
I'd like the tmpfiles format to be extended. We add a new key there, like say
Unit=
(better names welcome)Example: you have a /usr/lib/tmpfiles.d/foo.conf which should only be run if foo.service is enabled. You can add a
Unit=foo.service
key to /usr/lib/tmpfiles.d/foo.conf and the tmpfile would only be processed if foo.service is enabled.This would have the benefit, that you can tie the processing of the tmpfile to the enablement state of the corresponding service/unit.