Disable service by default (with ability to enable using app)

Hi,

I’ve created a snap which consist of an app and its service. However, right after snap install, service will start automatically which is not the behavior I want.

What I’m trying to achieve is:

  • service to be disabled by default after snap install
  • have ability to enable/start service by setting environment variables within the app

I managed to stop daemon after install by using environment variable which is later interpreted as part of the app.

But part where I fail is when I try to set value of this env. variable within the app. After this if I go into shell within the snap, I still see that “echo $DAEMON” is equal to “DISABLED” and with this daemon will fail to start.

I tried few things without much success. Does anyone have any suggestion how I could change env. variable within snap environment “on fly” and with it start/stop app related service?

Thanks

1 Like

You can disable the service with an install hook that runs snapctl stop --disable <snap-name>.<service-name>. Then your app can inspect the environment variable and if it’s what you expect, enable the service again with snapctl start --enable <snap-name>.<service-name>.

Another approach we’ve been using is to have a simple shell wrapper around the service that ensures all of its prerequisites are set up, and either exit (possibly with an error code) or exec $daemon "$@" otherwise.

Out of curiosity, what’s the reason behind doing it this way and not using snapctl?

I tried using snapctl before but without much success. Namely, when I run:

snapctl services auto-cpufreq I get:

Service                            Startup  Current  Notes
auto-cpufreq.service  enabled  active   -

But when I run I try to stop it doesn’t seem to work:

ahodzic@carbon7:$ snapctl stop auto-cpufreq.service
error: cannot use "stop" with uid 1000, try with sudo
ahodzic@carbon7:$ sudo snapctl stop auto-cpufreq.service
error: error running snapctl: cannot stop without a context
ahodzic@carbon7:$ snapctl stop --disable auto-cpufreq.service
error: error running snapctl: unknown flag `disable'
ahodzic@carbon7:$ sudo snapctl stop --disable auto-cpufreq.service
error: error running snapctl: cannot stop without a context

I also referred to official documentation but to no avail, any idea what could be the problem here?

ideally I would like to not have a bash wrapper around my Python app. But, considering snapctl is failing for me at this point, if you have an example of what you’re suggesting I’d be willing to give it a try.

snapctl needs to run as root IIRC

Also, snapctl only works from inside a snap, try `snap run --shell -c “snapctl stop auto-cpufreq.service” from outside a snap.

This appears to be a bug where the disable flag is not recognized when there’s not a context.

This is the same as above, snapctl needs to be run from inside a snap (where an env variable is defined so that snapctl can get it’s context.

Right, what I pasted was output of running all those commands inside a snap. I also tried same by being root user (instead of sudo) and ended up with same errors …

How were you running inside the snap? sudo should not work inside a snap, which is why I’m not sure if you were running inside a snap. For example, I would run something inside a snap like this:

$ snap run --shell docker
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

$ snapctl services
Service         Startup   Current   Notes
docker.dockerd  disabled  inactive  -
$ snapctl start --enable docker
error: error running snapctl: unknown flag `enable'
$ sudo snapctl start --enable docker
bash: /usr/bin/sudo: Permission denied
$ exit
$ sudo snap run --shell docker
# snapctl start --enable docker
# snapctl services
Service         Startup  Current  Notes
docker.dockerd  enabled  active   -

I do realize that it is misleading when we do snap run --shell as an unpriviledged user it says “use sudo …” when that in fact will never work from inside a strictly confined snap.

Also, to clarify, are you running these commands from inside a strictly confined snap or a classic snap?

1 Like

Thank you for your clarification, this did the trick:

sudo snap run --shell auto-cpufreq

After which I’m able to run:

snapctl stop --disable auto-cpufreq

Since I’m still in development I’m using devmode as confinement, but even after I’m done I’m planning to use classic.

Now I just need to figure out how I’m going to make this call as part of my Python app, if you have any suggestions for that as well please let me know.

Regardless, thank you for your assistance, much appreciated!

1 Like

I’ll defer to others on this forum, my python is quite rusty

No worries, I’ll figure it out, this is a major lead in right direction. Again, thanks!

Just another approach, I feel like if there’s a prerequisite of a service that isn’t met, the service itself should react to that. With snapctl you need an external thing (like the configure hook) to manage the service. But what if the user disables the service manually and then the configure hook runs - the service is enabled again.