Dear Package Maintainers: Stop Being Clever

Date July 24, 2013

In the Linux world, there are two ways of treating a service/daemon installation.

The Right Waytm (which is what Redhat does) is to install the service but not start it immediately. This only makes sense. The administrator hasn't had time to configure it yet, it may be harmful, etc, etc. You should install the software, make it available, put skeleton config, whatever, but leave it up to the administrator to actually turn on.

The Wrong Way is what Debian / Ubuntu does, where software that's being installed will begin running immediately following the completed installation. This is wrong. It's bad. It was, in my opinion, a dumb design decision.

That being said, it was a design decision made by the distribution. If you are a person who packages software for a distribution that has made certain design decisions,

STOP TRYING TO OUTWIT THE DISTRIBUTION

I don't know how to say it more clearly than that. I have, in my year of experience with Ubuntu, found many pieces of software that find clever ways to not run immediately following installation. Some will put a flag in the initialization script itself, but most will create a file in /etc/default/ matching the service name, and will put a flag in there that, out of the box, prevents the service from running.

The idea behind this is solid. It's clearly a bad idea to run software immediately following installation, but as a software packager, that is not a decision you should be making. If you're bundling Ubuntu software, you need to follow the tao of Ubuntu, even if you don't like it, because things expect software running under Debian-based distros to behave a certain way.

Here's a case in point.

I've been working on puppetizing my installation of Nagios. Nagios itself works fine. This block is really all I need to do once I get my configuration in place:

   package { 'nagios3':
      ensure   => present,
      before   => [
                  File['/etc/nagios3'],
                  Package["pnp4nagios"],
                  ],
   }
   service { "nagios3":
      enable   => true,
      ensure   => "running",
      require  => Package["nagios3"],
   }

That will install nagios3 and make sure that the service is running. The files that are referenced there will update the service when they change because of a "notify" line. But it works just fine, because the person packaging it wasn't trying to be clever.

This, on the other hand, does not work:

   service { "npcd":
      enable   => true,
      ensure   => "running",
      require  => [
                  Package["pnp4nagios"],
                  File["/etc/default/npcd"],
                  ],
   }

As you can see, I've got "enable" set to true, and "ensure running" set, nevertheless the service WILL NOT run. Why? Because of these lines in /etc/init.d/npcd:

     46 # Check if RUN is set to "yes" in /etc/defaults/npcd
     47 if [ "x$RUN" != "xyes" ] ; then
     48         echo "$NAME has been disabled in /etc/default/npcd."
     49         exit 0
     50 fi

Here are the contents of /etc/defaults/npcd out of the box:

# Default settings for the NPCD init script.

# Should NPCD be started? ("yes" to enable)
RUN="no"

# Additional options that are passed to the daemon.
DAEMON_OPTS="-d -f /etc/pnp4nagios/npcd.cfg"

Awesome. You might naively think, like I did, that RUN="no" is standard, but that's not the case. I asked about this problem on ServerFault, and one of the answers found half a dozen ways to signal "please don't start the service".

As someone who has to use the software that you're packaging, I'm asking you to not do this.

Seriously, please stop. You're breaking other things by trying to do the "right" thing.

14 Responses to “Dear Package Maintainers: Stop Being Clever”

  1. Jordan Sissel said:

    I tend to think of Debian/Ubuntu as a system not intended to be configured. Things start "by default, on installation" because you aren't intended to configure anything. Want to configure mysql before launching it? Well, you get the maintainer's desired configuration instead.

    In this way, I think it's sort of an expectations clash. Debian provides a system that doesn't feel intended for configuration or management by humans. The maintainer made decisions and you get what you get.

    I absolutely don't mean this in a negative way - I think this is basically an expectations mismatch problem. I find resetting my expectations to this kind of thing helps me be less angry about things since I spend less time with failed expectations.

    Expectation mismatches are part of what drives me to improve fpm and other 'do your own thing more easily' tools, because it's so often you need a custom kernel, special database configurations, system tuning, different access controls, etc, that we need tools that help operators deploy and maintain systems.

    To be fair, I think RedHat has similar 'wow, this is terribly odd' decisions that shock me; ditto for other platforms and operating systems. Best recommendation is to use whatever is most amenable to your needs, right? Sounds like for your case, Debian and Ubuntu aren't a fit given the constant conflict between you wanting to configure things to your business and Debian's "configured by the maintainer, not for your business" approach.

  2. bob said:

    Actually,

    I wholeheartedly disagree with the premise that if debian is starting unconfigured services that packages should just go along with that.

    I also disagree with the comment that packages on ubuntu are not intended to be configured.
    Thats a pretty insane remark.

    In fact, if I were a package maintainer in the face of this horrible behavior, I would put a do nothing binary in place of the real one and require a configure step on the part of the user.

    These things open ports with default user names and passwords. A sysadmin could easily compromise their system unwittingly.

  3. Yuvi said:

    Redis does this too, and is annoying.

  4. Sam Bashton said:

    RHEL and Debian (and their respective derivatives) have different philosophies on packaging, which is why you see this result.

    The RHEL philosophy is simple; package installation only installs the package, starting daemons is a separate process.

    The Debian philosophy is that installing a daemon should also make that daemon run, unless it's not possible the make the daemon run securely by default. Things like the /etc/default RUN="no" aren't the package maintainer trying to be clever, but rather them following Debian packaging guidelines. There also the reason you see things like MySQL listening only on the loopback interface by default on Debian.

    One you understand this the decisions seem a bit less crazy.

    For me, the big issue with the Debian approach isn't on installation, but rather on upgrade. On Debian, running 'apt-get upgrade' on a live server can cause an unspecified amount of downtime. If you're upgrading MySQL, MySQL will get restarted. If you're upgrading a library on which multiple daemons rely, they will also get restarted. yum upgrade on RHEL doesn't suffer from the same problem, and you can schedule the restart yourself.

    Again, this is because of a philosophical difference. On Debian, the idea is that if you've asked to upgrade something, it should be upgraded. On RHEL, you can upgrade a package, but continue to run the old (potentially insecure version).

  5. Vidar Hokstad said:

    Debian (and by extension Ubuntu) has an extensive mechanism for configuration before/during installation: Most packages will ask questions. And if you want to automate it, you do that by feeding the config settings to "debconf-set-selections". If you set up a test system first, you can obtain all those settings via "debconf-get-selections" from the debconf-utils package. Settings configured this way can also later be modified via dpkg-reconfigure [package name].

    As such, a Debian and Ubuntu user would generally expect that the software installed is in a reasonable state when installation is finished. If he/she is not asked questions during installation, it better be because it is not strictly necessary, and the package *better* have set up sane defaults that does not cause security issues. E.g. a mail server or database server setup with no user input would most likely be expected to bind to localhost only as mentioned above.

    Making the service not run is laziness. It means the packager could not be bothered to add, e.g. a step to configure a password during installation using the standard Debian tools.

    But I strongly agree with the post: Don't invent ways to disable the service or other wise deliver something non-standard. If a package maintainer is too lazy to do it the Debian way and providing support for debconf driven configuration, then said package manager should pick sane and safe defaults.

  6. Grzegorz Nosek said:

    There's a policy-rc.d script you can use to prevent all well-behaved packages from starting/stopping itself during dpkg operations:

    policy-rc.d spec

  7. Daniel BArlow said:

    I agree with the article. If the user doesn't want services on his machine to be started when packages are installed, he can use policy-rc.d to ensure that this is the case (see http://people.debian.org/~hmh/invokerc.d-policyrc.d-specification.txt). If package maintainers feel that this should be the default policy - and personally I'd agree - they should lobby or vote or flame each other[*] until it's changed, not introduce ad hoc solutions in their own packages which are more work for the sysadmin to override. I don't want to have to teach puppet how to edit /etc/default/foo files with sed

    [*] I've never been quite sure how decisions are made in debian but it appears to be some combination of these three actions

  8. Brian Parsons said:

    @Jordan - MySQL is exactly the situation I ran into. One configuration does not fit all, and when you adjust INNODb you have to blow away what's there. Having it start, initialize it's config and then me have to stop and redo everything is not helpful at all.

    I chalked this up to Ubuntu being first and foremost a desktop distro oriented at users instead of a server distro. The other problem is that they also try to outsmart mysql by running mysql directly through upstart instead of using mysql's mysql-safe daemon.

    @Daniel - thanks for the tip on policy-rc.d - that may be the answer here!

  9. non7top said:

    The reason I stopped using debian as a server platform. RHEL derivations are much more predictable and reliable in regards to the subject. I just don't get the logic of all those RUN="no" crazy things.

  10. Ryan Tandy said:

    First, I agree completely with your point that packages should follow the distribution conventions. The topic of start-flags in /etc/default/$pkg is a recurring one on debian-devel. I think some developers are planning to push harder on this for jessie (possibly even release-goal it).

    Second, in the theoretical debconf utopia, starting services on installation does make sense, because they have already been configured via debconf. You know as well as I do that it doesn't actually work that way in real life, so we end up with this common case of preseeding just enough configuration to get it installed and doing the rest with a more powerful management system.

    The introduction to http://wiki.debian.org/debconf describes the theoretical debconf utopia very well.

  11. Jordan Sissel said:

    Also, for you debian users out there, here's a fun hack!

    A while back I experimented with hooking apt to strip a package of it's "maintainer scripts" so nothing is started/etc on package installation.

    Details here: https://gist.github.com/jordansissel/748313

    The effects were mixed. Sometimes it was great, other times it was not. Debian does a crapton of mysterious and sometimes-fragile things upon package installation as a way to compensate for dpkg being basically a versioned tarball. RPM does the same, with pre/post install/uninstall scripts.

    If you try this hack above (stripdeb.sh hook in apt), be aware that it basically renders python packages inert; On debian, python package installs have this "pycentral" thing i see nowhere else that requires a post-install step for every debian python package.

  12. gpapilion said:

    I wrote a policy.d implementation due to this. https://github.com/gpapilion/policy-rc.d

  13. dub said:

    The "Right Way" vs "Wrong Way" is you opinion:

    cite: "It was, in my opinion, a dumb design decision."

  14. D.F. said:

    I remember that I made a comment about this on your blog awhile back. I really wish that I could find the source for that comment, but it really does describe the attitude of the debian distribution at the time it was made.
    This would be a great thing for the debian maintainers to revist, but there's a good chance that given the sometimes glacial pace of change in debian that it will remain that way since its the way its always been done. That sounds harsh, but I didn't mean it as a slight. Debian is a huge project, with thousands of packages and multiple layers of bureaucracy and several competing philosophies.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*