[systemd-devel] /usr vs /etc for default distro units enablement

Colin Guthrie gmane at colin.guthr.ie
Tue Nov 18 05:01:46 PST 2014


Martin Pitt wrote on 18/11/14 12:01:
> Hello Colin, all,
> 
> Colin Guthrie [2014-11-18 11:30 +0000]:
>> I believe that it is generally discouraged to use "systemctl enable"
>> indirectly or otherwise during postinst.
> 
> Right, I don't like this either, hence this discussion. :-) I don't
> know whether Debian's current way of enabling units on package install
> has ever been discussed here, but Didier and I would like to
> understand the options and some recommendations, to consider whether
> it makes sense to change this in D/U.
> 
>> You should instead use systemctl preset which uses information in
>> various distro provided *.preset files that contain rules for which
>> units should be enabled or disabled.
>>
>> This allows a "default" /etc tree of symlinks to be repopulated easily.
> 
> We can certainly ship a preset of "enable *" to reflect the policy
> that in general services do get enabled by default. But this still
> leaves some issues:
> 
>  * I suppose even wich such a policy the post-installation script
>    still needs to call some systemd-update-policy-mumble-mumble magic
>    to actually apply the new policy?

Well, the *.policy files are simply read when calling "systemctl preset"

The idea is that there are very few policy files shipped in a distro and
on initial installation (and depending on how the installer wors), they
would be installed very early on such that any postinst script of
packages getting installed would adhere to that policy.

I would say it's generally discouraged to "reapply" a policy again at a
later date as this would override any admin decisions made in the meantime.

I'd say it's perfectly acceptable to call systemctl preset-all
--preset-mode=full at the end of an installation however.


>  * With that, how would a package then say that it does *not* want a
>    particular unit to get enabled?

The idea is that you don't really decide that at a package level, but at
a distro level.

The distro (or spin) might make these default decisions and ship them in
the ubuntu.preset file accordingly.

So ultimately the *package* doesn't decided. The vendor decides that
"this is a package that should go against our normal policy" and embed
that information in their policy file.

It's not generally encouraged to ship *.preset files with packages
(nothing to stop you of course, but the idea is to keep these preset
files fairly manageable and thus allow easy respins of distros using the
same packages but perhaps taking on different policies).


>  * This doesn't solve the problem of having these rather uninteresting
>    and cluttering symlinks in /etc at all; the wants.d symlinks would
>    still be as they are now, just the place that decides when to
>    enable them changes.

Indeed, but ultimately if you want to make something configurable in
some capacity, you have to put that configuration somewhere and /etc is
the defacto place to put it.

So I'd say that if these really are things you want admins to be able to
disable, then having them here is correct.


>> If a package ships a unit enabled via a symlink in /usr/lib, then that
>> same package should ensure the systemd unit does NOT have an [Install]
>> section.
>>
>> Doing so is confusing to the user, so if the packager makes this
>> decision, he should follow it through properly.
> 
> But then you would entirely lose the information into which target a
> service belongs by default. 

Only if you don't look at the shipped symlink - it would still be
embedded in that.

> In particular, an administrator couldn't
> override the default it with "systemd disable" (I know that this
> doesn't work right now, but it's part of the discussion).

Yes, it's true that an admin could not override the default target but
he could easily add the unit to *another* target via a wants symlink in
/etc/.

But I'd say that if you, as a vendor, are shipping an enabling symlink
in /usr/lib in the first place, you're making a concious decision that
this is something you don't generally want an admin to override easily.
The admin only really has the choice of masking it.

My general recommendation would be that if you want to let the admin
control things, then don't ship the enabling symlink in /usr/lib :)

>> If this is an upstream make-install rule, then it should be fixed
>> upstream to make it consistent - again the rules is "if you ship a
>> symlink in /usr/lib, you should not have an [Install] section" (I think
>> this is good advice but I'm sure someone will correct me if I'm wrong!).
> 
> I think there are some plymouth .service files with that problem,  but
> as far as I can see, most upstreams leave it to packagers to enable
> their units.


All of my plymouth units show as static here so I don't think any have
[Install] sections:


[colin at jimmy log (master)]$ systemctl status plymouth-*
● plymouth-start.service - Show Plymouth Boot Screen
   Loaded: loaded (/usr/lib/systemd/system/plymouth-start.service; static)
   Active: inactive (dead) since Fri 2014-11-14 15:28:55 GMT; 3 days ago
 Main PID: 150 (code=exited, status=0/SUCCESS)

● plymouth-read-write.service - Tell Plymouth To Write Out Runtime Data
   Loaded: loaded (/usr/lib/systemd/system/plymouth-read-write.service;
static)
   Active: inactive (dead) since Fri 2014-11-14 15:28:53 GMT; 3 days ago
 Main PID: 279 (code=exited, status=0/SUCCESS)

● plymouth-quit.service - Terminate Plymouth Boot Screen
   Loaded: loaded (/usr/lib/systemd/system/plymouth-quit.service; static)
   Active: inactive (dead)

● plymouth-quit-wait.service - Wait for Plymouth Boot Screen to Quit
   Loaded: loaded (/usr/lib/systemd/system/plymouth-quit-wait.service;
static)
   Active: inactive (dead) since Fri 2014-11-14 15:28:55 GMT; 3 days ago
 Main PID: 373 (code=exited, status=0/SUCCESS)


("grep Install /usr/lib/systemd/system/plymouth*.service" confirms no
matches and I don't see any downstream patches)


But indeed, most upstreams do (and indeed should) not ship an enabling
symlink. Most things are ultimately admin decisions so it's quite rare
that you'd want such symlinks. I'd say plymouth is a good example of
somewhere where it makes sense to enable them all the time as it has a
different enabling mechanism outside of systemd and thus shipping the
enabling symlinks kinda makes sense and avoids potential breakage if
admins interfere!

>>> - Wrt. the "golden image, /etc reset" approach of reducing base os
>>> installation defaults in /etc, this is another instance of "always needs
>>> to be there" clutter in /etc. If the package default is  to start the
>>> service, then it's better to just ship that wants.d/ symlink in the
>>> package (and thus in /usr) instead of always having to create the
>>> symlink in /etc at package install time or after a factory reset.
>>
>> Yes and no. Depending on your use case perhaps shipping it in /usr/lib
>> is OK (e.g. an embedded system that still wants to support factory
>> reset), but I'd say that generally speaking, this is what *.preset files
>> and systemctl preset is meant to achieve. They represent the distro
>> rules, but still give users full control after the default rules are
>> applied.
> 
> I might misunderstand presets, but as I wrote above they don't address
> this at all -- even with them you have preset-induced wants.d/
> symlinks in /etc.
> 
> I. e. my question is not so much about being able to restore the
> default wants.d symlinks in /etc after a factory reset -- there are
> multiple ways how this can be done: with presets or iterating over the
> installed packages and re-enabling them (Debian also does some
> house-keeping which unit files got enabled by postinstall scripts,
> which can simply be replayed).
> 
> I was rather wondering whether we couldn't make all that
> post-processing much simpler by not requiring any /etc/**/wants.d/
> links at all. And everything which *is* in /etc/**/wants.d/ would then
> be explicit admin choices, with both enabling and disabling units.

OK, but I think this is the wrong approach personally.

I see the symlinks as desirable and necessary and they accurately
reflect the state of things as desired by the vendor and/or the admin,
whether this is immediately after a factory reset, after a puppet run or
after several years of admins randomly enabling and disabling things.


I think moving enabling symlinks into the packages (and thus /usr) has
several drawbacks:

1. It pushes decision making on such policy to be distributed through
thousands of packages rather than being centralised and thus makes it
very difficult to do respins and change such policy centrally.

2. It makes the packaging task more complex - these links have to be
created during packaging (although I'm sure this could be mostly automated).

3. I makes it much less clear to users if they see such links embedded
and shipped with packages (IMO) but can still disable them if they so wish.


So I guess my reply to this is, this is OK, and I think this goal is not
one to aim for. It's "state" information and it should be represented in
/etc and I don't think trying to reduce this is a good idea (personally!) :)


>>> - We are mixing sys admin information and distro default choices in the
>>> same directories, and can't tell apart what is what.
>>
>> /etc is admin, and the distro *default* is applied there (via *.preset
>> files) but the admin still has full control.
> 
> Sure she does, but this still makes it waaay harder to see on a system
> how it deviates from the default install.

Perhaps teaching systemd-delta or systemctl status to show you the
preset state would solve this problem? e.g. if it showed something like:


[colin at jimmy log (master)]$ systemctl status sshd.service
● sshd.service - OpenSSH server daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled
[preset: disabled])
   Active: active (running) since Fri 2014-11-14 15:29:28 GMT; 3 days ago
 Main PID: 18816 (sshd)
   CGroup: /system.slice/sshd.service
           └─18816 /usr/sbin/sshd -D


Perhaps that would help?

Perhaps we could even add two more (optional) columns to systemctl
list-units for "ENABLED" and "PRESET"?

This way it works just as well for ssh (which you maybe enable by
default on Ubuntu - I've not checked!) to properly reflect the preset
state when shipped with a "Secbuntu" respin which has more paranoid
service policy (because it ships different preset files) without needing
to actually ship a different sshd package.

>> 1. Discourage strongly the shipping of enabling symlinks in /usr/lib
>> (but aliases are probably OK).
> 
> I'm interested in the reason for that. This basically cements the
> status quo that one *has* to have a gazillion links in /etc in order
> for your system to work, even if they are not at all specific to the
> particular system or represent a deviation from the default install.

Depends what you mean by "work" here tho'. I mean, the system should be
able to *boot* without lots of service enabled, but it's ultimately your
*choice* that you want to run sshd or faxd or postfix etc and I
personally don't see a problem with storing this configuration (aka a
gazillion links) in /etc.

>> 2. If a special case arises where a an enabling /usr/lib symlink is
>> deemed the best option, the unit must not have an [Install] section.
> 
> I rather want to discuss this in the general case, to reduce the
> clutter in /etc/. I don't  think it's right to remove [Install] for
> all units, see above.

Fair enough, I won't beat the drum too much :) But I do think this
configuration is exactly that, configuration, and thus living in /etc/
is both expected and normal.

>> 3. Do not use "systemctl enable myunit.service" (directly or indirectly)
>> in packaging postinst, but rely on "systemctl preset myunit.service"
>> instead to capture the distribution (or spin) rules.
> 
> That part is fair enough, and we can see whether that should be done
> in Debian, but in practice it will make absolutely no difference wrt.
> file system layout, cleaning up /etc/, and making admin choices more
> obvious.

I kinda disagree that it makes admin choices more obvious. I often list
files in a package to look at what it contains and if I see an enabling
symlink I might be fooled into thinking something should be enabled,
even if some other, non-packaged, config overrules it. This can happen
just now for masking but opening it up for regular disabling too would
seem like a bad idea with respect to clarity to me (again, just my
personal opinion).

But hopefully my systemctl status/list-units suggestions above might be
good solutions here anyway.


>> This deals means:
>>
>>  1. distro installs the default setup for users, but admins can override
>> later
>>  2. factory reset works fine (assuming "systemctl preset-all
>> --preset-mode=enable" is run after reset)
>>  3. systemctl status will work (because only units without [Install]
>> sections will have enabling links in /usr/lib)
> 
> I fully agree on these properties; your recommendations from above
> (which is essentially the status quo) certainly works for that, but I
> really think we can do better here.
> 
> With our proposal these properties would also be satisfied, except
> with no churn in package install (systemctl enable or preset),
> initialization of a system with empty /etc/, and cleanliness of /etc.

Well, I really think that pushing policy down to the package level is a
real backward step. I mean, it's one of the main principles that the
systemctl preset feature was developed to *avoid* in the first place!
See the first paragraph under "The Logic" on the preset wiki page:

http://freedesktop.org/wiki/Software/systemd/Preset/


But anyway, I think I've made my opinion clear enough, so will let
others comment on your general suggestions.

All the best!

Col


-- 

Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
  Tribalogic Limited http://www.tribalogic.net/
Open Source:
  Mageia Contributor http://www.mageia.org/
  PulseAudio Hacker http://www.pulseaudio.org/
  Trac Hacker http://trac.edgewall.org/


More information about the systemd-devel mailing list