mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 23:01:09 +02:00
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:
parent
2164d4afa0
commit
93060dc335
7 changed files with 843 additions and 0 deletions
241
scripts/mac-mini/README.md
Normal file
241
scripts/mac-mini/README.md
Normal 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
115
scripts/mac-mini/health-check.sh
Executable 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
69
scripts/mac-mini/restart.sh
Executable 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"
|
||||
201
scripts/mac-mini/setup-autostart.sh
Executable file
201
scripts/mac-mini/setup-autostart.sh
Executable 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
65
scripts/mac-mini/startup.sh
Executable 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
129
scripts/mac-mini/status.sh
Executable 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
23
scripts/mac-mini/stop.sh
Executable 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 ""
|
||||
Loading…
Add table
Add a link
Reference in a new issue