launchd / systemd unit
The daemon is meant to run as a service: starts on login, restarts on failure, logs centrally. Pick the unit file for your OS, drop it in, load it, done.
macOS — launchd
Section titled “macOS — launchd”launchd is macOS’s service manager. User agents (run as you, not
root) live in ~/Library/LaunchAgents/. They start when you log in
and stop when you log out — perfect for a personal backup daemon.
1. Create the plist
Section titled “1. Create the plist”<?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>com.unclez.quay.daemon</string>
<key>ProgramArguments</key> <array> <string>/usr/local/bin/quay</string> <string>daemon</string> </array>
<key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>ThrottleInterval</key> <integer>10</integer>
<key>EnvironmentVariables</key> <dict> <key>RUST_LOG</key> <string>quay=info</string> </dict>
<key>StandardOutPath</key> <string>/tmp/quay-daemon.log</string> <key>StandardErrorPath</key> <string>/tmp/quay-daemon.err</string></dict></plist>2. Load it
Section titled “2. Load it”launchctl load -w ~/Library/LaunchAgents/com.unclez.quay.daemon.plist3. Verify
Section titled “3. Verify”launchctl list | grep quay# com.unclez.quay.daemon - ...
tail -f /tmp/quay-daemon.logRestart / stop
Section titled “Restart / stop”# Restart (reads any plist changes)launchctl kickstart -k gui/$(id -u)/com.unclez.quay.daemon
# Stop temporarilylaunchctl unload ~/Library/LaunchAgents/com.unclez.quay.daemon.plist”But I want it to run when I’m not logged in”
Section titled “”But I want it to run when I’m not logged in””That’s a system-level daemon (/Library/LaunchDaemons/, runs as root).
Don’t do that for backups — the daemon needs your user’s
~/Library/Application Support/com.unclez.quay/ config files, which
won’t exist for root. Stay with the user-agent pattern.
If the host needs to run truly headless (a Mac mini that nobody logs into), enable Auto-login in System Settings → Users & Groups so the user agent loads on boot.
Linux — systemd user unit
Section titled “Linux — systemd user unit”Same idea: a per-user systemd service that survives reboots and restarts on failure.
1. Create the unit file
Section titled “1. Create the unit file”[Unit]Description=Quay scheduled-backup daemonAfter=network-online.targetWants=network-online.target
[Service]Type=simpleExecStart=/usr/local/bin/quay daemonEnvironment=RUST_LOG=quay=infoRestart=on-failureRestartSec=10
[Install]WantedBy=default.target2. Enable + start
Section titled “2. Enable + start”systemctl --user daemon-reloadsystemctl --user enable --now quay-daemon3. Verify
Section titled “3. Verify”systemctl --user status quay-daemonjournalctl --user -u quay-daemon -fSurvive logout
Section titled “Survive logout”By default a user systemd unit stops when you log out. Enable lingering to keep it running in the background:
sudo loginctl enable-linger $(whoami)Now quay-daemon runs 24/7 even if you’re not logged in.
Restart / stop
Section titled “Restart / stop”systemctl --user restart quay-daemonsystemctl --user stop quay-daemonsystemctl --user disable quay-daemonWindows
Section titled “Windows”Windows isn’t covered yet — v0.1 focuses on the Unix-style service
managers. For now use Task Scheduler with quay schedule run-once <id> per schedule, or run quay daemon in a long-lived PowerShell
window. v0.2 will ship a Windows Service wrapper.
Health check
Section titled “Health check”The daemon logs a heartbeat every tick. If you want explicit liveness monitoring, the log file’s mtime moves on every fire and the process PID is in the launchd / systemd status.
A simple “is it alive” alert:
# macOS — alert if last log line is more than 70min oldtest "$(stat -f %m /tmp/quay-daemon.log)" -gt $(($(date +%s) - 4200)) || \ echo "Quay daemon log is stale" | mail -s "alert" you@example.com
# Linux — equivalent via journalctljournalctl --user -u quay-daemon --since "1 hour ago" --no-pager | tail -1For a real production setup pair the unit with your existing log/ metric pipeline (Datadog, Grafana Agent, etc.) tailing the journal.