Hacker News new | ask | show | jobs
by jcrites 3447 days ago
I think systemd needs to do most of the things it does. Russ Allbery's analysis of systemd [1], written as part of Debian's evaluation of whether to switch to systemd, explains the benefits. Journal integration is something that Russ was also skeptical about, until he realized its value:

  * Integrated daemon status.  This one caught me by surprise, since the
    systemd journal was functionality that I expected to dislike.  But I was
    surprised at how well-implemented it is, and systemctl status blew me
    away.  I think any systems administrator who has tried to debug a
    running service will be immediately struck by the differences between
    upstart:
  
    lbcd start/running, process 32294
  
    and systemd:
  
      lbcd.service - responder for load balancing
       Loaded: loaded (/lib/systemd/system/lbcd.service; enabled)
       Active: active (running) since Sun 2013-12-29 13:01:24 PST; 1h 11min ago
         Docs: man:lbcd(8)
               http://www.eyrie.org/~eagle/software/lbcd/
     Main PID: 25290 (lbcd)
       CGroup: name=systemd:/system/lbcd.service
               └─25290 /usr/sbin/lbcd -f -l
  
    Dec 29 13:01:24 wanderer systemd[1]: Starting responder for load balancing...
    Dec 29 13:01:24 wanderer systemd[1]: Started responder for load balancing.
    Dec 29 13:01:24 wanderer lbcd[25290]: ready to accept requests
    Dec 29 13:01:43 wanderer lbcd[25290]: request from ::1 (version 3)
  
    Both are clearly superior to sysvinit, which bails on the problem
    entirely and forces reimplementation in every init script, but the
    systemd approach takes this to another level.  And this is not an easy
    change for upstart.  While some more data could be added, like the
    command line taken from ps, the most useful addition in systemd is the
    log summary.  And that relies on the journal, which is a fundamental
    design decision of systemd.
  
    And yes, all of those log messages are also in the syslog files where
    one would expect to find them.  And systemd can also capture standard
    output and standard error from daemons and drop that in the journal and
    from there into syslog, which makes it much easier to uncover daemon
    startup problems that resulted in complaints to standard error instead
    of syslog.  This cannot even be easily replaced with something that
    might parse the syslog files, even given output forwarding to syslog
    (something upstart currently doesn't have), since the journal will
    continue to work properly even if all syslog messages are forwarded off
    the host, stored in some other format, or stored in some other file.
    systemd is agnostic to the underlying syslog implementation.
I wrote another comment recently [2] to explain why I value systemd's approach and appreciate its declarative style. I can launch my service at the appropriate time during boot with configuration as simple as:

  [Unit]
  Description=Demo service

  [Service]
  Type=forking
  ExecStart=/usr/sbin/my-daemon
Now let's say that I didn't author this daemon, but I'd like to run it with a private network, private temp folder, or a private /dev namespace. Or perhaps the daemon needs to run as root, but I want to drop all capabilities it doesn't need. It's as simple as adding these lines to the service's configuration:

  PrivateTmp=yes
  PrivateDevices=yes
  PrivateNetwork=yes
  CapabilityBoundingSet=CAP_NET_BIND_SERVICE
The fact that systemd supports these configuration options means that there's a simple and standard way to employ them with any service. The service itself doesn't need to support them, and needn't complicate its own daemonization logic to do so correctly. Indeed, I don't need to trust the service to daemonize or drop capabilities, since I can tell the init system do that before launching the service.

I can drop capabilities with CapabilityBoundingSet=, or limit resource usage with CPUSchedulingPriority=, IOSchedulingPriority=, etc. I could even tell systemd to open the listening socket for me so the service doesn't need CAP_NET_BIND_SERVICE! Moving these options into the init system makes a ton of sense, because it gives administrators the ability to employ these features from outside applications, not just by enabling them within applications that bother to explicitly support them via command line arguments. Systemd better encourages the principle of least privilege: if a system daemon does not need the ability to "ptrace" other processes, or bind to ports <1024, then as the administrator I can take those away with CapabilityBoundingSet= in the unit file. Chrooting the service is as easy as RootDirectory=. This is a huge step forward compared to the world where every service must be relied upon to expose these settings, and must be trusted to implement them correctly.

[1] https://lists.debian.org/debian-ctte/2013/12/msg00234.html

[2] https://news.ycombinator.com/item?id=13359519

4 comments

I thought that was the part of systemd that was universally liked? The best arguments against systemd seem to be that everything becomes implemented in or tightly bound to it.
This is also the rationale behind uselessd, which keeps the service management part and cuts out everything else.
Pid 1 runs its own DNS server now. It also launders kernel calls for non-setuid xorg (breaking rootless x on non-systemd boxes, since the kernel can't be bothered to consistently check process uid or gids, apparently). In turn, that means it must have some baroque authentication subsystem too. There is no way you need that in init. The amount of ancillary damage systemd causes far outweighs any possible benefits there are to improving init.

Also, I have never seen a systemd box emit log lines like that for a failed service. It invariably points at some useless logfile with obscure systemd messages in it instead of the stderr of the failed process. This is on clean ubuntu and debian installs. Maybe it is user error, but I doubt it. (Though there is no command line in the examples...)

Anyway, I'm happy to cleanse with fire instead of RTFM at this point. On a related note, I just learned the solaris init system and started using openbsd's again.

I prefer them both to systemd. They are at opposite ends of a spectrum. The openbsd approach is well curated shell scripts. I think systemd was heavily inspired by the solaris thing.

> Pid 1 runs its own DNS server now.

It doesn't. Systemd has its own resolver (systemd-resolved), which has other issues, but it does not run in PID 1. It's a completely separate process.

// I'm enjoying watching the points bouncing up and down, but if you disagree in some way, please comment :)

> PrivateTmp=yes > PrivateUsers=yes > PrivateNetwork=yes >The fact that systemd supports these configuration options means that there's a simple and standard way to employ them with any service.

What exactly does 'PrivateUsers' do? What uid do I have? When I write that uidin a db, what value does it keep? Between invocations, does the uid change or is it per unit? If a file is owned by a private uid, what do other processes on the system see? Is PrivateUsers for this unit file only, for the unit files in this group of unit files, across the entire system, across the entire cluster? If I want two different programs to share this PrivateUsers concept, how do I do that?

It turns out that gluing random shit to the side of a monolith gives you the illusion of convenience, but since the monolith will not do that thing well -- for example, identity management -- you will end up with some programs that adopt the half-assed solution, and some programs that are forced to do things a different way because their use case is complex. Now you have two problems.

PrivateUsers= is documented in the manual page for systemd.exec [1]. I hope the section I linked will answer your question, but for the sake of simplicity I edited my comment to use PrivateDevices= as the example instead.

https://www.freedesktop.org/software/systemd/man/systemd.exe...

You missed the point completely, I'm afraid. The point was that it's a leaky abstraction composed of half implemented concepts that devs have to add to their brain. It does not replace the existing functionality or improve it.
Respectfully, actually, I think you missed the point. Linux itself offers a number of powerful features such as namespaces to isolate programs, capabilities that can be dropped, etc., including the User Namespace feature we're discussing presently [1].

Systemd's job and goal is to provide a simple configuration file format that makes it easy to enable these features with installed system daemons.

You may overlooking the parameters supported by systemd and their benefits. Admins get a single way to manage their services and dependencies, and a way to do that that works consistently across all services. These features can be enabled even if the services were not designed for it (e.g., chroot). With systemd you can employ these settings from the outside with any service, and that's a big advance. Difficult to achieve otherwise.

> The point was that it's a leaky abstraction composed of half implemented concepts

I am unclear what part you want to criticize. The Linux kernel is what provides the User Namespace feature. Systemd helps users take advantage of it. What part do you consider half-implemented or a leaky abstraction?

Please also consider whether you might have the wrong mental model for the feature or its employment. In particular, the documentation for PrivateUsers= says: "This is useful to securely detach the user and group databases used by the unit from the rest of the system, and thus to create an effective sandbox environment." The usage you had in mind when you wrote your comment may not be compatible with the purpose of PrivateUsers. I recommend reading up systemd.exec params [1] before criticism. PrivateUsers= is intended for scenarios like transient sandboxed environments, so I'd suggest we discuss a simpler example like PrivateDevices=

[1] http://man7.org/linux/man-pages/man7/user_namespaces.7.html

With all due respect, I'm afraid you're addressing a series of unrelated points and indulging, hopefully unintentionally, in a rhetorical smokescreen, which includes editing your original post to hide an important topic.

I'm aware of what systemd claims to be. I'm aware of the benefits that its fans claim it, and it alone has.

My criticism is not with the Linux kernel (!?!) or user namespacing as a concept. My criticism is that systemd takes all of the rich complexity of user namespacing and, in response, adds the flag 'PrivateUsers=yes' -- a boolean. That's not what user namespacing is for and now we have two problems: systemd, which has no business making that decision and has done it the wrong way, and the continuing need, which has not been solved by a boolean flag, for daemons to have competent, complex user namespaces. Now devs have to know both ways: the half-assed way, and the real way, instead of just having a tool that gives them the real way.

That's what we in the software design business call a shitty design that would make Guy Fieri blush. But I guess we're all in Flavortown now.

>The point was that it's a leaky abstraction composed of half implemented concepts that devs have to add to their brain.

As opposed to a multitude of implementations of varying quality and functionality for the same concept in each init script that needs it?.

You've copied and pasted that text multiple times on this page alone. Once, or at the very least once per Hacker News page, is surely enough.