docs: fixup a merge of macOS docs I messed up
This commit is contained in:
commit
bf3efa54c1
|
|
@ -79,7 +79,7 @@ archives:
|
|||
- src: Dockerfile.singlearch
|
||||
dst: Dockerfile
|
||||
- webui
|
||||
- ./var/
|
||||
- var
|
||||
name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}{{ .Arm }}"
|
||||
wrap_in_directory: true
|
||||
format_overrides:
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
*** xref:install/bsd.adoc[BSD]
|
||||
*** xref:install/windows.adoc[Windows]
|
||||
**** xref:install/windows_service.adoc[Windows Service]
|
||||
*** xref:install/macos.adoc[MacOS]
|
||||
**** xref:install/macos_service.adoc[MacOS Service]
|
||||
*** xref:install/macos.adoc[macOS Desktop]
|
||||
*** xref:install/macos_service.adoc[macOS Service]
|
||||
*** xref:install/choose_package.adoc[All download options]
|
||||
* Upgrade Guide
|
||||
** xref:upgrade/2k3k.adoc[Understanding 2k vs 3k]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
= macOS
|
||||
= macOS Desktop
|
||||
|
||||
OliveTin runs natively on macOS, on both Apple Silicon (M-series) and Intel Macs. It is a single, self-contained binary - there is no installer and no dependencies to set up.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
= macOS launchd service install
|
||||
= 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.
|
||||
|
||||
|
|
@ -6,14 +6,81 @@ Before continuing, complete the xref:install/macos.adoc[macOS install] steps (do
|
|||
|
||||
== Install the files
|
||||
|
||||
Copy the binary somewhere on your `PATH`, and put your configuration in a dedicated directory:
|
||||
Run these from the extracted archive directory:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
sudo cp OliveTin /usr/local/bin/OliveTin
|
||||
# Create the application folder and a place for logs
|
||||
mkdir -p ~/Library/Application\ Support/OliveTin/var
|
||||
mkdir -p ~/Library/Logs/OliveTin
|
||||
|
||||
sudo mkdir -p /usr/local/etc/OliveTin
|
||||
sudo cp config.yaml /usr/local/etc/OliveTin/config.yaml
|
||||
# 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]
|
||||
----
|
||||
<?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>app.olivetin.olivetin</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/YOUR_USERNAME/Library/Application Support/OliveTin/OliveTin</string>
|
||||
<string>-configdir</string>
|
||||
<string>/Users/YOUR_USERNAME/Library/Application Support/OliveTin</string>
|
||||
</array>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/YOUR_USERNAME/Library/Application Support/OliveTin</string>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/YOUR_USERNAME/Library/Logs/OliveTin/olivetin.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/YOUR_USERNAME/Library/Logs/OliveTin/olivetin.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
----
|
||||
|
||||
`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]
|
||||
|
|
@ -29,6 +96,15 @@ launchd offers two ways to run a background service:
|
|||
== 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]
|
||||
----
|
||||
|
|
@ -46,6 +122,9 @@ Create a file named `app.olivetin.olivetin.plist` with the following contents. A
|
|||
<string>/usr/local/etc/OliveTin</string>
|
||||
</array>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/usr/local/etc/OliveTin</string>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
|
|
@ -62,9 +141,7 @@ Create a file named `app.olivetin.olivetin.plist` with the following contents. A
|
|||
|
||||
`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
|
||||
|
||||
=== As a LaunchAgent (per-user)
|
||||
=== Register and start the service
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
|
|
@ -84,20 +161,45 @@ launchctl unload ~/Library/LaunchAgents/app.olivetin.olivetin.plist
|
|||
|
||||
[source,shell]
|
||||
----
|
||||
sudo mkdir -p /usr/local/var/log
|
||||
sudo cp app.olivetin.olivetin.plist /Library/LaunchDaemons/
|
||||
sudo chown root:wheel /Library/LaunchDaemons/app.olivetin.olivetin.plist
|
||||
sudo launchctl load /Library/LaunchDaemons/app.olivetin.olivetin.plist
|
||||
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 unload /Library/LaunchDaemons/app.olivetin.olivetin.plist
|
||||
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?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">
|
||||
<!--
|
||||
launchd service definition for OliveTin on macOS.
|
||||
This is the macOS equivalent of the Linux systemd unit (var/systemd/OliveTin.service).
|
||||
|
||||
As a per-user LaunchAgent (recommended, no root needed):
|
||||
cp app.olivetin.olivetin.plist ~/Library/LaunchAgents/
|
||||
launchctl bootstrap ~/Library/LaunchAgents/app.olivetin.olivetin.plist # start now + at login
|
||||
launchctl bootout ~/Library/LaunchAgents/app.olivetin.olivetin.plist # stop + disable
|
||||
|
||||
As a system-wide LaunchDaemon (starts at boot, before login; needs root):
|
||||
sudo cp app.olivetin.olivetin.plist /Library/LaunchDaemons/
|
||||
sudo chown root:wheel /Library/LaunchDaemons/app.olivetin.olivetin.plist
|
||||
sudo launchctl load /Library/LaunchDaemons/app.olivetin.olivetin.plist
|
||||
|
||||
Edit the two paths below to match where you installed the binary and config.
|
||||
-->
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>app.olivetin.olivetin</string>
|
||||
|
||||
<!-- Path to the OliveTin binary, then flags. -configdir is the directory
|
||||
that contains your config.yaml. -->
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/local/bin/OliveTin</string>
|
||||
<string>-configdir</string>
|
||||
<string>/usr/local/etc/OliveTin</string>
|
||||
</array>
|
||||
|
||||
<!-- systemd's Restart=always -->
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
<!-- Start at load (login for a LaunchAgent, boot for a LaunchDaemon) -->
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<!-- Where stdout/stderr go; tail these for troubleshooting -->
|
||||
<key>StandardOutPath</key>
|
||||
<string>/usr/local/var/log/olivetin.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/usr/local/var/log/olivetin.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
# =============================================================================
|
||||
# OliveTin example configuration — macOS (Apple Silicon & Intel)
|
||||
# =============================================================================
|
||||
#
|
||||
# This is a macOS-flavoured version of the stock `example.config.yaml`. Every
|
||||
# action that differs from the Linux example carries a `# Linux equivalent:`
|
||||
# comment so you can see exactly what was changed and why.
|
||||
#
|
||||
# All commands here are tested against macOS with /bin/zsh (the default login
|
||||
# shell since macOS Catalina) and also work under /bin/bash. OliveTin runs the
|
||||
# `shell:` string with `sh -c` by default, so these are written to be portable
|
||||
# POSIX/zsh/bash one-liners.
|
||||
#
|
||||
# To use this file, copy it next to the OliveTin binary as `config.yaml`:
|
||||
# cp ./var/macos/config.yaml config.yaml
|
||||
# ./OliveTin
|
||||
#
|
||||
# Docs: https://docs.olivetin.app/
|
||||
# =============================================================================
|
||||
|
||||
# The built-in micro proxy hosts the WebUI and REST API on a single port.
|
||||
# Listen on all addresses, port 1337. Open http://localhost:1337 after start.
|
||||
listenAddressSingleHTTPFrontend: 0.0.0.0:1337
|
||||
|
||||
# Choose from INFO (default), WARN and DEBUG.
|
||||
# Docs: https://docs.olivetin.app/advanced_configuration/logs.html
|
||||
logLevel: "INFO"
|
||||
|
||||
# Actions are commands that OliveTin executes, normally shown as buttons.
|
||||
# Docs: https://docs.olivetin.app/action_execution/create_your_first.html
|
||||
actions:
|
||||
# The simplest possible action: run a command, flash the button for status.
|
||||
# `ping` works identically on macOS and Linux.
|
||||
- title: Ping the Internet
|
||||
shell: ping -c 3 1.1.1.1
|
||||
icon: ping
|
||||
popupOnStart: execution-dialog-stdout-only
|
||||
execOnStartup: true
|
||||
|
||||
# Show just the command output in a popup.
|
||||
#
|
||||
# Linux equivalent: shell: df -h /media
|
||||
# macOS has no /media mountpoint. The root volume is `/`; external/USB disks
|
||||
# mount under /Volumes. `df -h /` shows the boot disk; drop the path to list
|
||||
# every mounted volume.
|
||||
- title: Check disk space
|
||||
icon: disk
|
||||
shell: df -h /
|
||||
popupOnStart: execution-dialog-stdout-only
|
||||
|
||||
# Show a fuller dialog with details about the command that ran.
|
||||
#
|
||||
# Linux equivalent: shell: dmesg | tail
|
||||
# macOS `dmesg` requires root and is rarely useful. The unified logging
|
||||
# system is the macOS way to read kernel/system messages. This shows the
|
||||
# last 2 minutes of high-level system log entries.
|
||||
- title: Recent system log
|
||||
shell: log show --last 2m --style compact | tail -n 40
|
||||
icon: logs
|
||||
popupOnStart: execution-dialog
|
||||
|
||||
# A mini button that links to the logs, with rate limiting and an hourly cron.
|
||||
# `date` is identical across platforms.
|
||||
- title: date
|
||||
shell: date
|
||||
id: date
|
||||
timeout: 6
|
||||
icon: clock
|
||||
popupOnStart: execution-button
|
||||
maxRate:
|
||||
- limit: 3
|
||||
duration: 1m
|
||||
execOnCron:
|
||||
- "@hourly"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# macOS-native actions (no Linux equivalent — these showcase the platform)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Send a real macOS Notification Center banner via AppleScript.
|
||||
- title: Send a notification
|
||||
icon: '🔔' # bell
|
||||
shell: osascript -e 'display notification "Triggered from OliveTin" with title "OliveTin" sound name "Glass"'
|
||||
popupOnStart: execution-button
|
||||
|
||||
# Stop the Mac from sleeping for 1 hour (handy during long jobs/downloads).
|
||||
# `caffeinate` is a built-in macOS utility. `-t` is seconds.
|
||||
- title: Keep awake for 1 hour
|
||||
icon: '☕' # hot beverage
|
||||
shell: caffeinate -d -i -t 3600 &
|
||||
popupOnStart: execution-button
|
||||
|
||||
# Put the displays to sleep immediately (the Mac stays running).
|
||||
- title: Sleep the displays
|
||||
icon: '💤' # zzz
|
||||
shell: pmset displaysleepnow
|
||||
popupOnStart: execution-button
|
||||
|
||||
# Battery / power summary using the built-in `pmset`.
|
||||
- title: Power & battery status
|
||||
icon: '🔋' # battery
|
||||
shell: pmset -g batt
|
||||
popupOnStart: execution-dialog-stdout-only
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Prompt the user for input with `arguments`. `ping` again works as-is.
|
||||
# Docs: https://docs.olivetin.app/action_examples/ping.html
|
||||
- title: Ping host
|
||||
id: ping_host
|
||||
shell: ping {{ host }} -c {{ count }}
|
||||
icon: ping
|
||||
timeout: 100
|
||||
popupOnStart: execution-dialog-stdout-only
|
||||
arguments:
|
||||
- name: host
|
||||
title: Host
|
||||
type: ascii_identifier
|
||||
default: example.com
|
||||
description: The host that you want to ping
|
||||
|
||||
- name: count
|
||||
title: Count
|
||||
type: int
|
||||
default: 3
|
||||
description: How many times do you want to ping?
|
||||
|
||||
# OliveTin can control Docker containers — `docker` is just a CLI app.
|
||||
# On macOS this requires Docker Desktop (or colima/podman) to be installed
|
||||
# and running. The command itself is identical to Linux.
|
||||
# Docs: https://docs.olivetin.app/solutions/container-control-panel/index.html
|
||||
- title: Restart Docker Container
|
||||
icon: restart
|
||||
shell: docker restart {{ container }}
|
||||
arguments:
|
||||
- name: container
|
||||
title: Container name
|
||||
choices:
|
||||
- value: plex
|
||||
- value: traefik
|
||||
- value: grafana
|
||||
|
||||
# The special `confirmation` argument guards against accidental clicks.
|
||||
# Docs: https://docs.olivetin.app/args/input_confirmation.html
|
||||
#
|
||||
# Linux equivalent: shell: rm -rf /opt/oldBackups/
|
||||
# Using a path under the user's home is more natural on macOS.
|
||||
- title: Delete old backups
|
||||
icon: ashtonished
|
||||
shell: rm -rf "$HOME/Backups/old/"
|
||||
arguments:
|
||||
- name: confirm
|
||||
type: confirmation
|
||||
title: Are you sure?!
|
||||
|
||||
# Run your own scripts, not just OS commands. `maxConcurrent` prevents
|
||||
# parallel runs; `timeout` kills a command that runs too long.
|
||||
#
|
||||
# Linux equivalent: shell: /opt/backupScript.sh
|
||||
# macOS convention is to keep personal scripts under your home directory.
|
||||
- title: Run backup script
|
||||
shell: "$HOME/bin/backupScript.sh"
|
||||
shellAfterCompleted: "osascript -e 'display notification \"Backup finished with code {{ exitCode }}\" with title \"OliveTin\"'"
|
||||
maxConcurrent: 1
|
||||
timeout: 10
|
||||
icon: backup
|
||||
popupOnStart: execution-dialog
|
||||
|
||||
# Download themes using a script bundled with OliveTin. You still need to set
|
||||
# `themeName` in this config to actually use the theme.
|
||||
# Docs: https://docs.olivetin.app/reference/reference_themes_for_users.html
|
||||
- title: Get OliveTin Theme
|
||||
exec:
|
||||
- "olivetin-get-theme"
|
||||
- "{{ themeGitRepo }}"
|
||||
- "{{ themeFolderName }}"
|
||||
icon: theme
|
||||
arguments:
|
||||
- name: themeGitRepo
|
||||
title: Theme's Git Repository
|
||||
description: Find new themes at https://olivetin.app/themes
|
||||
type: url
|
||||
|
||||
- name: themeFolderName
|
||||
title: Theme's Folder Name
|
||||
type: ascii_identifier
|
||||
|
||||
# Run actions on other servers over SSH. macOS ships with an OpenSSH client,
|
||||
# so this works out of the box. The helper below is optional.
|
||||
# Docs: https://docs.olivetin.app/action_examples/ssh-easy.html
|
||||
- title: "Setup easy SSH"
|
||||
icon: ssh
|
||||
shell: olivetin-setup-easy-ssh
|
||||
popupOnStart: execution-dialog
|
||||
|
||||
# Entities let you generate actions dynamically from "things" (servers,
|
||||
# containers, VMs) loaded from files on disk.
|
||||
# Docs: https://docs.olivetin.app/entities/intro.html
|
||||
#
|
||||
# entities:
|
||||
# - file: entities/servers.yaml
|
||||
# name: server
|
||||
|
||||
# Dashboards organise actions into folders and fieldsets.
|
||||
# Docs: https://docs.olivetin.app/dashboards/intro.html
|
||||
#
|
||||
# dashboards:
|
||||
# - title: My Mac
|
||||
# contents:
|
||||
# - title: Power & battery status
|
||||
# - title: Sleep the displays
|
||||
|
||||
# =============================================================================
|
||||
# Security - Authentication
|
||||
# =============================================================================
|
||||
|
||||
# If "true", users must log in before doing anything.
|
||||
authRequireGuestsToLogin: false
|
||||
|
||||
# The simplest auth: define users/passwords in this config. OliveTin also
|
||||
# supports header-based auth, OAuth2 and JWT (documented separately).
|
||||
# Docs: https://docs.olivetin.app/security/local.html
|
||||
#
|
||||
# Generating an argon2id hash on macOS:
|
||||
# brew install argon2
|
||||
# echo -n 'yourPassword' | argon2 "$(openssl rand -base64 16)" -id -e
|
||||
# (Linux equivalent typically uses the distro's `argon2` package directly.)
|
||||
authLocalUsers:
|
||||
enabled: true
|
||||
# users:
|
||||
# - username: alice
|
||||
# usergroup: admins
|
||||
# password: "$argon2id$v=19$m=65536,t=4,p=2$puyxA0s555TSFx7hnFLCXA$PyhLGpZtvpMMvc2DgMWkM8OJMKO55euwV5gm//1iwx4"
|
||||
|
||||
# =============================================================================
|
||||
# Security - Access Control
|
||||
# =============================================================================
|
||||
|
||||
# Policies affect the whole app (eg: ability to view the log list).
|
||||
# Docs: https://docs.olivetin.app/security/acl.html
|
||||
defaultPolicy:
|
||||
showDiagnostics: true
|
||||
showLogList: true
|
||||
|
||||
# Permissions affect individual actions.
|
||||
defaultPermissions:
|
||||
view: true
|
||||
exec: true
|
||||
logs: true
|
||||
|
||||
# ACLs match policy/permissions to users.
|
||||
accessControlLists:
|
||||
- name: admin_acl
|
||||
matchUsergroups: ["admins"]
|
||||
policy:
|
||||
showDiagnostics: true
|
||||
permissions:
|
||||
view: true
|
||||
exec: true
|
||||
logs: true
|
||||
|
||||
# OliveTin has many more options not shown here. See docs.olivetin.app.
|
||||
|
|
@ -0,0 +1,383 @@
|
|||
# Installing OliveTin on macOS
|
||||
|
||||
> **Draft** — local Markdown draft kept in sync with the AsciiDoc docs at
|
||||
> <https://docs.olivetin.app/install/macos.html> and
|
||||
> <https://docs.olivetin.app/install/macos_service.html>
|
||||
> (`docs/modules/ROOT/pages/install/macos.adoc` and `macos_service.adoc`).
|
||||
|
||||
OliveTin runs natively on macOS on both **Apple Silicon (M1/M2/M3/M4)** and
|
||||
**Intel** Macs. It is a single self-contained binary written in Go — there is no
|
||||
installer and no background dependencies to install.
|
||||
|
||||
---
|
||||
|
||||
## 1. Choose the right download
|
||||
|
||||
macOS builds are published on the
|
||||
[GitHub releases page](https://github.com/OliveTin/OliveTin/releases). Pick the
|
||||
archive that matches your Mac's processor:
|
||||
|
||||
| Your Mac | Archive |
|
||||
|---|---|
|
||||
| Apple Silicon (M-series) | `OliveTin-darwin-arm64.tar.gz` |
|
||||
| Intel | `OliveTin-darwin-amd64.tar.gz` |
|
||||
|
||||
Not sure which you have? Run this in Terminal:
|
||||
|
||||
```sh
|
||||
uname -m
|
||||
```
|
||||
|
||||
`arm64` → Apple Silicon, `x86_64` → Intel.
|
||||
|
||||
> If you download the wrong architecture, macOS will refuse to run it with a
|
||||
> "Bad CPU type in executable" error.
|
||||
|
||||
---
|
||||
|
||||
## 2. Extract and place the binary
|
||||
|
||||
```sh
|
||||
# Move to your Downloads folder (adjust if needed)
|
||||
cd ~/Downloads
|
||||
|
||||
# Extract — replace arm64 with amd64 on Intel
|
||||
tar -xzf OliveTin-darwin-arm64.tar.gz
|
||||
cd OliveTin-darwin-arm64
|
||||
```
|
||||
|
||||
For a quick try-out you can run it straight from this folder. To install it
|
||||
properly, see step 6 — you can install it **as your own user (no root)** or
|
||||
**system-wide**.
|
||||
|
||||
---
|
||||
|
||||
## 3. Clear the Gatekeeper quarantine
|
||||
|
||||
Because the binary is downloaded from the internet and is **not notarized by
|
||||
Apple**, macOS Gatekeeper will block the first run with a message like
|
||||
*"OliveTin can't be opened because Apple cannot check it for malicious
|
||||
software."*
|
||||
|
||||
Remove the quarantine attribute so it will run:
|
||||
|
||||
```sh
|
||||
xattr -dr com.apple.quarantine ./OliveTin
|
||||
```
|
||||
|
||||
Alternatively, the first time only, you can right-click the binary in Finder →
|
||||
**Open**, or approve it under **System Settings → Privacy & Security**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Create a configuration file
|
||||
|
||||
OliveTin looks for a file named `config.yaml` in its **config directory**, which
|
||||
defaults to the current directory (`.`). You can point elsewhere with
|
||||
`-configdir /path/to/dir`.
|
||||
|
||||
A minimal `config.yaml` to confirm everything works:
|
||||
|
||||
```yaml
|
||||
listenAddressSingleHTTPFrontend: 0.0.0.0:1337
|
||||
logLevel: "INFO"
|
||||
|
||||
actions:
|
||||
- title: Hello macOS
|
||||
icon: terminal
|
||||
shell: echo "Hello from $(scutil --get ComputerName)!"
|
||||
popupOnStart: execution-dialog-stdout-only
|
||||
```
|
||||
|
||||
For a fuller, macOS-tuned starting point — with working examples for
|
||||
notifications (`osascript`), `caffeinate`, `pmset`, disk usage, the unified
|
||||
system log, and Docker — see the **`config.macos.yaml`** that ships alongside
|
||||
this guide. Copy it in place with:
|
||||
|
||||
```sh
|
||||
cp config.macos.yaml config.yaml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Run OliveTin
|
||||
|
||||
From the folder that contains both `OliveTin` and `config.yaml`:
|
||||
|
||||
```sh
|
||||
./OliveTin
|
||||
```
|
||||
|
||||
Then open the web interface at:
|
||||
|
||||
```text
|
||||
http://localhost:1337
|
||||
```
|
||||
|
||||
(or `http://<your-mac-hostname>:1337` from another device on your network).
|
||||
|
||||
Press **Ctrl-C** in the Terminal to stop it.
|
||||
|
||||
---
|
||||
|
||||
## 6. Run OliveTin as a background service (launchd)
|
||||
|
||||
On Linux, OliveTin is managed by **systemd**. The macOS equivalent is
|
||||
**launchd**. launchd offers two ways to run a background service, and which one
|
||||
you pick decides whether you need root:
|
||||
|
||||
* **LaunchAgent (local user)** — runs as *your* user and starts when you log in.
|
||||
**No `sudo` required**, and everything lives under your home folder. Best for a
|
||||
desktop Mac. See [Local user installation](#local-user-installation-no-root).
|
||||
* **LaunchDaemon (system-wide)** — runs as `root` and starts at boot, before any
|
||||
user logs in. Requires `sudo`. Best for a headless, always-on Mac. See
|
||||
[System-wide installation](#system-wide-installation-requires-root).
|
||||
|
||||
You only need to follow **one** of the two sections below.
|
||||
|
||||
### Local user installation (no root)
|
||||
|
||||
Everything — the binary, configuration, the `var` data folder, and the `webui`
|
||||
folder — is kept together under `~/Library/Application Support/OliveTin`, so you
|
||||
never need `sudo`.
|
||||
|
||||
**Install the files** (run from the extracted archive directory):
|
||||
|
||||
```sh
|
||||
# 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:
|
||||
|
||||
```
|
||||
~/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.
|
||||
|
||||
```xml
|
||||
<?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>app.olivetin.olivetin</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/YOUR_USERNAME/Library/Application Support/OliveTin/OliveTin</string>
|
||||
<string>-configdir</string>
|
||||
<string>/Users/YOUR_USERNAME/Library/Application Support/OliveTin</string>
|
||||
</array>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/YOUR_USERNAME/Library/Application Support/OliveTin</string>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/YOUR_USERNAME/Library/Logs/OliveTin/olivetin.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/YOUR_USERNAME/Library/Logs/OliveTin/olivetin.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
`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:**
|
||||
|
||||
```sh
|
||||
cp app.olivetin.olivetin.plist ~/Library/LaunchAgents/
|
||||
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/app.olivetin.olivetin.plist
|
||||
```
|
||||
|
||||
> `bootstrap`/`bootout` replace the deprecated `launchctl load`/`unload`. They
|
||||
> take a *domain target*: `gui/$(id -u)` is your own per-user GUI domain
|
||||
> (`id -u` is your numeric user ID).
|
||||
|
||||
To stop and disable it:
|
||||
|
||||
```sh
|
||||
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/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:
|
||||
|
||||
```sh
|
||||
launchctl kickstart -k gui/$(id -u)/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):
|
||||
|
||||
```sh
|
||||
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/app.olivetin.olivetin.plist
|
||||
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/app.olivetin.olivetin.plist
|
||||
```
|
||||
|
||||
**Verify** — open <http://localhost:1337>. If the page does not load, check the
|
||||
service log:
|
||||
|
||||
```sh
|
||||
tail -f ~/Library/Logs/OliveTin/olivetin.log
|
||||
```
|
||||
|
||||
### System-wide installation (requires root)
|
||||
|
||||
Use this for a headless or shared Mac that should start OliveTin at boot, before
|
||||
anyone logs in. It installs the binary on the system `PATH` and runs as `root`
|
||||
via a LaunchDaemon, so the commands use `sudo`.
|
||||
|
||||
**Install the files:**
|
||||
|
||||
```sh
|
||||
sudo cp OliveTin /usr/local/bin/OliveTin
|
||||
|
||||
sudo mkdir -p /usr/local/etc/OliveTin
|
||||
sudo cp config.yaml /usr/local/etc/OliveTin/config.yaml
|
||||
sudo cp -R webui /usr/local/etc/OliveTin/
|
||||
```
|
||||
|
||||
> 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.
|
||||
|
||||
```xml
|
||||
<?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>app.olivetin.olivetin</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/local/bin/OliveTin</string>
|
||||
<string>-configdir</string>
|
||||
<string>/usr/local/etc/OliveTin</string>
|
||||
</array>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/usr/local/etc/OliveTin</string>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/usr/local/var/log/olivetin.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/usr/local/var/log/olivetin.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
`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:**
|
||||
|
||||
```sh
|
||||
sudo mkdir -p /usr/local/var/log
|
||||
sudo cp app.olivetin.olivetin.plist /Library/LaunchDaemons/
|
||||
sudo chown root:wheel /Library/LaunchDaemons/app.olivetin.olivetin.plist
|
||||
sudo launchctl bootstrap system /Library/LaunchDaemons/app.olivetin.olivetin.plist
|
||||
```
|
||||
|
||||
> `bootstrap`/`bootout` replace the deprecated `launchctl load`/`unload`. The
|
||||
> domain target for a LaunchDaemon is `system`.
|
||||
|
||||
To stop and disable it:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
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):
|
||||
|
||||
```sh
|
||||
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>. If the page does not load, check the
|
||||
service log:
|
||||
|
||||
```sh
|
||||
tail -f /usr/local/var/log/olivetin.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**"Bad CPU type in executable"** — you downloaded the wrong architecture. Get
|
||||
the `arm64` build for Apple Silicon, `amd64` for Intel (see step 1).
|
||||
|
||||
**Gatekeeper still blocks it** — re-run the `xattr -dr com.apple.quarantine`
|
||||
command in step 3, or approve the app under **System Settings → Privacy &
|
||||
Security**.
|
||||
|
||||
**It runs but the page won't load** — check that nothing else is using port
|
||||
1337 (`lsof -i :1337`), and that you're browsing to `http://` (not `https://`).
|
||||
|
||||
**Reading the logs**
|
||||
|
||||
* Running in Terminal: the log is printed directly to the window.
|
||||
* Running under launchd as a local user: `tail -f ~/Library/Logs/OliveTin/olivetin.log`
|
||||
* Running under launchd system-wide: `tail -f /usr/local/var/log/olivetin.log`
|
||||
* You can raise detail by setting `logLevel: "DEBUG"` in `config.yaml`.
|
||||
|
||||
**Still stuck?** Ask in the
|
||||
[OliveTin Discord](https://discord.gg/jhYWWpNJ3v) or open an issue on
|
||||
[GitHub](https://github.com/OliveTin/OliveTin/issues).
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
* [Create your first action](https://docs.olivetin.app/action_execution/create_your_first.html)
|
||||
* [Configuration reference](https://docs.olivetin.app/)
|
||||
* [Security & authentication](https://docs.olivetin.app/security/local.html)
|
||||
Loading…
Reference in New Issue