Disable service by default

Hey there!

How can I prevent snapd from automatically starting every daemon of my snap on installation?

I’m currently working on a snap, which requires the user to connect some non-auto-connecting interfaces first before the snap’s daemons can start. Without these interfaces, the daemons fail to start.

I tried adding a hook, which would disable all services using snapctl stop --disable mysnap.daemon, as mentioned in Using snapctl in install hook to disable services, in a similar fashion as https://github.com/anonymouse64/service-test. However, this does not seem to work. Is there another option?

What does your hook look like? this should work, all relevant code has landed in snapd for a while now to enable this to work.

1 Like

You are right. Using a hook to disable autostart seems to work. At least in some cases, I figure.

When using daemon: forking the installer, however, still tries to run the specified command.

Let’s say your snapcraft.yaml contains the following service declaration:

apps:
  myservice:
    daemon: forking
    command: bash $SNAP/test.sh

The test.sh always exits with exit code 1 (only for demonstration purposes):

#!/bin/bash
sleep 60 &
exit 1

And the hook in snap/hooks/configure tries to disable the service:

#!/bin/bash -e
snapctl stop --disable mysnap.myservice

Then, the installation of the snap will fail, because snapd still tries to start the daemon during installation:

error: cannot perform the following tasks:

  • Start snap “mysnap” (unset) services ([start snap.mysnap.myservice.service] failed with exit status 1: Job for snap.mysnap.myservice.service failed because the control process exited with error code.
    See “systemctl status snap.mysnap.myservice.service” and “journalctl -xe” for details.
    )

However, if the specified command exits with exit code 0, and the forked process exits with exit code 1, the installation does succeed.
Another version of test.sh:

#!/bin/bash
exit 1 &
exit 0

When using daemon: simple and a command that exits with exit code 1, the installation is also successful.

Is this behavior expected?

This I think is part of the issue, the order of things during snap installation is always:

  1. run the install hook
  2. start all non-disabled daemons
  3. run the configure hook

So if you are trying to disable services in your configure hook, you’re too late as they would already have been started in 2.

The reason for this is from systemd, in that systemd considers a “simple” daemon to be done “starting” immediately after systemd starts the process, regardless of what happens, but for “forking” daemons, systemd waits for the daemon to actually fork a child process then waits for the parent process (i.e. the one that systemd forked initially) to exit with non-zero code. This also explains your point:

So yes all this behavior is expected. I do think we could probably do a better job at documenting how to order daemons with an example and perhaps some other examples of how the different daemon types are used and what systemd expects of them. @degville do you think that would be useful and/or do you already have something like that queued up?

1 Like

We should definitely cover this because it’s both a good insight into how snapd is working with systemd, and a help for snap devs managing services. I’m obviously more than happy to do this - have you got a good example we could use @ijohnson?

I have several fake service examples that don’t really do anything, but the best example I have IRL is the edgexfoundry snap which is quite complicated and I don’t think we really want to get into all the gory details there… Let me look through my tests/examples and I’ll get back to you with what could be used for such a doc.

1 Like

All right, now I get it. Thanks!
I used the configure hook because I wanted to run the script when installing the snap for the first time and when refreshing. I now understand that the right way to do this is by using the install and post-refresh hooks, not the configure hook. This is for a private snap of mine. I know that in a regular snap, disabling services on each refresh does not sound like a good idea.

@degville I think adding some information about how to disable autostart for services to the Services and daemons documentation page would also be helpful.
The page could also mention that services always run as root. I’ve read this on a different page but repeating it couldn’t hurt.