How to correctly deploy bundled launchdaemons/launchagents?

I'm working on an enterprise product that's mainly a daemon (with Endpoint Security) without any GUI component. I'm looking into the update process for daemons/agents that was introduced with Ventura (Link), but I have to say that the entire process is just deeply unfun. Really can't stress this enough how unfun. Anyway...

The product bundle now contains a dedicated Swift executable that calls SMAppService.register for both the daemon and agent. It registers the app in the system preferences login items menu, but I also get an error.

Error registering daemon: Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}

What could be the reason?

I wouldn't need to activate the items, I just need them to be added to the list, so that I can control them via launchctl.

Which leads me to my next question, how can I control bundled daemons/agents via launchctl? I tried to use launchctl enable and bootstrap, just like I do with daemons under /Library/LaunchDaemons, but all I get is

sudo launchctl enable system/com.identifier.daemon
sudo launchctl bootstrap /Path/to/daemon/launchdplist/inside/bundle/Library/LaunchDaemons/com.blub.plist

Bootstrap failed: 5: Input/output error (not super helpful error message)

I'm really frustrated by the complexity of this process and all of its pitfalls.

Answered by DTS Engineer in 809211022

Lemme take a step back here. ES products typically ship in one of two ways:

  • If they’re consumer focused, they use an ES system extension.

  • If they’re enterprise focused, they use an ES daemon.

It sounds like you fall into the latter category. If so, why are you adopting SMAppService? That mechanism is intended for folks shipping consumer focused products. For an ES client that’s targeting enterprise environments it makes sense to stick with an installer package.

In short, SMAppService is meant to be a replacement for things like SMJobBless and SMLoginItemSetEnabled, not a replacement for installer packages and launchctl.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

Lemme take a step back here. ES products typically ship in one of two ways:

  • If they’re consumer focused, they use an ES system extension.

  • If they’re enterprise focused, they use an ES daemon.

It sounds like you fall into the latter category. If so, why are you adopting SMAppService? That mechanism is intended for folks shipping consumer focused products. For an ES client that’s targeting enterprise environments it makes sense to stick with an installer package.

In short, SMAppService is meant to be a replacement for things like SMJobBless and SMLoginItemSetEnabled, not a replacement for installer packages and launchctl.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for your help Quinn, as always. Yes, we definitively fall under the second category.

We were under the impression that daemons and agents must live under /Library/LaunchDaemons starting with Ventura and that this will become mandatory some time in the future. The documentation said: In apps that target macOS 13 and later, your app needs to only use the property list locations outlined above.

If we can continue to put our launchd plists under /Library/Launch... and ignore SMAppService that would be great. I was following the provided example Xcode project in which an installer package is created and then calls the SMAppService part during the postinstall. I just assumed that "this is the way", even if it is very painful.

I can see how you might get that impression but…

My take on this is that /Library/Launch{Daemons,Agents} is critical to many folks, not just developers but also sysadmins. If we were to deprecate it, we’d have to be very clear about that.

Sometimes it pays to read between the lines and proactively adopt new technologies. Sometimes it pays to sit back, relax, and see how things pan out. The tricky is telling those cases apart O-:

Oh, one last thing: If you do stick with launchd property lists, make sure you set AssociatedBundleIdentifiers. That way the system can tie your launchd job to something user visible.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How to correctly deploy bundled launchdaemons/launchagents?
 
 
Q