Back to portfolio
PHYSICAL LAYER · macOS · launchd

Production Host

Everything you've read about runs on a single Mac mini sitting in my home office. Eleven launchd-managed services behind nginx with Let's Encrypt. PostgreSQL + Redis. Tailscale to a Synology NAS for the third leg of 3-2-1 backup. No Kubernetes. No serverless. Just disciplined Unix.

The host stack — bottom to top

Hardware → OS → process supervisor → reverse proxy → services → external networks. Nothing magic.

Why one box

The whole system runs on a single mini because — at the volume I serve — that's the right answer. No queues piling up. Latency from any service to Postgres is a Unix domain socket. The cost of a failover region for a portfolio site is silly. The cost of explaining a multi-region architecture for a portfolio site is sillier.

When the box becomes the bottleneck — and not before — the next move is a second mini in failover, not a re-platform. The deployment pipeline already handles that: rsync to a second host, kickstart launchd, swap nginx upstreams.

Service rack — what's listening

Live launchd jobs. Each LED matches the live status; amber means a known transitional state.

:443 → :80
nginxSSL · Let's Encrypt · CSP
:8000
career-botcom.coreyscherrer.career-bot
:8001
fal-appcom.coreyscherrer.fal-app
:8003
contact-apicom.coreyscherrer.contact-api
:8004
resume-buildercom.coreyscherrer.resume-builder
:8006
blog-publiccom.coreyscherrer.blog-public
:8007
blog-admincom.coreyscherrer.blog-admin
:5009
memory-archivecom.coreyscherrer.memory-archive-web · 30+ MCP tools
:5014
morning-briefcom.coreyscherrer.morning-brief · 6:30 AM digest
:5015
prototype-studiocom.coreyscherrer.prototype-studio · internal sandbox
:5016
discothequecom.coreyscherrer.discotheque · media surface
:5017
personal-assistantcom.coreyscherrer.personal-assistant · APScheduler daemon
:5432
postgresqlshared · brokered by docs/architecture/DATABASE_OWNERSHIP.md
:6379
redisqueues · caches · transient state

Operational primitives

launchd, not systemd
macOS-native
Every service is a com.coreyscherrer.<name> plist under /Library/LaunchDaemons/. Restart with sudo launchctl kickstart -k system/com.coreyscherrer.<name>. Cron-style work (orphan audits, weekly learning agent, NAS health-check) runs as scheduled launchd jobs.
nginx + Let's Encrypt
strict CSP
SSL terminates at nginx. Per-route auth gating for the Memory Archive admin surface. CSP forbids third-party scripts — vendor libs are self-hosted so the policy doesn't have escape hatches.
PostgreSQL — single source of truth
brokered ownership
One Postgres backs Career Bot, Blog, Resume Builder, Memory Archive, KG, and Continuous Learning Agent. Database ownership is documented; no service writes outside its lane. Database Agent enforces this on every schema diff.
Redis — queues + caching
independent of Postgres
Job queue for the Resume Builder PDF pipeline; rate-limit + state cache for Career Bot. A slow LLM call never blocks transactional reads because they don't share a tier.
Tailscale + NAS — 3-2-1 backup
DS918+ over SMB
Local snapshots + Tailscale-mounted Synology NAS form the third leg of 3-2-1 backup. Daily NAS health-check posts to Slack. Off-host = different failure domain.
Service mesh via Memory Archive
observable from one place
Every service registers itself in MA (service_route, service_get). Cross-service calls discover each other from a single source; the live agentic-topology view reads the same registry.

When something goes wrong

A short, deliberate playbook. Most pages call the same five primitives.

1
Cross-service health probe first
curl :port/ for all 11 — never just the one in question. Catches regressions where a shared-package change broke a service you didn't think you'd touched.
2
launchd state inspection
sudo launchctl print system/com.coreyscherrer.<svc> — look for state = spawn scheduled (throttled) or non-zero last exit code.
3
Kickstart to break throttle
sudo launchctl kickstart -k system/com.coreyscherrer.<svc>. The -k kills then respawns; clears the throttle that builds up after rapid restarts.
4
Tail the right log
tail -f /var/www/coreyscherrer/<svc>/logs/web-service-error.log. Per-service log directories so the noise of one doesn't drown another.
5
Rollback is a deploy
Production is rsync'd from the dev tree. To roll back, check out the prior commit in dev and re-run dev-ops.sh deploy <svc>. No special "rollback" tool — same pipeline, opposite direction.

More of the system

The host is the foundation; the brain is upstairs. See how Memory Archive turns this rack into something more than a process supervisor, or watch the live system topology.