Security
Somewhere a security auditor is reading this page and trying to decide whether to be impressed or alarmed that this level of defense-in-depth has been applied to a house. The answer is both. It should be both.

Defense in Depth
Section titled “Defense in Depth”Sanctum uses seven layers of security, because if action movies have taught us anything, it’s that every single layer will eventually be breached by someone with enough determination. The game isn’t making the wall perfect — it’s making the attacker tired.
- Network isolation — VM has no internet access (host-only networking)
- Firewall — pf rules on LAN interface block unauthorized port access
- SSH hardening — Key-only auth, no root login, AllowUsers restriction
- Encrypted secrets — SOPS+age on VM, macOS Keychain on Mac
- Automatic rotation — 8 secrets rotated monthly
- Service binding — Services bound to specific interfaces (not 0.0.0.0)
- PII anonymization — Personal data scrubbed from all external LLM requests
pf Firewall
Section titled “pf Firewall”Rules in /etc/pf.anchors/sanctum block external access to internal ports on the LAN interface (en1):
Blocked ports include: gateway (1977), dashboard (1111), XTTS (8008), MLX (1337), Firewalla bridge (1984), and others.
The philosophy: if a service doesn’t need to talk to the LAN, it doesn’t get to. Every open port is a decision, not a default.
Secret Rotation
Section titled “Secret Rotation”Monthly via com.sanctum.rotate-secrets LaunchAgent (1st of month, 3:30am).
Rotates 8 secrets:
- Home Assistant main + Windu tokens
- Firewalla bridge token
- Gateway token
- Network control token
- Backup encryption key
- OpenRouter API key
- Deepgram API key
Plus verifies the Cloudflare tunnel token.
# Manual rotationbash ~/Backups/rotate-secrets.sh
# Dry runbash ~/Backups/rotate-secrets.sh --dry-runSSH Hardening
Section titled “SSH Hardening”Both Mac and VM have hardened SSH configs:
- Key-only authentication (no passwords)
- No root login
- AllowUsers restriction
- Post-quantum key exchange (on VM)
Yes, post-quantum key exchange. For a VM that can’t access the internet. Because when the quantum computers arrive, they’ll find this particular door already bolted from the inside.
VM Isolation
Section titled “VM Isolation”The Ubuntu VM runs on host-only networking (bridge100, 10.10.10.0/24). It can only reach the Mac at 10.10.10.1 — no direct internet access. All external communication goes through the Mac.
This means a compromised VM can’t phone haus, can’t exfiltrate data, can’t join a botnet. The worst it can do is send a strongly worded message to the Mac, which is already watching.
Secrets Storage
Section titled “Secrets Storage”| Location | Purpose |
|---|---|
| macOS Keychain | Runtime token access |
| 1Password | Backup copies of all secrets |
| VM SOPS (age) | Encrypted secrets for VM services |
Secrets are never stored in config files, git repos, or environment variables on disk.
PII Anonymization
Section titled “PII Anonymization”All requests routed to external LLM providers (OpenRouter) pass through a Presidio-based anonymization layer before leaving the network. This ensures personal data never reaches third-party inference APIs.
Your AI agents know your name. The cloud doesn’t need to.
How It Works
Section titled “How It Works”The Sanctum Proxy (port 4040) handles all LLM request routing. When a request targets an OpenRouter model — either directly or via fallback routing — the proxy:
- Extracts text from user and assistant messages (system prompts are left untouched)
- Sends the text to a local Presidio analyzer container to detect PII entities
- Sends detected entities to a local Presidio anonymizer container to replace them with placeholders
- Forwards the scrubbed request to the external provider
- De-anonymizes the response before returning it to the caller
What Gets Scrubbed
Section titled “What Gets Scrubbed”| Entity | Example | Replacement |
|---|---|---|
| Person names | John Smith | <PERSON> |
| Email addresses | [email protected] | <EMAIL_ADDRESS> |
| Phone numbers | 514-555-1234 | <PHONE_NUMBER> |
| Credit cards | 4111-1111-1111-1111 | <CREDIT_CARD> |
| SSN / bank numbers | 123-45-6789 | <US_SSN> |
Only entities above 0.7 confidence score are anonymized. IP addresses, locations, and code identifiers are intentionally excluded to avoid breaking technical context.
What Is Not Affected
Section titled “What Is Not Affected”- Anthropic (Claude) — direct API, no PII scrubbing (trusted provider, privacy policy reviewed)
- Local models (LM Studio, Council-27B MLX) — never leave the network
- Gemini — routed via Google AI Studio API (separate trust decision)
- System prompts — contain instructions, not personal data
Architecture
Section titled “Architecture”Client → Sanctum Proxy (port 4040) → Provider | | +-- Presidio Analyzer (Docker, port 5002) +-- Presidio Anonymizer (Docker, port 5001) | | +-- PII scrubbed before exit ◄──────────+ +-- PII restored on responsePresidio Containers
Section titled “Presidio Containers”The analyzer and anonymizer run as local Docker containers, bound to localhost only:
# Check statusdocker ps --filter name=presidio
# Restart if neededdocker restart presidio-analyzer presidio-anonymizer