Skip to content

Operations Tooling

Sanctum ships with a set of operational scripts in ~/.sanctum/scripts/ that automate the most common maintenance tasks. These are designed to be run from the Mac Mini hub.

The cron clock tower — automation runs on schedule

Your house has a health check suite, a sync pipeline, an auto-healing watchdog, and a diagnostic tool. There are Fortune 500 companies with worse observability. We’re not going to dwell on what that says about the state of enterprise software or the mental state of people who build home intelligence platforms. We’re just going to document the tools.

The big picture. One command, every service, everything you need to know about whether your house is alive and well or quietly falling apart.

Terminal window
~/.sanctum/scripts/sanctum-status.sh

What it checks:

  • Mac services: Cloudflare Tunnel, Home Assistant, LM Studio, Docker
  • VM services: health ingester, Graphiti, Neo4j, OpenClaw gateway
  • External access: ha.nepveu.name, health.nepveu.name, sanctum.haus (with CF Access token test)
  • Tailscale: connection status, peer count
  • Keychain: all critical keys present (account: sanctum)
  • Git repos: 8 Mac repos + VM repo (dirty files, unpushed commits)
  • Disk usage: Mac and VM

Flags:

FlagEffect
--quietOnly show problems. Exit code = number of issues.

Use --quiet in cron jobs or post-boot checks to get a pass/fail result. No news is good news. Literally — silence means everything is fine.

One command to check, commit, and push every Sanctum git repository. Including the VM repo, which requires a bundle proxy because — and this never stops being fun to explain — the VM has no internet access.

Terminal window
~/.sanctum/scripts/sanctum-sync.sh

Repos synced:

  • sanctum-config (~/.sanctum)
  • command-center, health-center, openclaw-skills, sanctum-docs
  • yoda-voice-agent, genome-mcp, icloud-organizer
  • manoir-nepveu (VM, via bundle proxy)

Dirty files are auto-committed with a generated message describing the changes. The VM repo is pushed through the Mac using vm-push.sh under the hood, which creates a git bundle, sneaks it across the bridge network like contraband, and pushes it to GitHub on the VM’s behalf.

Flags:

FlagEffect
--dry-runShow what would be done without making changes
--forceCommit and push without prompting

The thing you run when something feels wrong but you don’t know what. It checks file permissions, port conflicts, stale processes, config cache, Docker health, keychain integrity, firewall state, and VM connectivity. Then it tells you what’s broken. And if you ask nicely — with --fix — it’ll try to repair things too.

Terminal window
# Diagnose only
~/.sanctum/scripts/sanctum-doctor.sh
# Diagnose and auto-fix
~/.sanctum/scripts/sanctum-doctor.sh --fix

What it checks and fixes:

CheckAuto-fix
Config cache staleRegenerates .instance.json
File permissions driftedRestores 700/600 as needed
Scripts not executablechmod 700
Duplicate cloudflared processesKills extras, keeps oldest
Zombie Docker containersdocker container prune
Stale sanctum keychain entriesReports (manual cleanup)
Missing critical keychain keysReports
pf firewall anchor not loadedReloads anchor
Stopped Docker containersdocker start
LaunchAgents not loadedlaunchctl bootstrap
VM SOPS vault integrityReports

Push the VM git repository to GitHub via the Mac. The VM runs on a host-only network with no internet access, so this script creates a git bundle on the VM, transfers it to the Mac, merges it with the GitHub remote, and pushes.

It’s a Rube Goldberg machine for git push, and it works flawlessly.

Terminal window
# Push current VM state
~/.sanctum/scripts/vm-push.sh
# Commit all dirty files on VM first, then push
~/.sanctum/scripts/vm-push.sh --commit "Updated health ingester config"

Merge conflicts are resolved automatically by favoring the VM version (since the VM is the source of truth for its own repo).

Rotate the Cloudflare Access service token used by Health Auto Export to authenticate with the health ingester. This should be run before the current token expires (check sanctum-status.sh for expiry warnings).

Terminal window
~/.sanctum/scripts/rotate-cf-service-token.sh

What it does:

  1. Creates a new service token via CF API (1-year expiry)
  2. Updates the CF Access policy for health.nepveu.name
  3. Deletes the old service token
  4. Updates the Mac Keychain with new credentials
  5. Regenerates the Health Auto Export import file
  6. Verifies the new token works end-to-end

After running, you need to update Health Auto Export on the iPhone with the new CF-Access-Client-Id and CF-Access-Client-Secret headers (or re-import the regenerated config from iCloud).

Yes, the last step is manual. On your phone. With your thumbs. Welcome to the limits of automation.

Generate a Health Auto Export importable .json file for this Sanctum instance. Reads tokens from Keychain and VM SOPS, and produces a file ready to AirDrop to an iPhone.

Terminal window
# Generate on Desktop (default)
~/.sanctum/scripts/generate-hae-config.sh
# Generate to specific path
~/.sanctum/scripts/generate-hae-config.sh ~/Desktop/my-health-config.json

The generated config includes the correct endpoint URL, all three authentication headers (base64-encoded), and the 16 health metrics that the ingester processes. After AirDropping to the iPhone, open the file in Health Auto Export and tap Import.

Interactive wizard that creates a new instance.yaml for a fresh Sanctum installation. Asks about your household, network, optional services, and notifications, then generates a complete config file.

Terminal window
~/.sanctum/scripts/generate-instance.sh

The wizard:

  • Auto-detects your macOS username, home directory, and LAN IP
  • Picks up Tailscale hostname and IP if installed
  • Generates a URL slug from your household name
  • Asks which optional services to enable (Firewalla, voice agent, Cloudflare, health, Tailscale)
  • Configures Cloudflare domain and tunnel name if enabled
  • Sets up notification preferences (Signal)
  • Produces a properly formatted instance.yaml with 600 permissions

After generating, review the file, fill in any hardware-specific values (UTM VM UUID, Firewalla MAC address, HA entity IDs), then run generate-plists.sh to create the LaunchAgents.