← back to Nas Setup

scripts/install-root-daemon.sh

98 lines

#!/bin/bash
# install-root-daemon.sh — one-paste, run as root:
#     sudo bash /Users/macstudio3/Projects/nas-setup/scripts/install-root-daemon.sh
#
# Converts the realestate on-prem dump mirror from a user LaunchAgent (which EPERM'd on
# /Volumes/Henry because macOS TCC won't honor Full Disk Access on the SIP bash responsible
# process for launchd) to a root LaunchDaemon (runs outside the per-user TCC consent domain).
#
# Self-diagnosing + idempotent:
#   1. PROBE  — can root write to /Volumes/Henry? If NOT, root is TCC-gated too → bail, Option B
#               doesn't help, no infra installed. If yes, continue.
#   2. SSH    — give root its own copy of the Kamatera key (/var/root/.ssh) + config.
#   3. RUN    — execute the pull once as root, end-to-end, and show the result.
#   4. INSTALL— drop the LaunchDaemon into /Library/LaunchDaemons, bootstrap it into system/.
#   5. RETIRE — bootout the old user LaunchAgent so the two don't both run.
# Re-running is safe (overwrites its own artifacts, re-bootstraps).
set -uo pipefail

USER_HOME=/Users/macstudio3
NAS=$USER_HOME/Projects/nas-setup
HENRY=/Volumes/Henry/dw-backups/realestate
KEY=id_ed25519_wallco_20260530
LABEL=com.steve.nas-realestate-dump-mirror
ROOT_LABEL=$LABEL-root
DAEMON_SRC=$NAS/launchd/$ROOT_LABEL.plist
DAEMON_DST=/Library/LaunchDaemons/$ROOT_LABEL.plist

say(){ printf '\n=== %s ===\n' "$1"; }

if [ "$(id -u)" -ne 0 ]; then echo "must run as root: sudo bash $0"; exit 1; fi

# ── 1. PROBE: can root write to the external volume? (the decisive TCC test) ──
say "1. probe: root write to /Volumes/Henry"
mkdir -p "$HENRY" 2>/dev/null
PROBE="$HENRY/.root-tcc-probe.$$"
if touch "$PROBE" 2>/tmp/root-probe.err; then
  rm -f "$PROBE"
  echo "OK — root CAN write to Henry. TCC does not gate the system LaunchDaemon domain here. Proceeding."
else
  echo "BLOCKED — root is ALSO TCC-gated on /Volumes/Henry:"
  cat /tmp/root-probe.err
  echo
  echo "=> Option B (root daemon) does NOT bypass TCC on this box. Nothing was installed."
  echo "   Fall back to Option A: grant Full Disk Access to /opt/homebrew/bin/bash in System Settings."
  exit 2
fi

# ── 2. SSH: give root its own copy of the Kamatera key + config ──
say "2. root ssh setup (/var/root/.ssh)"
install -d -m 700 /var/root/.ssh
install -m 600 "$USER_HOME/.ssh/$KEY" /var/root/.ssh/$KEY
cat > /var/root/.ssh/config <<CFG
Host 45.61.58.125
    HostName 45.61.58.125
    User root
    IdentityFile /var/root/.ssh/$KEY
    IdentitiesOnly yes
    StrictHostKeyChecking accept-new
    UserKnownHostsFile /var/root/.ssh/known_hosts
CFG
chmod 600 /var/root/.ssh/config
if HOME=/var/root ssh -o BatchMode=yes -o ConnectTimeout=15 root@45.61.58.125 "echo ok" >/dev/null 2>&1; then
  echo "OK — root authenticates to Kamatera."
else
  echo "WARN — root ssh test to Kamatera failed; the daemon run below will surface the error."
fi

# ── 3. RUN once as root, end-to-end ──
say "3. run the pull once as root"
HOME=/var/root \
  HENRY_BACKUP_DIR="$HENRY" \
  NAS_BACKUP_DIR=/Volumes/DW-Backups/realestate \
  PGDUMP_GLOB='/root/backups/db/realestate_*.dump' \
  PGDUMP_FLOOR_MB=1 PGDUMP_TOC_FLOOR=5 \
  PATH=/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin \
  /opt/homebrew/bin/bash "$NAS/scripts/pull-dw-dump.sh"
RUN_RC=$?
echo "pull exit rc=$RUN_RC (0 = a destination verified)"

# ── 4. INSTALL the LaunchDaemon ──
say "4. install + bootstrap the root LaunchDaemon"
install -m 644 -o root -g wheel "$DAEMON_SRC" "$DAEMON_DST"
launchctl bootout system/$ROOT_LABEL 2>/dev/null
launchctl bootstrap system "$DAEMON_DST" && echo "bootstrapped $ROOT_LABEL into system/"
launchctl print system/$ROOT_LABEL >/dev/null 2>&1 && echo "loaded OK (runs daily 03:50 as root)"

# ── 5. RETIRE the old user LaunchAgent so both don't run ──
say "5. retire the old user LaunchAgent"
launchctl bootout gui/501/$LABEL 2>/dev/null && echo "booted out user agent gui/501/$LABEL"
# disable it from auto-reloading on next login (leave the plist file in place, just disabled)
launchctl disable gui/501/$LABEL 2>/dev/null || true
echo "user agent disabled (plist left on disk, no longer loads)"

say "DONE"
echo "Latest on Henry:"; ls -la "$HENRY"
echo
echo "If step 3 showed a PASS line and rc=0, the root daemon is the fix — realestate now mirrors nightly as root."