Autostart on macOS

:warning: This guide has been migrated from our website and might be outdated. Feel free to edit this guide to update it, and to remove this message after that.

Setting up Home Assistant to run as a background service is simple; macOS will start Home Assistant after the system has booted, the user has logged in, and make sure it’s always running.

To get Home Assistant installed as a background service, run:

$ hass --script macos install

Home Assistant has been installed.         Open it here: http://localhost:8123

Home Assistant will log to ~/Library/Logs/homeassistant.log

Configuration is kept in ~/.homeassistant

To uninstall the service, run:

$ hass --script macos uninstall

Home Assistant has been uninstalled.

Note:
automake is required for hass to start. If you are missing this on your system, you can install this by running:

brew install autoconf

The above may work under certain circumstances, but in my installation on a Mac running Catalina and HA in a VENV, it didn’t (and I’ve seen the same from others in the forums). The updated way to automate jobs on Mac is using launchd; see more at this link (but I will replicate the important parts herein):

In order to use launchd you create a .plist file in the appropriate folder and the system will see it and run the payload, in this case at system startup. If you’ve set things up the way I did with your user as the HA user, you would put the .plist file in /Users/YOURUSERNAME/Library/LaunchAgents; otherwise use the appropriate path for your HA user. That’s it- create the file as below and make sure to proof the paths.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>AbandonProcessGroup</key>
	<false/>
	<key>EnvironmentVariables</key>
	<dict>
		<key>LC_CTYPE</key>
		<string>UTF-8</string>
		<key>PATH</key>
		<string>/usr/local/bin/:/usr/bin:/usr/sbin:/sbin:$PATH</string>
	</dict>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<false/>
	</dict>
	<key>Label</key>
	<string>org.homeassistant</string>
	<key>Program</key>
	<string>/Users/YOURUSERNAME/homeassistant/bin/hass</string>
	<key>RunAtLoad</key>
	<true/>
	<key>StandardErrorPath</key>
	<string>/Users/YOURUSERNAME/.homeassistant/home-assistant.log</string>
	<key>StandardOutPath</key>
	<string>/Users/YOURUSERNAME/.homeassistant/home-assistant.log</string>
</dict>
</plist>

Just to clarify.

How does /Users/YOURUSERNAME/homeassistant/bin/hass run inside venv?

Don’t you have to specify the venv and user first?

source ~/Documents/homeassistant/bin/activate
~/Documents/homeassistant/bin/hass

In my case ~/homeassistant is the VENV.; by calling it that way you’re activating it. This is a .plist not a script. I could be wrong… not a guru, just a guy that experimented a lot

But if I manually do it, it shows the actual user. Don’t you think, you just run homeassistant from your main system instead of venv?

What does this do then:
source ~/Documents/homeassistant/bin/activate

I had to go to Google on this one but I think this answers our question…. Sourcing the activation file (which is just a scipt) just ensures that the PATH is correct. I guess you need to activate it to work with the VENV from the command line but apparently you can run the VENV without that step. Done so through a .plist as above presumably obviates issues with loading the wrong python binary because we’ve specified the entire path. If anyone feels otherwise please correct me.

Note that, as I said above, the HA user will be the username in the path of the .../library/launchagents from which the .plist loads. You could create a non-admin user just for HA but then it would have to be logged in every time the server restarts. You don’t want to put it in /library/launchagents because then it would load as root.

Thanks.

Could that be a problem, though:

when you enter python or pip or other script without any path into the terminal, the shell will find a different Python binary to run.

Yeah they’re not talking about running a VENV there though.
Edit: they’re not specifying a path to the VENV of interest
It’s been working beautifully for me this way. I think the only criticism is that an admin user is running my HA.

Well it will work as long as the dependencies on your system are met. These can change if you install something else. This is avoided by using venv and the big advantage.

You are NOT running inside the venv.

I do the same at the moment, primarily, because I can’t get launchd working with venv…

For me only this loads properly at startup:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>Label</key>
		<string>org.homeassistant</string>
		<key>Program</key>
    		<string>/Users/server/Documents/homeassistant/bin/hass</string>
		<key>RunAtLoad</key>
		<true/>
		<key>KeepAlive</key>
		<true/>
	</dict>
</plist>

If i link a shell file like this or an executable, it doesn’t work.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>Label</key>
		<string>org.homeassistant</string>
		<key>Program</key>
    		<string>/Users/server/runha</string>
		<key>RunAtLoad</key>
		<true/>
		<key>KeepAlive</key>
		<true/>
	</dict>
</plist>

runha (executable) contains:
cd ~/Documents source home-assistant/bin/activate; homeassistant/bin/hass

I guess this is not possible to do, because the service needs to monitor an application, which this isn’t.

Maybe someone can help with this.

That’s interesting and makes complete sense. Will cron run a script? It’s deprecated but still functional.

On the other hand, I just read a whole article about running scripts as launch agents/daemons. Maybe this would work?
<string>/Users/server/runha.sh</string>

You might also want to specify the entire path in your bash script.

If you cat homeassistant/bin/hass it’s just an 8-line python script.

I tried it already, but didn‘t work.

Not sure about cron.

I think the agent has to monitor a process, like homeassistant. It can‘t monitor runha.

@davinci Check your permissions- I just got it to work like below. The script has permissions 711. Now if we can figure out how to use sudo -u or su to specify a non-admin user then it’s all worked out.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>AbandonProcessGroup</key>
	<false/>
	<key>EnvironmentVariables</key>
	<dict>
		<key>LC_CTYPE</key>
		<string>UTF-8</string>
		<key>PATH</key>
		<string>/usr/local/bin/:/usr/bin:/usr/sbin:/sbin:$PATH</string>
	</dict>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<false/>
	</dict>
	<key>Label</key>
	<string>org.homeassistant</string>
	<key>Program</key>
	<string>/Users/username/.homeassistant/scripts/ha_agent.sh</string>
	<key>RunAtLoad</key>
	<true/>
	<key>StandardErrorPath</key>
	<string>/Users/username/.homeassistant/ha_agent.log</string>
	<key>StandardOutPath</key>
	<string>/Users/username/.homeassistant/ha_agent.log</string>
</dict>
</plist>

and ha_agent.sh is:

#!/bin/bash

source /Users/username/homeassistant/bin/activate ;
/Users/username/homeassistant/bin/hass

Thank you so much. It finally works. I also restarts properly.

I can’t help you with sudo, but I am curious as of why you need it?

Ideally HA runs as a non-admin user because it’s the safest thing if it gets hacked (it is the entity exposed to the web via the port forward after all). But… I don’t want to have to log in multiple users every time I restart the server. So, I think what we could do is actually put the .plist in library/launchagents which would be run by root at any startup of the system, but use something in the script like:
sudo -u homeassistant "/Users/username/homeassistant/bin/activate && /Users/username/homeassistant/bin/hass"
If we get it right then everything in the shell runs as the homeassistant user, not root (sudo means substitute user do, NOT superuser do). If we blow it then HA runs as root which is even worse than an admin user.