# Infrastructure Runbook

> Last Verified: 2026-02-17 | Owner: John

# Runbook: Local Infrastructure

**Platform:** Mac Studio M3 Ultra, 96GB RAM, macOS
**Services:** Docker containers, LaunchAgents, Cloudflare tunnels

---

## Docker Services

### Status Check
```bash
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
```

### Services
| Container | Image | Port | Health |
|-----------|-------|------|--------|
| mattermost | mattermost/mattermost-enterprise | 8065 | healthcheck |
| mattermost-db | postgres:13 | 5432 (internal) | — |
| planka | ghcr.io/plankanban/planka | 3100→1337 | healthcheck |
| planka-db | postgres:15-alpine | 5433 (internal) | healthcheck |
| documenso | documenso/documenso | 3003 | — |
| documenso-db | postgres | 5434 (internal) | healthcheck |
| bookstack | lscr.io/linuxserver/bookstack | 6875→80 | — |
| bookstack_db | lscr.io/linuxserver/mariadb | 3306 (internal) | — |

### Restart a container
```bash
docker restart <container_name>
# Example: docker restart mattermost
```

### Restart all
```bash
# Mattermost stack
cd ~/system/services/mattermost && docker compose down && docker compose up -d

# Planka stack
cd ~/system/services/planka && docker compose down && docker compose up -d

# Documenso
cd ~/system/services/documenso && docker compose down && docker compose up -d

# BookStack
cd ~/system/services/bookstack && docker compose down && docker compose up -d
```

### View logs
```bash
docker logs <container_name> --tail 50
docker logs <container_name> -f  # follow
```

### Disk cleanup (if disk >90%)
```bash
docker system prune -f            # Remove unused images, containers, networks
docker volume prune -f             # Remove unused volumes (CAREFUL: data loss)
```

---

## Cloudflare Tunnels

### Config
```bash
cat ~/.cloudflared/config.yml
```

### Routes
| Hostname | Target | Service |
|----------|--------|---------|
| mm.basicconsulting.no | localhost:8065 | Mattermost |
| boards.basicconsulting.no | localhost:3100 | Planka |
| sign.basicconsulting.no | localhost:3003 | Documenso |

### Status
```bash
cloudflared tunnel info mattermost
```

### Restart tunnel
```bash
# Tunnel runs as LaunchAgent
launchctl unload ~/Library/LaunchAgents/com.cloudflare.tunnel.plist
launchctl load ~/Library/LaunchAgents/com.cloudflare.tunnel.plist
```

---

## LaunchAgents (Daemons)

### List all custom daemons
```bash
launchctl list | grep -E "com\.(john|edita|cloudflare)"
```

### Expected daemons
| Daemon | Interval | Location |
|--------|----------|----------|
| com.john.ops-agent | 5 min | ~/Library/LaunchAgents/ |
| com.edita.autowork | 30 min | ~/Library/LaunchAgents/ |
| com.john.mc-dashboard | always | ~/Library/LaunchAgents/ |
| com.john.mc-session-worker | on events | ~/Library/LaunchAgents/ |

### Load/unload
```bash
launchctl load ~/Library/LaunchAgents/<plist-name>.plist
launchctl unload ~/Library/LaunchAgents/<plist-name>.plist
```

---

## Ollama (Local AI)

### Status
```bash
curl -s http://localhost:11434/api/tags | python3 -c "import sys,json; [print(m['name']) for m in json.load(sys.stdin)['models']]"
```

### Models
| Model | Size | Use |
|-------|------|-----|
| llama3.1:8b | 5GB | Fast classification (ops-agent) |
| qwen2.5-coder:32b | 19GB | Code generation, contextual responses |
| llama3.1:70b | 40GB | Research, writing |

### Restart Ollama
```bash
# Ollama runs as macOS app
killall ollama 2>/dev/null
open -a Ollama
```

---

## Mission Control Dashboard

### Status
```bash
curl -s http://localhost:3030 | head -1
```

### Restart
```bash
launchctl unload ~/Library/LaunchAgents/com.john.mc-dashboard.plist
launchctl load ~/Library/LaunchAgents/com.john.mc-dashboard.plist
```

---

## Full Health Check

```bash
# Human-readable
node ~/system/tools/health-check.js

# JSON (programmatic)
node ~/system/tools/health-check.js --json

# Quick (HTTP only)
node ~/system/tools/health-check.js --quick
```

---

## After System Reboot

All LaunchAgents with `RunAtLoad: true` start automatically. Verify:

```bash
# 1. Check Docker is running
docker ps

# 2. Check all daemons
launchctl list | grep -E "com\.(john|edita|cloudflare)"

# 3. Run health check
node ~/system/tools/health-check.js

# 4. If anything missing, load it
launchctl load ~/Library/LaunchAgents/<missing>.plist
```

---

**Created:** 2026-02-10
**Last Updated:** 2026-02-10