Skip to content

Installation

Tommy supervises the Mac Mini setup — quality assurance by feline

Open Terminal and run:

Terminal window
curl -fsSL https://sanctum.run/install.sh | bash

The installer checks your hardware, installs dependencies, walks you through configuration, and sets up your Sanctum — all in about two minutes. No manual YAML editing required. Two minutes from “I wonder if this works” to “Oh God, it actually works.”

The installer will:

  1. Verify your Mac meets the requirements (Apple Silicon, macOS 15+, 16GB+ RAM)
  2. Install missing dependencies (Homebrew, Node.js, Python, Docker) with your permission
  3. Ask you a few questions about your haus and which features you want
  4. Create ~/.sanctum/instance.yaml with your configuration
  5. Start the Presidio privacy containers (PII scrubbing for external AI)
  6. Set up the shell library and LaunchAgents

After installation, visit the First Run guide to verify everything is working.


If you prefer to set things up by hand — because you read man pages for fun, or because you have trust issues, or both — follow the steps below. Make sure you have completed all the Requirements first.

  1. Create the directory structure.

    Sanctum stores all configuration, templates, and runtime data under ~/.sanctum. A hidden directory for a hidden infrastructure. Poetic.

    Terminal window
    mkdir -p ~/.sanctum/{templates/launchagents,tests,lib,scripts}
  2. Copy the example configuration.

    The example file is an annotated template that documents every available option. It is the most lovingly commented YAML file you will ever read.

    Terminal window
    cp ~/.sanctum/instance.yaml.example ~/.sanctum/instance.yaml
  3. Set your node identity.

    Each node needs a single-line identity file that tells the system which node it is. This is the machine learning who it is, which — depending on your philosophical leanings — is either beautiful or terrifying.

    Terminal window
    echo "your-haus-name" > ~/.sanctum/.node_id

    Use a short, lowercase slug. This value must match a key under the nodes section of your instance.yaml.

Open ~/.sanctum/instance.yaml in your editor. The file is organized into these top-level sections:

# Instance identity
instance:
name: "Your Home Name"
slug: "your-haus-name"
# Node topology
nodes:
your-haus-name:
type: hub
host: 192.168.1.10
# ...
# Services and their ports
services:
gateway:
enabled: true
port: 1977
homeassistant:
enabled: true
port: 8123
# ...
# VM configuration
vm:
ip: 10.10.10.10
bridge_ip: 10.10.10.1
ssh_user: ubuntu
# ...
# Secret management
secrets:
backend: keychain # "keychain" on Mac, "sops" on VM
rotation_day: 1 # Day of month for auto-rotation

At minimum, configure the following for your environment:

SectionWhat to Set
instance.nameHuman-readable name for your haus
instance.slugURL-safe lowercase slug
nodesAt least one hub node with its LAN IP
servicesEnable or disable services based on what you need
vm.ipYour VM’s static IP (default: 10.10.10.10)

The shell library provides helper functions used by scripts and LaunchAgents. It is the connective tissue of the system — unglamorous, essential, and the first thing to check when something stops working.

  1. Source the library in your shell profile.

    Add this line to your ~/.zshrc (or ~/.bashrc):

    Terminal window
    source ~/.sanctum/lib/config.sh
  2. Reload your shell.

    Terminal window
    source ~/.zshrc
  3. Verify the library is loaded.

    Terminal window
    sanctum_get instance.slug

    This should print your instance slug. If it does, the config library is working. If it prints nothing, stare at the cursor for a moment, then check that instance.yaml exists and is valid YAML.

The shell library provides these functions:

FunctionPurpose
sanctum_get <key>Read a value from instance.yaml
sanctum_slugShortcut for the instance slug
sanctum_homeReturns the Sanctum haus directory path
sanctum_vm_ssh <command>Run a command on the VM via SSH
sanctum_enabled <service>Check if a service is enabled
sanctum_expand <template>Expand {{PLACEHOLDER}} variables in a template

Sanctum uses macOS LaunchAgents to manage services. Rather than maintaining individual plist files by hand — an activity that has driven better engineers than you to drink — you generate them from templates.

  1. Review the templates.

    Templates live in ~/.sanctum/templates/launchagents/. Each template uses {{PLACEHOLDER}} syntax for values pulled from instance.yaml and macOS Keychain.

  2. Run the generator.

    Terminal window
    # Preview what will be generated (no files written)
    bash ~/.sanctum/generate-plists.sh --dry-run
    # Generate for real
    bash ~/.sanctum/generate-plists.sh

    The generator does the following:

    • Reads each template from ~/.sanctum/templates/launchagents/
    • Expands placeholders with values from instance.yaml
    • Pulls tokens from macOS Keychain where referenced
    • Skips templates for disabled services
    • Writes rendered plists to ~/Library/LaunchAgents/
  3. Load the generated agents.

    Terminal window
    # Load all Sanctum LaunchAgents
    for plist in ~/Library/LaunchAgents/com.sanctum.*.plist; do
    launchctl load "$plist"
    done

The dashboard is a web interface that displays the status of all services, nodes, and agents. It is the face of Sanctum — the thing you show people when they ask “So what does this Mac Mini actually do?”

  1. Install dependencies.

    Terminal window
    cd ~/.sanctum/dashboard
    npm install
  2. Build and start.

    Terminal window
    npm run dev

    The dashboard will be available at http://localhost:1111.

  3. Verify the config endpoint.

    The dashboard serves instance configuration (with secrets excluded) at its API endpoint:

    Terminal window
    curl -s http://localhost:1111/api/config | python3 -m json.tool

    You should see your instance configuration as JSON. If you see an error, welcome to your first Sanctum debugging session. There will be others.

If you plan to run VM workloads (agent orchestration, knowledge graph), set up the Ubuntu VM. This is where the system goes from “neat haus automation project” to “wait, you’re running a knowledge graph in a virtual machine inside a Mac Mini?”

  1. Create the VM in UTM.

    Use the settings from the Requirements page. Install Ubuntu 24.04 LTS with SSH enabled.

  2. Configure networking.

    The Mac needs to set the bridge IP each time the VM starts. This is handled by the UTM autostart LaunchAgent, which runs:

    Terminal window
    sudo ifconfig bridge100 10.10.10.1/24

    A sudoers entry at /etc/sudoers.d/vmnet-bridge allows this without a password prompt.

  3. Set the VM’s static IP.

    Inside the VM, configure a static IP of 10.10.10.10 on the vmnet interface using netplan or your preferred method.

  4. Test connectivity.

    Terminal window
    # From Mac
    # From VM
    ping 10.10.10.1

With the base installation complete, proceed to First Run to verify everything is working and complete initial setup. This is the moment of truth. Deep breath.