major.io

Words of wisdom from a Linux engineer focused on information security

major.io

Words of wisdom from a systems engineer

  • Who am I?
  • icanhazip FAQ
  • Résumé
  • Keybase
  • RSS
Creative Commons License

Preventing Ubuntu 16.04 from starting daemons when a package is installed

May 5, 2016 By Major Hayden 12 Comments

I’ve gone on some mini-rants in other posts about starting daemons immediately after they’re installed in Ubuntu and Debian. Things are a little different in Ubuntu 16.04 and I thought it might be helpful to share some tips for that release.

Before we do that, let’s go over something. I still don’t understand why this is a common practice within Ubuntu and Debian.

Take a look at the postinst-systemd-start script within the init-systems-helpers package (source link):

Shell
1
2
3
4
if [ -d /run/systemd/system ]; then
    systemctl --system daemon-reload >/dev/null || true
    deb-systemd-invoke start #UNITFILES# >/dev/null || true
fi

The daemon-reload is totally reasonable. We must tell systemd that we just deployed a new unit file or it won’t know we did it. However, the next line makes no sense. Why would you immediately force the daemon to start (or restart)? The deb-systemd-invoke script does check to see if the unit is disabled before taking action on it, which is definitely a good thing. However, this automatic management of running daemons shouldn’t be handled by a package manager.

If you don’t want your package manager handling your daemons, you have a few options:

The policy-rc.d method

This method involves creating a script called /usr/sbin/policy-rc.d with a special exit code:

Shell
1
2
3
4
5
# echo -e '#!/bin/bash\nexit 101' > /usr/sbin/policy-rc.d
# chmod +x /usr/sbin/policy-rc.d
# /usr/sbin/policy-rc.d
# echo $?
101

This script is checked by the deb-systemd-invoke script in the init-systems-helpers package (source link). As long as this script is in place, dpkg triggers won’t cause daemons to start, stop, or restart.

You can start your daemon at any time with systemctl start service_name whenever you’re ready.

The systemd mask method

If you need to prevent a single package from starting after installation, you can use systemd’s mask feature for that. When you run systemctl mask nginx, it will symlink /etc/systemd/system/nginx.service to /dev/null. When systemd sees that, it won’t start the daemon.

However, since the package isn’t installed yet, we can just mask it with a symlink:

Shell
1
# ln -s /dev/null /etc/systemd/system/nginx.service

You can install nginx now, configure it to meet your requirements, and start the service. Just run:

Shell
1
2
# systemctl enable nginx
# systemctl start nginx

Share this post:

  • Twitter
  • Google
  • LinkedIn
  • Reddit
  • Email
  • Print

Tagged With: security, systemd, ubuntu

Comments

  1. JoeJulian says

    May 5, 2016 at 10:06 am

    If you *do* for some reason want deb-systemd-invoke to start or restart a specific service, test $1 against the systemd unit name. “exit 104” for services you do want deb-systemd-invoke to manage.

    #!/bin/bash
    [[ “$1” = “salt-minion.service ]] && exit 104
    exit 101

    Reply
  2. Soren Hansen says

    May 6, 2016 at 10:20 am

    I never really understood why this is a problem for people… If you install nginx it doesn’t seem like an unreasonable assumption that you want it to run. Does it?

    Reply
    • Major Hayden says

      May 6, 2016 at 11:52 am

      I’d definitely like it to run — but only after I’ve configured it, put my web content in place, etc. Otherwise I’ll need to do all of that configuration and restart it. The initial startup provides no value for me.

      Reply
      • Soren Hansen says

        May 6, 2016 at 4:52 pm

        We’re talking about the difference between:

        Starts after installation with a usable, default config -> I make some changes -> I restart it

        and:

        Doesn’t start after installation -> I make changes to the config -> I start it

        I must be missing something, because I can’t see how you’d get worked up over that enough to dedicate multiple blog posts to it.

        Reply
        • Serge van Ginderachter says

          May 8, 2016 at 3:22 am

          Because, for example, sometimes the “make changes/config” part is important enough it should happen before the daemon ever starts.

          Reply
        • Jennifer says

          June 1, 2017 at 12:50 am

          Generally if you are setting up 1 instance it might not be a big deal to install, start, configure, restart. If you are trying to support multiple instances behind a load balancer for example of a particular service you need to ensure that the system is completely good to go before you start it up.

          Reply
  3. JCC says

    May 9, 2016 at 12:17 pm

    Honestly, I never understood how Debian (and Ubuntu) could get the initscript and startup config process so wrong like this for so long. It’s been standard for pretty much forever on the Red Hat / RPM side to NOT start up a service on install for explicitly this reason (the details still survive in EPEL: https://fedoraproject.org/wiki/EPEL:SysVInitScript#Why_don.27t_we…. ).

    This was one of the many, many beefs sysadmins had with systemd; service management and the init process should be distinct to allow for more control at install time.

    Reply
  4. tim says

    June 30, 2016 at 11:05 am

    Switching back and forth between RedHat family and Debian family this has been one of my major annoyances.

    I tried giving the first alternative a shot, but because both stop and start might be issued by a dpkg trigger when also uninstalling packages (e.g. mysql-server) it quickly became more of a nuisance than of any help. Had a quick look at the source code and didn’t seem to be possibly to only prevent autostart when installing packages, but would you happen to know of any other solution?

    Systemd mask however works fine, but it’s a bit of a hassle to incorporate into all my Ansible roles (not to mention third party ones!).

    Reply
  5. Nathan Grennan says

    August 5, 2016 at 3:11 pm

    Thank you for this post. This have been driving me nuts with configuration management tools. Sometimes the tool will hang, because it can’t stop the package started service after I have rewritten the configuration file and tried to restart the service.

    Reply
  6. MRG says

    September 20, 2017 at 1:32 pm

    I found this way:
    Just add runlevel, i.e.
    sudo RUNLEVEL=1 apt-get install iptables-persistent

    Reply
  7. Keerthi says

    October 25, 2017 at 2:38 pm

    Thank you! This was very helpful.

    Reply
  8. Nagendra Maynattamai says

    November 20, 2017 at 9:52 am

    Was much helpful. Thanks for sharing!
    IMHO apt-get should take an arg to perform this action.

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

loading Cancel
Post was not sent - check your email addresses!
Email check failed, please try again
Sorry, your blog cannot share posts by email.