feat(mac-mini): add auto-start and management scripts

- setup-autostart.sh: Configure launchd services for boot
- startup.sh: Main startup script (waits for Docker, starts containers)
- health-check.sh: Check all services (runs every 5 min)
- status.sh: Full system status overview
- restart.sh: Restart containers (with --pull and --force options)
- stop.sh: Stop all containers gracefully
- README.md: Complete documentation

Includes optional ntfy.sh push notifications for health check failures.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2026-01-23 11:48:24 +01:00
parent 2164d4afa0
commit 93060dc335
7 changed files with 843 additions and 0 deletions

241
scripts/mac-mini/README.md Normal file
View file

@ -0,0 +1,241 @@
# Mac Mini Server Scripts
Scripts for managing the ManaCore production environment on Mac Mini.
## Quick Start (After System Update)
```bash
# 1. SSH into Mac Mini (from your local machine)
ssh mac-mini
# 2. Navigate to project
cd ~/projects/manacore-monorepo
# 3. Setup auto-start (only needed once)
./scripts/mac-mini/setup-autostart.sh
# 4. Check status
./scripts/mac-mini/status.sh
```
## Scripts Overview
| Script | Purpose |
|--------|---------|
| `setup-autostart.sh` | Configure automatic startup on boot (run once) |
| `startup.sh` | Main startup script (called by launchd) |
| `health-check.sh` | Check all services health |
| `status.sh` | Show full system status |
| `restart.sh` | Restart all Docker containers |
| `stop.sh` | Stop all Docker containers |
| `deploy.sh` | Pull latest images and deploy |
## First-Time Setup
### 1. Prerequisites on Mac Mini
```bash
# Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install required tools
brew install cloudflared git docker
# Install Docker Desktop
# Download from: https://www.docker.com/products/docker-desktop/
```
### 2. Clone Repository
```bash
mkdir -p ~/projects
cd ~/projects
git clone https://github.com/Memo-2023/manacore-monorepo.git
cd manacore-monorepo
```
### 3. Configure Cloudflare Tunnel
```bash
# Login to Cloudflare
cloudflared tunnel login
# The tunnel is already created (ID: bb0ea86d-8253-4a54-838b-107bb7945be9)
# Credentials should be at: ~/.cloudflared/bb0ea86d-8253-4a54-838b-107bb7945be9.json
```
### 4. Configure Environment
```bash
# Copy and edit the environment file
cp .env.macmini.example .env.macmini
nano .env.macmini
```
### 5. Enable Auto-Start
```bash
# This sets up all launchd services
./scripts/mac-mini/setup-autostart.sh
```
### 6. Configure Docker Desktop
Open Docker Desktop and enable:
- **Settings > General > Start Docker Desktop when you sign in**
## Daily Operations
### Check Status
```bash
./scripts/mac-mini/status.sh
```
### Run Health Check
```bash
./scripts/mac-mini/health-check.sh
```
### Restart Services
```bash
# Normal restart
./scripts/mac-mini/restart.sh
# Pull latest images and restart
./scripts/mac-mini/restart.sh --pull
# Force recreate containers
./scripts/mac-mini/restart.sh --force
```
### View Logs
```bash
# Startup log
tail -f /tmp/manacore-startup.log
# Health check log
tail -f /tmp/manacore-health.log
# Cloudflare tunnel log
tail -f /tmp/cloudflared.log
# Specific container logs
docker logs -f mana-core-auth
docker logs -f chat-backend
```
### Stop Services
```bash
./scripts/mac-mini/stop.sh
```
## LaunchD Services
Three services are configured to run automatically:
| Service | Label | Purpose |
|---------|-------|---------|
| Cloudflared | `com.cloudflare.cloudflared` | Tunnel to Cloudflare |
| Docker Startup | `com.manacore.docker-startup` | Start containers on boot |
| Health Check | `com.manacore.health-check` | Check every 5 minutes |
### Manual Service Control
```bash
# Check status
launchctl list | grep -E 'cloudflare|manacore'
# Restart a service
launchctl kickstart -k gui/$(id -u)/com.manacore.docker-startup
# Stop a service
launchctl unload ~/Library/LaunchAgents/com.manacore.docker-startup.plist
# Start a service
launchctl load ~/Library/LaunchAgents/com.manacore.docker-startup.plist
```
## Troubleshooting
### Docker not starting
```bash
# Check if Docker Desktop is running
docker info
# Start Docker Desktop manually
open -a Docker
```
### Cloudflare tunnel not connecting
```bash
# Check cloudflared status
pgrep -x cloudflared
# View tunnel logs
tail -50 /tmp/cloudflared.log
# Restart tunnel
launchctl kickstart -k gui/$(id -u)/com.cloudflare.cloudflared
```
### Container health check failing
```bash
# Check specific container
docker logs <container-name>
# Restart specific container
docker restart <container-name>
# Check database connectivity
docker exec manacore-postgres pg_isready -U postgres
```
### Services not starting on boot
```bash
# Re-run setup
./scripts/mac-mini/setup-autostart.sh
# Check launchd errors
launchctl error <exit-code>
# Verify plist files
plutil ~/Library/LaunchAgents/com.manacore.*.plist
```
## Push Notifications (Optional)
To receive notifications when health checks fail:
1. Create a topic at [ntfy.sh](https://ntfy.sh/)
2. Add to your shell profile:
```bash
export NTFY_TOPIC=your-topic-name
```
3. Subscribe on your phone using the ntfy app
## URLs
Once running, services are available at:
| Service | URL |
|---------|-----|
| Dashboard | https://mana.how |
| Auth API | https://auth.mana.how |
| Chat | https://chat.mana.how |
| Chat API | https://chat-api.mana.how |
| Todo | https://todo.mana.how |
| Todo API | https://todo-api.mana.how |
| Calendar | https://calendar.mana.how |
| Calendar API | https://calendar-api.mana.how |
| Clock | https://clock.mana.how |
| Clock API | https://clock-api.mana.how |
| SSH | ssh mac-mini (via cloudflared) |

115
scripts/mac-mini/health-check.sh Executable file
View file

@ -0,0 +1,115 @@
#!/bin/bash
# ManaCore Health Check Script
# Checks all services and optionally sends notifications
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Colors for terminal output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Track failures
FAILURES=()
check_service() {
local name=$1
local url=$2
local timeout=${3:-5}
local status=$(curl -s -o /dev/null -w "%{http_code}" --max-time "$timeout" "$url" 2>/dev/null)
if [ "$status" = "200" ]; then
echo -e " ${GREEN}[OK]${NC} $name"
return 0
else
echo -e " ${RED}[FAIL]${NC} $name (HTTP $status)"
FAILURES+=("$name")
return 1
fi
}
echo ""
echo "=== ManaCore Health Check ==="
echo "Time: $(date)"
echo ""
echo "Infrastructure:"
check_service "PostgreSQL" "http://localhost:5432" 2 || true # Will fail but that's ok for TCP
# Check postgres via docker
if docker exec manacore-postgres pg_isready -U postgres >/dev/null 2>&1; then
echo -e " ${GREEN}[OK]${NC} PostgreSQL"
else
echo -e " ${RED}[FAIL]${NC} PostgreSQL"
FAILURES+=("PostgreSQL")
fi
# Check redis via docker
if docker exec manacore-redis redis-cli ping >/dev/null 2>&1; then
echo -e " ${GREEN}[OK]${NC} Redis"
else
echo -e " ${RED}[FAIL]${NC} Redis"
FAILURES+=("Redis")
fi
echo ""
echo "Auth & Dashboard:"
check_service "Auth API" "http://localhost:3001/api/v1/health"
check_service "Dashboard Web" "http://localhost:5173/health"
echo ""
echo "Chat:"
check_service "Chat Backend" "http://localhost:3002/api/v1/health"
check_service "Chat Web" "http://localhost:3000/health"
echo ""
echo "Todo:"
check_service "Todo Backend" "http://localhost:3018/api/health"
check_service "Todo Web" "http://localhost:5188/health"
echo ""
echo "Calendar:"
check_service "Calendar Backend" "http://localhost:3016/api/v1/health"
check_service "Calendar Web" "http://localhost:5186/health"
echo ""
echo "Clock:"
check_service "Clock Backend" "http://localhost:3017/api/v1/health"
check_service "Clock Web" "http://localhost:5187/health"
echo ""
echo "Cloudflare Tunnel:"
if pgrep -x "cloudflared" >/dev/null; then
echo -e " ${GREEN}[OK]${NC} cloudflared running"
else
echo -e " ${RED}[FAIL]${NC} cloudflared not running"
FAILURES+=("cloudflared")
fi
echo ""
echo "=== Summary ==="
if [ ${#FAILURES[@]} -eq 0 ]; then
echo -e "${GREEN}All services healthy!${NC}"
exit 0
else
echo -e "${RED}Failed services (${#FAILURES[@]}):${NC}"
for f in "${FAILURES[@]}"; do
echo " - $f"
done
# Send notification if ntfy is configured
NTFY_TOPIC="${NTFY_TOPIC:-}"
if [ -n "$NTFY_TOPIC" ]; then
FAILED_LIST=$(printf '%s, ' "${FAILURES[@]}")
curl -s -d "ManaCore Health Check Failed: ${FAILED_LIST%, }" \
-H "Title: Mac Mini Alert" \
-H "Priority: high" \
-H "Tags: warning" \
"https://ntfy.sh/$NTFY_TOPIC" >/dev/null 2>&1 || true
fi
exit 1
fi

69
scripts/mac-mini/restart.sh Executable file
View file

@ -0,0 +1,69 @@
#!/bin/bash
# ManaCore Mac Mini Restart Script
# Restarts all Docker containers gracefully
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
COMPOSE_FILE="$PROJECT_ROOT/docker-compose.macmini.yml"
ENV_FILE="$PROJECT_ROOT/.env.macmini"
echo "=== ManaCore Restart ==="
echo ""
# Check for flags
PULL_IMAGES=false
FORCE_RECREATE=false
while [[ "$#" -gt 0 ]]; do
case $1 in
--pull) PULL_IMAGES=true ;;
--force) FORCE_RECREATE=true ;;
--help)
echo "Usage: restart.sh [OPTIONS]"
echo ""
echo "Options:"
echo " --pull Pull latest images before restart"
echo " --force Force recreate containers"
echo " --help Show this help"
exit 0
;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
shift
done
cd "$PROJECT_ROOT"
# Optional: Pull latest images
if [ "$PULL_IMAGES" = true ]; then
echo "Pulling latest images..."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" pull
echo ""
fi
# Stop containers
echo "Stopping containers..."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down
echo ""
echo "Starting containers..."
if [ "$FORCE_RECREATE" = true ]; then
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --force-recreate
else
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d
fi
echo ""
echo "Waiting for services to start (30s)..."
sleep 30
echo ""
echo "=== Container Status ==="
docker compose -f "$COMPOSE_FILE" ps
echo ""
echo "Running health check..."
"$SCRIPT_DIR/health-check.sh"

View file

@ -0,0 +1,201 @@
#!/bin/bash
# ManaCore Mac Mini Auto-Start Setup
# Run this ONCE on the Mac Mini to configure automatic startup on boot
#
# This sets up:
# 1. Cloudflared tunnel (via launchd)
# 2. Docker containers (via launchd, after Docker starts)
# 3. Periodic health checks (every 5 minutes)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
USER_HOME="$HOME"
LAUNCH_AGENTS_DIR="$USER_HOME/Library/LaunchAgents"
echo "=== ManaCore Mac Mini Auto-Start Setup ==="
echo ""
echo "Project root: $PROJECT_ROOT"
echo "User: $(whoami)"
echo ""
# Create LaunchAgents directory
mkdir -p "$LAUNCH_AGENTS_DIR"
# Make scripts executable
chmod +x "$SCRIPT_DIR/startup.sh"
chmod +x "$SCRIPT_DIR/health-check.sh"
chmod +x "$SCRIPT_DIR/setup-cloudflared-service.sh"
# ============================================
# 1. Cloudflared Tunnel Service
# ============================================
echo "=== Setting up Cloudflared Service ==="
TUNNEL_ID="bb0ea86d-8253-4a54-838b-107bb7945be9"
CLOUDFLARED_CONFIG="$PROJECT_ROOT/cloudflared-config.yml"
CREDENTIALS_FILE="$USER_HOME/.cloudflared/${TUNNEL_ID}.json"
# Check if credentials exist
if [ ! -f "$CREDENTIALS_FILE" ]; then
echo ""
echo "WARNING: Cloudflare credentials not found!"
echo "Run these commands first:"
echo " cloudflared tunnel login"
echo " cloudflared tunnel create mana-server"
echo ""
echo "Then run this script again."
echo ""
else
# Create cloudflared plist
CLOUDFLARED_PLIST="$LAUNCH_AGENTS_DIR/com.cloudflare.cloudflared.plist"
cat > "$CLOUDFLARED_PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.cloudflare.cloudflared</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/cloudflared</string>
<string>tunnel</string>
<string>--config</string>
<string>${CLOUDFLARED_CONFIG}</string>
<string>run</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/cloudflared.log</string>
<key>StandardErrorPath</key>
<string>/tmp/cloudflared.error.log</string>
</dict>
</plist>
EOF
echo "Created: $CLOUDFLARED_PLIST"
# Load cloudflared service
launchctl unload "$CLOUDFLARED_PLIST" 2>/dev/null || true
launchctl load "$CLOUDFLARED_PLIST"
echo "Cloudflared service loaded"
fi
# ============================================
# 2. ManaCore Docker Startup Service
# ============================================
echo ""
echo "=== Setting up Docker Startup Service ==="
DOCKER_PLIST="$LAUNCH_AGENTS_DIR/com.manacore.docker-startup.plist"
cat > "$DOCKER_PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.manacore.docker-startup</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>${SCRIPT_DIR}/startup.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>0</integer>
<key>StandardOutPath</key>
<string>/tmp/manacore-startup.log</string>
<key>StandardErrorPath</key>
<string>/tmp/manacore-startup.error.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
</dict>
</plist>
EOF
echo "Created: $DOCKER_PLIST"
# Load docker startup service
launchctl unload "$DOCKER_PLIST" 2>/dev/null || true
launchctl load "$DOCKER_PLIST"
echo "Docker startup service loaded"
# ============================================
# 3. Health Check Service (every 5 minutes)
# ============================================
echo ""
echo "=== Setting up Health Check Service ==="
HEALTH_PLIST="$LAUNCH_AGENTS_DIR/com.manacore.health-check.plist"
cat > "$HEALTH_PLIST" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.manacore.health-check</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>${SCRIPT_DIR}/health-check.sh</string>
</array>
<key>StartInterval</key>
<integer>300</integer>
<key>StandardOutPath</key>
<string>/tmp/manacore-health.log</string>
<key>StandardErrorPath</key>
<string>/tmp/manacore-health.error.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
</dict>
</plist>
EOF
echo "Created: $HEALTH_PLIST"
# Load health check service
launchctl unload "$HEALTH_PLIST" 2>/dev/null || true
launchctl load "$HEALTH_PLIST"
echo "Health check service loaded (runs every 5 minutes)"
# ============================================
# Summary
# ============================================
echo ""
echo "=========================================="
echo " Auto-Start Setup Complete!"
echo "=========================================="
echo ""
echo "Services configured:"
echo " 1. Cloudflared tunnel (starts on login)"
echo " 2. Docker containers (starts on login)"
echo " 3. Health checks (every 5 minutes)"
echo ""
echo "Log files:"
echo " /tmp/cloudflared.log"
echo " /tmp/manacore-startup.log"
echo " /tmp/manacore-health.log"
echo ""
echo "Manual commands:"
echo " Check status: launchctl list | grep -E 'cloudflare|manacore'"
echo " View logs: tail -f /tmp/manacore-startup.log"
echo " Health check: $SCRIPT_DIR/health-check.sh"
echo " Restart docker: launchctl kickstart -k gui/\$(id -u)/com.manacore.docker-startup"
echo ""
echo "IMPORTANT: Make sure Docker Desktop is set to start on login!"
echo " Docker Desktop > Settings > General > 'Start Docker Desktop when you sign in'"
echo ""
# Optional: Configure notifications
echo "Optional: To enable push notifications on failures, set:"
echo " export NTFY_TOPIC=your-topic-name"
echo " in your .zshrc or .bashrc"
echo ""

65
scripts/mac-mini/startup.sh Executable file
View file

@ -0,0 +1,65 @@
#!/bin/bash
# ManaCore Mac Mini Startup Script
# This script is called by launchd on boot to start all services
set -e
LOG_FILE="/tmp/manacore-startup.log"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
COMPOSE_FILE="$PROJECT_ROOT/docker-compose.macmini.yml"
ENV_FILE="$PROJECT_ROOT/.env.macmini"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=== ManaCore Startup Script ==="
log "Project root: $PROJECT_ROOT"
# Wait for Docker to be ready
log "Waiting for Docker..."
MAX_WAIT=120
WAITED=0
while ! docker info >/dev/null 2>&1; do
sleep 2
WAITED=$((WAITED + 2))
if [ $WAITED -ge $MAX_WAIT ]; then
log "ERROR: Docker not available after ${MAX_WAIT}s"
exit 1
fi
done
log "Docker is ready (waited ${WAITED}s)"
# Check if env file exists
if [ ! -f "$ENV_FILE" ]; then
log "ERROR: Environment file not found: $ENV_FILE"
exit 1
fi
# Pull latest images (optional, comment out for faster startup)
# log "Pulling latest images..."
# docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" pull
# Start containers
log "Starting Docker containers..."
cd "$PROJECT_ROOT"
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d
# Wait for services to initialize
log "Waiting 45s for services to initialize..."
sleep 45
# Create databases if they don't exist
log "Ensuring databases exist..."
docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE manacore_auth;" 2>/dev/null || true
docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE chat;" 2>/dev/null || true
docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE todo;" 2>/dev/null || true
docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE calendar;" 2>/dev/null || true
docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE clock;" 2>/dev/null || true
# Run health checks
log "Running health checks..."
"$SCRIPT_DIR/health-check.sh" >> "$LOG_FILE" 2>&1
log "=== Startup Complete ==="

129
scripts/mac-mini/status.sh Executable file
View file

@ -0,0 +1,129 @@
#!/bin/bash
# ManaCore Mac Mini Status Overview
# Shows the current state of all services
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
COMPOSE_FILE="$PROJECT_ROOT/docker-compose.macmini.yml"
ENV_FILE="$PROJECT_ROOT/.env.macmini"
# Colors
BOLD='\033[1m'
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo ""
echo -e "${BOLD}=========================================="
echo -e " ManaCore Mac Mini Status"
echo -e "==========================================${NC}"
echo ""
echo -e "${BLUE}Time:${NC} $(date)"
echo -e "${BLUE}Hostname:${NC} $(hostname)"
echo -e "${BLUE}Uptime:${NC} $(uptime | sed 's/.*up //' | sed 's/,.*//')"
echo ""
# ============================================
# LaunchD Services
# ============================================
echo -e "${BOLD}LaunchD Services:${NC}"
check_launchd() {
local label=$1
local name=$2
if launchctl list | grep -q "$label"; then
echo -e " ${GREEN}[Running]${NC} $name"
else
echo -e " ${RED}[Stopped]${NC} $name"
fi
}
check_launchd "com.cloudflare.cloudflared" "Cloudflared Tunnel"
check_launchd "com.manacore.docker-startup" "Docker Startup"
check_launchd "com.manacore.health-check" "Health Check (5min)"
# ============================================
# Docker Status
# ============================================
echo ""
echo -e "${BOLD}Docker Status:${NC}"
if docker info >/dev/null 2>&1; then
echo -e " ${GREEN}[Running]${NC} Docker Desktop"
# Container count
RUNNING=$(docker ps -q | wc -l | tr -d ' ')
TOTAL=$(docker ps -aq | wc -l | tr -d ' ')
echo -e " ${BLUE}Containers:${NC} $RUNNING running / $TOTAL total"
else
echo -e " ${RED}[Stopped]${NC} Docker Desktop"
fi
# ============================================
# Container Details
# ============================================
echo ""
echo -e "${BOLD}Containers:${NC}"
if docker info >/dev/null 2>&1; then
# Format: NAME | STATUS | PORTS
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | while read line; do
if echo "$line" | grep -q "Up"; then
echo -e " ${GREEN}$line${NC}"
elif echo "$line" | grep -q "NAMES"; then
echo -e " ${BOLD}$line${NC}"
else
echo -e " ${RED}$line${NC}"
fi
done
fi
# ============================================
# Network/Tunnel Status
# ============================================
echo ""
echo -e "${BOLD}Network:${NC}"
if pgrep -x "cloudflared" >/dev/null; then
echo -e " ${GREEN}[Connected]${NC} Cloudflare Tunnel"
# Check external connectivity
if curl -s --max-time 3 https://mana.how >/dev/null 2>&1; then
echo -e " ${GREEN}[Reachable]${NC} https://mana.how"
else
echo -e " ${YELLOW}[Unknown]${NC} https://mana.how (check from external)"
fi
else
echo -e " ${RED}[Disconnected]${NC} Cloudflare Tunnel"
fi
# ============================================
# Disk Usage
# ============================================
echo ""
echo -e "${BOLD}Disk Usage:${NC}"
df -h / | tail -1 | awk '{print " System: " $3 " used / " $2 " total (" $5 " full)"}'
if docker info >/dev/null 2>&1; then
DOCKER_DISK=$(docker system df --format "{{.Size}}" 2>/dev/null | head -1)
echo " Docker: $DOCKER_DISK"
fi
# ============================================
# Recent Logs
# ============================================
echo ""
echo -e "${BOLD}Recent Activity:${NC}"
if [ -f /tmp/manacore-health.log ]; then
echo " Last health check:"
tail -3 /tmp/manacore-health.log | sed 's/^/ /'
fi
echo ""
echo -e "${BLUE}Commands:${NC}"
echo " Health check: ./scripts/mac-mini/health-check.sh"
echo " Restart all: ./scripts/mac-mini/restart.sh"
echo " View logs: tail -f /tmp/manacore-startup.log"
echo ""

23
scripts/mac-mini/stop.sh Executable file
View file

@ -0,0 +1,23 @@
#!/bin/bash
# ManaCore Mac Mini Stop Script
# Stops all Docker containers
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
COMPOSE_FILE="$PROJECT_ROOT/docker-compose.macmini.yml"
ENV_FILE="$PROJECT_ROOT/.env.macmini"
echo "=== Stopping ManaCore Services ==="
echo ""
cd "$PROJECT_ROOT"
echo "Stopping Docker containers..."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down
echo ""
echo "Containers stopped."
echo ""
echo "Note: Cloudflare tunnel is still running (managed by launchd)"
echo "To stop tunnel: launchctl unload ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist"
echo ""