= macOS Service (launchd) This option installs OliveTin as a launchd service, so it runs in the background and starts automatically. This is the macOS equivalent of running OliveTin as a Linux systemd service or a xref:install/windows_service.adoc[Windows service]. If you just want to run OliveTin as a regular application, follow the xref:install/macos.adoc[macOS install] instructions instead. Before continuing, complete the xref:install/macos.adoc[macOS install] steps (download, extract, and clear the Gatekeeper quarantine) and confirm OliveTin starts correctly by running `./OliveTin`. == Install the files Run these from the extracted archive directory: [source,shell] ---- # Create the application folder and a place for logs mkdir -p ~/Library/Application\ Support/OliveTin/var mkdir -p ~/Library/Logs/OliveTin # Copy in the binary, your config, and the bundled web UI cp OliveTin ~/Library/Application\ Support/OliveTin/ cp config.yaml ~/Library/Application\ Support/OliveTin/ cp -R webui ~/Library/Application\ Support/OliveTin/ ---- This gives you the following layout, all owned by your user: [source] ---- ~/Library/Application Support/OliveTin/ ├── OliveTin # the binary ├── config.yaml # your configuration ├── webui/ # the web interface assets (shipped in the archive) └── var/ # runtime data OliveTin writes (logs, etc.) ~/Library/Logs/OliveTin/olivetin.log # service stdout/stderr ---- === Create the service definition Create a file named `app.olivetin.olivetin.plist` with the contents below. [IMPORTANT] launchd does *not* expand `~`, so the paths must be absolute. Replace `YOUR_USERNAME` with the output of `whoami` in every path. [source,xml] ---- Label app.olivetin.olivetin ProgramArguments /Users/YOUR_USERNAME/Library/Application Support/OliveTin/OliveTin -configdir /Users/YOUR_USERNAME/Library/Application Support/OliveTin WorkingDirectory /Users/YOUR_USERNAME/Library/Application Support/OliveTin KeepAlive RunAtLoad StandardOutPath /Users/YOUR_USERNAME/Library/Logs/OliveTin/olivetin.log StandardErrorPath /Users/YOUR_USERNAME/Library/Logs/OliveTin/olivetin.log ---- `WorkingDirectory` makes the relative `webui` and `var` folders resolve inside the application folder, `KeepAlive` restarts OliveTin if it exits (like systemd's `Restart=always`), and `RunAtLoad` starts it as soon as the service is loaded. === Register and start the service [source,shell] ---- cp app.olivetin.olivetin.plist ~/Library/LaunchAgents/ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/app.olivetin.olivetin.plist ---- [NOTE] OliveTin looks for `config.yaml` in the directory given by the `-configdir` flag, which defaults to the current directory. The service definition below passes `-configdir /usr/local/etc/OliveTin` explicitly. == Choose LaunchAgent or LaunchDaemon launchd offers two ways to run a background service: * *LaunchAgent* - runs as your user and starts when you log in. No root required. Best for a desktop Mac. * *LaunchDaemon* - runs as root and starts at boot, before any user logs in. Best for a headless, always-on Mac. == Create the service definition Create a file named `app.olivetin.olivetin.plist` with the following contents. Adjust the two paths if you installed OliveTin elsewhere. sudo cp -R webui /usr/local/etc/OliveTin/ ---- [NOTE] OliveTin looks for `config.yaml` in the directory given by the `-configdir` flag, which defaults to the current directory. The service definition below passes `-configdir /usr/local/etc/OliveTin` explicitly, and sets `WorkingDirectory` so the `webui` and `var` folders resolve there. === Create the service definition Create a file named `app.olivetin.olivetin.plist` with the following contents. Adjust the paths if you installed OliveTin elsewhere. [source,xml] ---- Label app.olivetin.olivetin ProgramArguments /usr/local/bin/OliveTin -configdir /usr/local/etc/OliveTin WorkingDirectory /usr/local/etc/OliveTin KeepAlive RunAtLoad StandardOutPath /usr/local/var/log/olivetin.log StandardErrorPath /usr/local/var/log/olivetin.log ---- `KeepAlive` restarts OliveTin if it exits (like systemd's `Restart=always`), and `RunAtLoad` starts it as soon as the service is loaded. === Register and start the service [source,shell] ---- mkdir -p /usr/local/var/log cp app.olivetin.olivetin.plist ~/Library/LaunchAgents/ launchctl load ~/Library/LaunchAgents/app.olivetin.olivetin.plist ---- To stop and disable it: [source,shell] ---- launchctl unload ~/Library/LaunchAgents/app.olivetin.olivetin.plist ---- === As a LaunchDaemon (system-wide, at boot) [source,shell] ---- sudo launchctl kickstart -k system/app.olivetin.olivetin ---- sudo launchctl bootstrap system /Library/LaunchDaemons/app.olivetin.olivetin.plist ---- [NOTE] `bootstrap`/`bootout` replace the deprecated `launchctl load`/`unload`. The domain target for a LaunchDaemon is `system`. To stop and disable it: [source,shell] ---- sudo launchctl bootout system /Library/LaunchDaemons/app.olivetin.olivetin.plist sudo launchctl bootstrap system /Library/LaunchDaemons/app.olivetin.olivetin.plist ---- == Verify sudo launchctl bootout system /Library/LaunchDaemons/app.olivetin.olivetin.plist ---- === Restart after a change After editing `config.yaml` or replacing the binary, restart the service so the change takes effect. To restart in place: [source,shell] ---- sudo launchctl kickstart -k system/app.olivetin.olivetin ---- If you changed the *plist* itself, `kickstart` is not enough - boot the service out and back in so launchd re-reads it (`bootstrap` errors if the service is still loaded): [source,shell] ---- sudo launchctl bootout system /Library/LaunchDaemons/app.olivetin.olivetin.plist sudo launchctl bootstrap system /Library/LaunchDaemons/app.olivetin.olivetin.plist ---- === Verify Open http://localhost:1337 in a browser. If the page does not load, check the service log: [source,shell] ---- tail -f /usr/local/var/log/olivetin.log ---- include::partial$install/post_generic.adoc[]