#1141909 tech-ctte: dh_installtmpfiles-generated dependencies

#1141909#5
Date:
2026-07-12 15:07:34 UTC
From:
To:
I am hereby asking the Technical Committee for advice and a
decision regarding dh_installtmpfiles-generated dependencies.

This is a not a topic that started recently, see e.g. [0].

dh_installtmpfiles installs tmpfiles.d configuration files.
This is a systemd invention, but src:systemd also provides
systemd-standalone-tmpfiles for other init systems.

Every Debian filesystem has one of the following:
(S) systemd as init
(I) non-systemd init
(N) no init (e.g. chroot)

The dh_installtmpfiles status quo until trixie was:
- no package dependencies created
- systemd-tmpfiles is only called after checking for its availability

It was in the past documented that dh_installtmpfiles might only
work with (S), limiting its use in Debian.

The check for availability of systemd-tmpfiles in generated maintainer
scripts was removed in [1].

Due to breakage caused by this,[2] dh_installtmpfiles now creates a
dependency on:
  systemd | systemd-standalone-tmpfiles | systemd-tmpfiles

systemd as first option is rather huge, which is undesirable in many
situations.[3]

After libselinux got rebuilt this also created a circular dependency,
causing various breakages (e.g. on our buildds).[4]

The workaround in [5] mitigated the latter, but "A library package should
not have side effects on a system." is not a correct general statement.
When I asked whether the change might introduce a security regression
the reply that Recommends are installed by default strikes me as a rather
non-convincing argument when the change is removing a dependency, and
incorrect assumptions about what can be expected to be installed are
also not helpful (Christian and Simon had more convincing arguments
why the change is mostly harmless).
In general I became convinced that this needs the TC involved which can
also make a decision to settle the issue.

One side effect of this workaround is that a package from the essential set
now recommends selinux-utils and installs it on many systems without SELinux,
wasting space.

The previous three paragraphs are about the circular dependency issue,
the debhelper maintainer suggesting to bring this topic to the TC[6]
(also implying that a 3:1 majority is not required) due to the size
of systemd pulled in predates the circular dependency issue.

While thinking about the dependency order suggestion and possible side effects
I came up with a different solution I hereby suggest as [A] and [B] depending
on what is desirable for (N):


If it is OK that tmpfiles might not be functional in (N):

  [A]
  - dh_installtmpfiles does not create any systemd-tmpfiles dependencies.
  - systemd-tmpfiles calls generated by dh_installtmpfiles are only made after
    checking for its availability.
  - init systems must ensure that a systemd-tmpfiles implementation is available.

The implementation of the last bullet point would be addition to policy 9.3 and
filing bugs against init systems.


If tmpfiles must also be functional in (N):

  [B]
  - dh_installtmpfiles does not create any systemd-tmpfiles dependencies.
  - The systemd-tmpfiles virtual package gets added to the essential set.

An essential virtual package would be similar to awk.

It does not make sense to generate dependencies in a gazillion packages
and argue about dependency order when the end result is anyway that we
are adding a (virtual) package to the essential set.


[0] https://bugs.debian.org/1017441#49
[1] https://salsa.debian.org/debian/debhelper/-/commit/14a5fb772a78854f4e57fceae2637f9dd3a58b1c
[2] https://bugs.debian.org/1140654
[3] https://bugs.debian.org/1140305
[4] https://bugs.debian.org/1140305#30
[5] https://salsa.debian.org/selinux-team/libselinux/-/merge_requests/14
[6] https://bugs.debian.org/1140305#25

#1141909#12
Date:
2026-07-12 17:45:39 UTC
From:
To:
(I'm no longer a TC member, these replies are my opinions as a DD only)

(in Adrian's option A)

It's probably useful to note that there's more than one part to
"tmpfiles might not be functional", Having an implementation of
tmpfiles.d(5) does two potentially important things, plus two
nice-to-haves:

1. immediately after installing a package with tmpfiles.d snippets that
    ask for files to be created, the files they describe are created for
    the rest of this boot (or for the rest of this chroot/container session)

2. after a subsequent reboot, the files configured to be created are
    re-created if necessary, which is important if they are on a tmpfs
    like /run

3. (nice to have) if the tmpfiles.d snippet asks for it, the files they
    describe are cleaned up when their configured lifetime expires

4. (nice to have) if the tmpfiles.d snippet asks for it, the files they
    describe are cleaned up when the package is purged
    (dh compat >= 14 only)

(1.) and (4.) are done by maintainer scripts. If debhelper stops
generating a hard dependency and starts guarding the systemd-tmpfiles
calls with a check for availability, then instead they'll be done
*conditionally* by maintainer scripts.

(2.) requires init-system support, because it's a system initialization
action: systemd does it, but as far as I'm aware, other init systems
don't (see #1139903, #1138618).

(3.) requires either a daemon or a a cron-like periodic action, which in
practice should usually be managed by a service manager (init system).

Container/chroot environments with no init can easily do (1.) and (4.),
but there's no init system to start services, daemons or cron, so (2.)
and (3.) will not usually happen.

(in Adrian's option B)
selinux-utils made a tmpfiles implementation no longer be transitively
Essential, so perhaps making systemd-tmpfiles transitively Essential is
not actually desired at this stage. But a different Essential package
could potentially gain a tmpfiles.d snippet in future, at which point
Adrian's reasoning here would apply in full (as it did before the
libselinux change).

At the moment, passwd (Priority: Required) has a tmpfiles.d snippet, so
next time it gets rebuilt with an updated debhelper, if debhelper's
behaviour has not been changed, it will pick up a dependency on a
systemd-tmpfiles implementation. That will make a systemd-tmpfiles
implementation be part of an almost-but-not-quite-minimal Debian system
- not Essential, but part of minbase, I think?

Other very common packages like sudo, udev and openssh-server also have
tmpfiles.d snippets. sudo is perhaps particularly interesting because
it's recommended (required?) for Toolbox containers (podman-toolbox in
Debian), even though those usually don't have an init system.

I've opened a separate libselinux1 bug report #1141939 (at wishlist
severity) querying whether this Recommends is necessary/helpful.

     smcv

#1141909#17
Date:
2026-07-12 20:27:12 UTC
From:
To:
Hi,

perhaps this request for advice should be extended to
dh_installsysusers-generated dependencies as well.

systemd-tmpfiles and systemd-sysusers have a similar architecture (in
particular both are based on snippet files and are available as
standalone packages) and their dh_install* commands inject the same kind
of dependencies.

Maybe a trigger-based solution could work better than a
maintscripts-based one? For examples removing issues like
order-of-installation or init-is-installed-vs-is-running.

Regards,

#1141909#22
Date:
2026-07-12 20:52:19 UTC
From:
To:
sysusers is perhaps less likely to become transitively Essential,
because if a system user is needed by Essential packages, we might as
well put it in base-passwd instead, as we did for non-Essential but very
popular packages like apt and sudo. (Unless of course the base-passwd
maintainer wants to use sysusers.d to create the basic users, which I
think some more-systemd-centric distros like Arch do, but I haven't seen
any sign of that happening in Debian.) So it might end up having
intentionally different behaviour because the conditions are different.

But I agree that it does seem worth bearing in mind - if the tradeoffs
are sufficiently similar, then using the same approach would make sense.

Would that work? I'm not sure it would, because triggers queue up
actions for later, but when a package has a systemd service or LSB init
script, we need everything to happen in the proper sequence: sysusers.d
first, then tmpfiles.d to create files/directories (which might be owned
by the newly-created user), and finally (re)start the service (which
will often need the newly-created user and/or the newly-created
files/directories).

     smcv

#1141909#27
Date:
2026-07-12 22:17:51 UTC
From:
To:
On Sun, Jul 12, 2026 at 06:45:39PM +0100, Simon McVittie wrote:
[..]

Yes. a minbase install currently only has passwd's tmpfiles.d
snippet. Note that it currently(?) is used only to clean up files on
boot, and thus not essential to the operation of passwd after
initial installation.

Chris

#1141909#32
Date:
2026-07-13 08:29:26 UTC
From:
To:
At the moment dh_installtmpfiles doesn't/can't distinguish between the
common case of tmpfiles.d snippets that (might) create things (cases 1
and 2 in https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1141909#12,
for example lines starting f, w, d, L) and the less common case of
snippets that only configure cleanup (cases 3 and 4 in the same message,
for example e, r, R). Instead it assumes that any tmpfiles.d snippet
might do both.

Cases 1 and 2 can be functionally necessary, so in general will need a
dependency, but cases 3 and 4 are merely a nice-to-have cleanup, so I
don't think they would merit a dependency (if systemd-tmpfiles was
gracefully skipped if not present).

     smcv

#1141909#37
Date:
2026-07-13 09:10:39 UTC
From:
To:
passwd is an example where lockfiles are removed during boot,
tmpfiles.d(5) contains examples for removing pid and cache
files during boot.

cu
Adrian

#1141909#42
Date:
2026-07-13 10:20:16 UTC
From:
To:
Hi Adrian and Simon and others,

thank you (plural) for adding all the context. Much appreciated.

I think there is yet another use that we should be considering
separately. Some packages use tmpfiles.d as an alternative to
dpkg-statoverride where the package installs a file using normal
ownership and permission and then a tmpfiles.d snippet changes ownership
and/or permissions. This is meant to be applied immediately after
installing (like case 1), but it extends beyond boot or container
session. This is not widely used yet (and this use may be questionable),
but a notabble case is openssh:

https://sources.debian.org/src/openssh/1%3A10.4p1-1/debian/openssh-client.tmpfiles
| x /tmp/ssh-*
| z /usr/bin/ssh-agent 2755 root _ssh

This would be bad for the openssh use case. Also note that a dependency
does not help during package purging. Unless tmpfiles become essential,
purging has to remain conditional.

If I try to take a more distant point of view, I generally perceive much
of this as a non-issue so long as there is an init system, because we
have come to expect that an init system provides this infrastructure
(sysusers.d, tmpfiles.d at boot and periodic, availability of commands
during maintainer scripts). Due to opensysusers and seedfiles, we this
extends even to hurd.

The difficult questions arise when we look at chroots and containers.
As Adrian pointed out, this is not new. The question of what we may
expect from containers surfaces every now and then and different
runtimes pose varying answers. We do expect availability of basic device
files. Most workloads expect a working /proc and some subset of /sys.
Some container runtimes support forwarding logs to the system journal.

sysusers integration is not a feature container runtimes appear to have
looked into. I also have't seen much effort at making hermetic /usr work
on containers. The expectation rather seems to be that users have been
created at the time the image is constructed. Availability of
systemd-sysusers may still be useful if additional packages are to be
installed. A dependency probably is appropriate here.

tmpfiles integration is less obvious, because application container
runtimes (and I count sbuild/schroot/mmdebstrap as runtimes) are
expected to provide some of init's functionality such as mounting /run.

So my initial feeling here is that we should look more closely at
popular container runtimes and see what form of sysusers/tmpfiles
integration they provide. Whatever they choose will be a subset of what
a full init system (including non-systemd) provides and we will likely
expand our custom container runtimes (e.g. sbuild) to match.

The other question I have is what technical downsides we'd face if
reversing the dependency and putting the standalone variants first.
Generally, when systemd already is installed nothing will change. I
agree that not putting our default init system first feels odd, but my
question is about the practical implications of putting the standalone
thing first.  So long as we ensure that no transitively essential
package uses tmpfiles.d (and that still seems possible), it might work
well enough.

Helmut

#1141909#47
Date:
2026-07-13 13:49:39 UTC
From:
To:
that we expect will persist between boots or chroot/container sessions
(like /etc, /var), or one that we expect probably won't persist (like
/run, /tmp).

I think we can treat that as similar to the case where files are created
on a filesystem that persists: in both cases, we expect that after a
reboot or a container restart, the state change will persist. So we
don't need an init system, as long as the maintainer script has ensured
that the state change really happened.

Indeed, and for any other case where the state-change encapsulated in
tmpfiles.d is functionally necessary.

Yes, like most things that happen during purge, but this is already the
case (reference:
/usr/share/debhelper/autoscripts/postrm-init-tmpfiles-purge).

Yes, and this is what Guillem suggested on #1140305. Adrian didn't
present that as an option when opening this bug, but I think it's worth
considering, even if it ends up being rejected for the reasons he gave
("It does not make sense to generate dependencies in a gazillion
packages and argue about dependency order when the end result is anyway
that we are adding a (virtual) package to the essential set.").

I'm not so sure that we really *are* adding -tmpfiles to the
transitively Essential set, and if we are not, then that makes Adrian's
reasoning less compelling.

     smcv

#1141909#52
Date:
2026-07-13 15:28:59 UTC
From:
To:
Reading my initial post in this bug again, I referred to it as
"the dependency order suggestion" but failed to present it properly.

Generating dependencies and keeping tmpfiles out of the Essential set
implies defining which packages are prohibited from using tmpfiles,
and continuously enforcing that.

In the libselinux1 case it strikes me as reasonable that a library was
creating the directory for a socket it might be using.

As you already noticed, the next rebuild of passwd will create a
tmpfiles dependency.

If attempting to keep tmpfiles out of the Essential set, the first
question is whether passwd is part of the packages in the Essential
set that are prohibited from using tmpfiles due to the dependency
it would generate.

Telling maintainers of packages in the Essential set (like libselinux1)
that they must not use tmpfiles while dependencies of other packages
will anyway install it de facto everywhere in the future - that's a lot
of hassle without real benefits.

If not having tmpfiles available in some "no init" setups is desirable,
then we do not want to have dependencies generated that would pull it in.

If we want to guarantee that everything from systemd-tmpfiles calls in
maintainer scripts will always happen, then adding tmpfiles to the
Essential set is the simplest solution.

seedfiles+libcap2 is only 220kB, not something huge to avoid at any cost.

cu
Adrian

#1141909#57
Date:
2026-07-13 16:13:20 UTC
From:
To:
essential. And when I say reasons, I don't want to say "we must keep it
out", but highlight aspects that can be weighed to form an opinion.

The obvious one is keeping essenntial small.

The other is mentioned in my other mail: You cannot just include a
package in essential. Special policy requirements apply to packages in
essential and systemd does not satisfy them, because it is known to not
work at all times in an unpacked state. Not having tmpfiles in essential
means that we can avoid figuring out how to make systemd suitable for
essential. It also means that it'll be less likely for a systemd upload
to break our build infrastructure.

The choice now becomes one of:
 1. Keep tmpfiles out of essential.
 2. Make it essential and ignore our experience with systemd breaking
    during upgrades.
 3. Make it essential and make systemd more robust.

Having multiple providers of tmpfiles also poses a challenge to being
essential. While we also do this for awk, it is half a lie and only
works well, because awk both rarely used in maintainer scripts and
rarely switches implementations. I am pretty sure that I can craft an
upgrade scenario where awk violates policy. With multiple tmpfiles
providers and lots of users, we are way more likely to encounter the
situation where the essential functionality is not always provided. The
coreutils-from package also runs into this and uses diversions to ensure
that switching providers satisfies essential requirements.

Even though I present reasons not to make it essential, I am in favor of
promoting the tmpfiles.d mechanism as the tool of choice for the tasks
it solves.

And then, the reasons I give are all addressable with effort rather than
being fundamental limitations. Would anyone be interested in working on
making systemd more robust in upgrades or making the tmpfiles provider
switching more robust?

Again, I am voicing my own opinion and not CTTE's.

Helmut

#1141909#62
Date:
2026-07-13 14:27:37 UTC
From:
To:
I bet that you mentioned this elsewhere. This distinction into
persistent (when not considering hermetic-/usr) and ephemeral could also
be embodied into dependencies. We could have one dependency for having
the command line utility and another for the tmpfiles boot/periodic
services. Parsing the files could tell them apart. Not sure this is
actually needed.

Given the state of discussion, I am pretty sure that a virtual package
(that has been proposed elsewhere already) is the way to go. The
generated dependency should likely become "default-systemd-tmpfiles |
systemd-tmpfiles" and then we can argue about which package should
provide the default at will and even change it retroactively if our
choice turns out to be bad.

I still hope that we can get away keeping tmpfiles out of essential
while having it in the required set (aka debootstrap variant minbase).

Let me raise an argument against making it essential. Essential packages
must work at all times in an unpacked state. It is known that packages
that link libsystemd0 (e.g. systemd) do not always work during upgrades.
While systemd-standalone-tmpfiles could fill the essential spot, systemd
providing systemd-tmpfiles could not. If we wanted to get there, systemd
would have to turn multiple versions of libsystemd0 coinstallable and
basically bump the private version on every upgrade.  This idea is not
new either. I've seen it mentioned at least by Michael Biebl.

Opinions stated here and in my earlier mail on this thread are my own
and not CTTE advice.

Helmut

#1141909#67
Date:
2026-07-13 17:45:14 UTC
From:
To:
Is my understanding correct that you are saying that while tmpfiles
might become part of the (transitive) essential set that is always
installed, we would still need package dependencies for ensuring
the correct order of package configuration during upgrades?

This would rule out my [A] option, since the dependency would exist
also in "no init" situations.[1]

cu
Adrian

[1] A dummy provider with "systemd-tmpfiles -> /usr/bin/true"
    might be possible if really desirable.

#1141909#72
Date:
2026-07-13 19:23:14 UTC
From:
To:
libsystemd0 (libsystemd.so.0) is an ordinary boring shared library like
zlib or whatever, but libsystemd-shared is a code reuse mechanism for
tightly-coupled systemd packages (libsystemd-core-261.so and
libsystemd-shared-261.so, as of v261).

If you mean libsystemd-shared, then, yes, that's a compelling argument
for why systemd.deb is OK to pull in at Priority: required but not OK to
be transitively Essential.

     smcv

#1141909#77
Date:
2026-07-13 21:29:20 UTC
From:
To:
Probably. It depends on the exact sequence of events. In principle, some
essential package could now depend on systemd-tmpfiles. Then once forky
is released, packages could start relying on it being there. I very much
expect that we want forky packages to be able to rely on
systemd-tmpfiles. Those packages cannot assume systemd-tmpfiles
presence, because the package depending on systemd-tmpfiles might be
upgraded later. So all packages that want to rely on systemd-tmpfiles in
forky must carry the dependency.

We could still get A for duke without additional dependencies, but for
forky I am inclined to agree.

Helmut

#1141909#82
Date:
2026-07-13 21:31:49 UTC
From:
To:
Yes. Thank you for correcting me and it was meant as you said.

Keep in mind that libsystemd-shared could be renamed with every upload
(and autoaccepted in the NEW queue).  This is not a fundamental
limitation, but an aspect of how systemd is currently maintained.

Helmut

#1141909#87
Date:
2026-07-13 23:06:22 UTC
From:
To:
* Helmut Grohne <helmut@subdivi.de> [260713 13:15]:
[..]

I'll note that it could also be a real package which is otherwise
empty, just to hold the dependencies. This would be somewhat like
the `init` package.
[..]

The systemd implementation of tmpfiles also requires /proc, which is
less than ideal in a number of important-yet-not-default cases, for
example chroots and (system) images currently under construction.

Best,
Chris

#1141909#92
Date:
2026-07-14 12:05:36 UTC
From:
To:
That's something different.

I was referring to your "work at all times in an unpacked state"
for packages with "Essential: yes".

Even when it is always installed, a dependency on the virtual package
would ensure that the tmpfiles provider is in a configured state when
a package using it calls systemd-tmpfiles.

When debhelper generated the dependency in libselinux1, this had two
effects:
1. the virtual package became part of the (transitive) essential set
2. during upgrades of libselinux1 it ensured that the systemd-tmpfiles
   implementation was configured before libselinux1

Unless I am missing something, this implies that the virtual package
systemd-tmpfiles could enter the transitive essential set without
having to be functional when unconfigured.

cu
Adrian

#1141909#97
Date:
2026-07-15 10:43:26 UTC
From:
To:
Indeed, this is more nuanced. Let me state some properties and see when
they hold.

A. systemd-tmpfiles works during a maintainer script of a particular
   package.

   We definitely want this property to hold for the cases where
   systemd-tmpfiles is being used for implementing core functionality of
   a package.

B. systemd-tmpfiles works at all times even when it is temporarily
   deconfigured (e.g. for being upgraded or replacing the provider).

   This is the policy requirement for essential packages.

C. A systemd-tmpfiles provider is part of the transitively essential
   set.

   Policy requires that this implies B.

D. A systemd-tmpfiles provider is part of the essential set.

   This is where packages do not have to declare dependencies on
   systemd-tmpfiles to use it. It implies C.

I argued that the systemd-tmpfiles command as provided by the systemd
package does not satisfy property B, because unpacking libsystemd-shared
or systemd without simultaneously unpacking the other breaks calling it.
When packages issue the dependency, systemd (as a systemd-tmpfiles
provider) will be configured, so adding explicit dependencies to
systemd-tmpfiles users satisies property A without addressing property
B. If libsystemd-shared were renamed on every upload and systemd were
pre-depending on libsystemd-shared, then apt would be forced to unpack
the new libsystemd-shared before unpacking systemd and it would likely
keep the old one until systemd is unpacked. That way, property B would
be satisified. When changing the systemd-tmpfiles provider, apt
temporarily uninstalls the current provider and that way technically
breaks property B, but we are tolerating this failure mode for awk
already. A dependency of libselinux1 on systemd-tmpfiles causes C to
hold, but this does not imply D, so packages would be forced to continue
to depend on it. If we were to actively pull systemd-tmpfiles into the
essential set (e.g. by having base-files depend on it), we'd call D
satisfied (after the next stable release). So yes, I think there is a
way to have D without having each and every package depend on
systemd-tmpfiles. Just keep in mind that all forky packages need to
support upgrading from trixie, so packages cannot rely on D in the forky
cycle. For forky packages to rely on systemd-tmpfiles, they have to
explicitly depend on it.

I hope this adds clarity rather than more confusion.

Helmut

#1141909#102
Date:
2026-07-21 15:19:19 UTC
From:
To:
Section 3.8. only requires it for packages marked "Essential: yes".

I also do not see how such a requirement would make sense:

Shared libraries can be part of the transitively essential set,
but packages cannot assume the availability of a library since
it might disappear during an upgrade to the next release.
Therefore all users already have to depend on shared libraries
in the transitively essential set in any case.

When dh_installtmpfiles generates dependencies, then C should be
fine even without B, similar to shared libraries.

From a practical point of view, I do also not see why passwd using
systemd-tmpfiles might be fine, but packages in the transitively
essential set like libselinux1 should be banned from using
systemd-tmpfiles due to one implementation using libsystemd-shared.

cu
Adrian

#1141909#107
Date:
2026-07-23 06:40:53 UTC
From:
To:
Hi Adrian,

I now see how you can read it that way. We may have to clarify it.
Evidently, my earlier attempt at clarifying it was not entirely
successful. The intention was to state that packages cannot be part of
the transitive essential set if they do not work when deconfigured.

This is why essential packages have their library dependencies upgraded
to Pre-Depends. It tells our package mananager that it cannot remove the
library before removing the depender.

If we assume that all users generate dependencies, the problem of not
always working does not affect theirt postinst and prerm scripts. Such a
dependency does not help with preinst (unless Pre-Depends) and postrm.

As pointed out elsewhere, that libsystemd-shared problem is a limitation
of the current implementation rather than a fundamental barrier. The
essential set indeed is special, because we never what other packages
need it.

There seems to be some ambiguity about the notion of essential that
still feels difficult to grasp. You're right that shared libraries can
and do enter and exit the transitive essential set. Hence, packages must
depend on them explicitly. The same could be argued for
systemd-tmpfiles. But then, awk also is kinda in that role and yet we
argue that availability of /usr/bin/awk is an essential feature to be
relied upon at all times. To me, this is a really good reason for
resuming work on removing awk from essential (as its size is not that
big of a reason).

I don't quite like a systemd-tmpfiles as a transitive essential package,
because unlike library packages dependencies on it are not entirely
automatic and you can miss them if you use the tool manually. A
transitive essential existence, would make such missed dependencies
likely and as a consequence would factually promote the package to full
essential with all the strings attached. I only really see the states of
not-essential and fully-essential as desirable end-states.

Again, opinions are my own.

Helmut