mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 17:41:09 +02:00
✨ feat(mac-mini): add stability improvements
High priority stability features: - Add all LaunchD plists to Git for version control - Handle crash-looping containers (Restarting status) in ensure-containers.sh - Add database backup script with daily/weekly rotation - Add Docker log rotation setup (50MB max, 3 files per container) New files: - scripts/mac-mini/backup-databases.sh - Daily pg_dump with rotation - scripts/mac-mini/setup-docker-logging.sh - Configure daemon.json - scripts/mac-mini/launchd/*.plist - All 8 LaunchD service configs - scripts/mac-mini/launchd/README.md - Documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
7d409465b6
commit
3de2f25552
12 changed files with 615 additions and 23 deletions
125
scripts/mac-mini/backup-databases.sh
Executable file
125
scripts/mac-mini/backup-databases.sh
Executable file
|
|
@ -0,0 +1,125 @@
|
|||
#!/bin/bash
|
||||
# ManaCore Database Backup Script
|
||||
# Creates daily backups of all PostgreSQL databases with rotation
|
||||
#
|
||||
# Retention policy:
|
||||
# - Daily backups: keep last 7 days
|
||||
# - Weekly backups: keep last 4 weeks (Sundays)
|
||||
#
|
||||
# Run via LaunchD daily at 3 AM
|
||||
|
||||
set -e
|
||||
|
||||
# Ensure PATH includes docker
|
||||
export PATH="/usr/local/bin:/opt/homebrew/bin:$PATH"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
BACKUP_DIR="/Volumes/ManaData/backups/postgres"
|
||||
LOG_FILE="/tmp/manacore-backup.log"
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
DAY_OF_WEEK=$(date +%u) # 1=Monday, 7=Sunday
|
||||
|
||||
# Load env for password
|
||||
if [ -f "$PROJECT_ROOT/.env.macmini" ]; then
|
||||
source "$PROJECT_ROOT/.env.macmini"
|
||||
fi
|
||||
|
||||
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-mana123}"
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Load notification config if exists
|
||||
if [ -f "$PROJECT_ROOT/.env.notifications" ]; then
|
||||
source "$PROJECT_ROOT/.env.notifications"
|
||||
fi
|
||||
|
||||
send_notification() {
|
||||
local message="$1"
|
||||
local priority="${2:-default}"
|
||||
|
||||
if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
|
||||
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||
-d "chat_id=${TELEGRAM_CHAT_ID}" \
|
||||
-d "text=${message}" \
|
||||
-d "parse_mode=HTML" \
|
||||
>/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Create backup directories
|
||||
mkdir -p "$BACKUP_DIR/daily"
|
||||
mkdir -p "$BACKUP_DIR/weekly"
|
||||
|
||||
log "=== ManaCore Database Backup ==="
|
||||
|
||||
# Check if postgres container is running
|
||||
if ! docker ps --format '{{.Names}}' | grep -q "mana-infra-postgres"; then
|
||||
log "ERROR: PostgreSQL container is not running"
|
||||
send_notification "🚨 <b>Backup Failed</b>\n\nPostgreSQL container not running" "high"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get list of databases (exclude templates and postgres)
|
||||
DATABASES=$(docker exec mana-infra-postgres psql -U postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname != 'postgres';" | tr -d ' ' | grep -v "^$")
|
||||
|
||||
log "Found databases: $(echo $DATABASES | tr '\n' ' ')"
|
||||
|
||||
BACKUP_COUNT=0
|
||||
BACKUP_SIZE=0
|
||||
FAILED_DBS=""
|
||||
|
||||
for DB in $DATABASES; do
|
||||
log "Backing up: $DB"
|
||||
BACKUP_FILE="$BACKUP_DIR/daily/${DB}_${DATE}.sql.gz"
|
||||
|
||||
# Create backup using pg_dump inside container, compress with gzip
|
||||
if docker exec mana-infra-postgres pg_dump -U postgres "$DB" 2>/dev/null | gzip > "$BACKUP_FILE"; then
|
||||
SIZE=$(ls -lh "$BACKUP_FILE" | awk '{print $5}')
|
||||
log " OK: $DB ($SIZE)"
|
||||
BACKUP_COUNT=$((BACKUP_COUNT + 1))
|
||||
BACKUP_SIZE=$((BACKUP_SIZE + $(stat -f%z "$BACKUP_FILE" 2>/dev/null || stat -c%s "$BACKUP_FILE" 2>/dev/null)))
|
||||
else
|
||||
log " FAILED: $DB"
|
||||
FAILED_DBS="$FAILED_DBS $DB"
|
||||
rm -f "$BACKUP_FILE" # Remove incomplete backup
|
||||
fi
|
||||
done
|
||||
|
||||
# On Sunday, create weekly backup
|
||||
if [ "$DAY_OF_WEEK" -eq 7 ]; then
|
||||
log "Creating weekly backup (Sunday)..."
|
||||
WEEKLY_DIR="$BACKUP_DIR/weekly/$DATE"
|
||||
mkdir -p "$WEEKLY_DIR"
|
||||
cp "$BACKUP_DIR/daily/"*"_${DATE}.sql.gz" "$WEEKLY_DIR/" 2>/dev/null || true
|
||||
log "Weekly backup created in $WEEKLY_DIR"
|
||||
fi
|
||||
|
||||
# Rotate daily backups (keep last 7 days)
|
||||
log "Rotating daily backups (keeping 7 days)..."
|
||||
find "$BACKUP_DIR/daily" -name "*.sql.gz" -mtime +7 -delete 2>/dev/null || true
|
||||
|
||||
# Rotate weekly backups (keep last 4 weeks)
|
||||
log "Rotating weekly backups (keeping 4 weeks)..."
|
||||
find "$BACKUP_DIR/weekly" -mindepth 1 -maxdepth 1 -type d -mtime +28 -exec rm -rf {} \; 2>/dev/null || true
|
||||
|
||||
# Calculate total backup size
|
||||
TOTAL_SIZE=$(du -sh "$BACKUP_DIR" 2>/dev/null | awk '{print $1}')
|
||||
|
||||
log "=== Backup Summary ==="
|
||||
log "Databases backed up: $BACKUP_COUNT"
|
||||
log "Total backup size: $TOTAL_SIZE"
|
||||
|
||||
if [ -n "$FAILED_DBS" ]; then
|
||||
log "FAILED databases:$FAILED_DBS"
|
||||
send_notification "⚠️ <b>Backup Partially Failed</b>\n\nFailed:$FAILED_DBS\nSuccessful: $BACKUP_COUNT databases" "high"
|
||||
exit 1
|
||||
else
|
||||
log "All backups successful!"
|
||||
# Only send notification on Sundays (weekly summary)
|
||||
if [ "$DAY_OF_WEEK" -eq 7 ]; then
|
||||
send_notification "💾 <b>Weekly Backup Complete</b>\n\n$BACKUP_COUNT databases backed up\nTotal size: $TOTAL_SIZE"
|
||||
fi
|
||||
fi
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
#!/bin/bash
|
||||
# ManaCore Container Health Enforcer
|
||||
# Ensures all containers are actually running, not just created
|
||||
# Ensures all containers are actually running and healthy
|
||||
#
|
||||
# This script detects containers that are stuck in "Created" or "Exited"
|
||||
# status and automatically starts them.
|
||||
# This script detects containers that are:
|
||||
# - Stuck in "Created" or "Exited" status -> starts them
|
||||
# - Crash-looping in "Restarting" status -> recreates them
|
||||
#
|
||||
# Run via LaunchD every 5 minutes or after system startup.
|
||||
|
||||
|
|
@ -17,6 +18,7 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|||
COMPOSE_FILE="$PROJECT_ROOT/docker-compose.macmini.yml"
|
||||
ENV_FILE="$PROJECT_ROOT/.env.macmini"
|
||||
LOG_FILE="/tmp/manacore-container-health.log"
|
||||
RESTART_TRACKER="/tmp/manacore-restart-tracker"
|
||||
|
||||
# Load notification config if exists
|
||||
if [ -f "$PROJECT_ROOT/.env.notifications" ]; then
|
||||
|
|
@ -29,6 +31,7 @@ log() {
|
|||
|
||||
send_notification() {
|
||||
local message="$1"
|
||||
local priority="${2:-default}"
|
||||
|
||||
# Telegram
|
||||
if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
|
||||
|
|
@ -42,8 +45,8 @@ send_notification() {
|
|||
# ntfy
|
||||
if [ -n "$NTFY_TOPIC" ]; then
|
||||
curl -s -d "$message" \
|
||||
-H "Title: ManaCore Container Fixed" \
|
||||
-H "Priority: default" \
|
||||
-H "Title: ManaCore Container Health" \
|
||||
-H "Priority: $priority" \
|
||||
-H "Tags: white_check_mark" \
|
||||
"https://ntfy.sh/$NTFY_TOPIC" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
|
@ -55,29 +58,90 @@ if ! docker info >/dev/null 2>&1; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Get containers that are NOT running (Created, Exited, etc.)
|
||||
# Filter only mana-* containers from our compose file
|
||||
# Get containers that are NOT running (Created, Exited)
|
||||
STUCK_CONTAINERS=$(docker ps -a --filter "status=created" --filter "status=exited" --format "{{.Names}}" | grep "^mana-" || true)
|
||||
|
||||
if [ -z "$STUCK_CONTAINERS" ]; then
|
||||
# Get containers that are crash-looping (Restarting)
|
||||
CRASHLOOP_CONTAINERS=$(docker ps -a --filter "status=restarting" --format "{{.Names}}" | grep "^mana-" || true)
|
||||
|
||||
# Track restart attempts to avoid infinite loops
|
||||
track_restart() {
|
||||
local container="$1"
|
||||
local count_file="$RESTART_TRACKER/$container"
|
||||
mkdir -p "$RESTART_TRACKER"
|
||||
|
||||
if [ -f "$count_file" ]; then
|
||||
local count=$(cat "$count_file")
|
||||
local age=$(( $(date +%s) - $(stat -f %m "$count_file" 2>/dev/null || stat -c %Y "$count_file" 2>/dev/null) ))
|
||||
# Reset counter if more than 1 hour old
|
||||
if [ "$age" -gt 3600 ]; then
|
||||
echo "1" > "$count_file"
|
||||
echo "1"
|
||||
else
|
||||
count=$((count + 1))
|
||||
echo "$count" > "$count_file"
|
||||
echo "$count"
|
||||
fi
|
||||
else
|
||||
echo "1" > "$count_file"
|
||||
echo "1"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -z "$STUCK_CONTAINERS" ] && [ -z "$CRASHLOOP_CONTAINERS" ]; then
|
||||
log "OK: All containers are running"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "WARNING: Found containers not running:"
|
||||
echo "$STUCK_CONTAINERS" | while read container; do
|
||||
STATUS=$(docker inspect "$container" --format '{{.State.Status}}' 2>/dev/null || echo "unknown")
|
||||
log " - $container (status: $STATUS)"
|
||||
done
|
||||
# Handle crash-looping containers first (more critical)
|
||||
if [ -n "$CRASHLOOP_CONTAINERS" ]; then
|
||||
log "WARNING: Found crash-looping containers:"
|
||||
for container in $CRASHLOOP_CONTAINERS; do
|
||||
RESTART_COUNT=$(docker inspect "$container" --format '{{.RestartCount}}' 2>/dev/null || echo "0")
|
||||
log " - $container (restart count: $RESTART_COUNT)"
|
||||
done
|
||||
|
||||
# Start the stuck containers using docker compose
|
||||
log "Starting stuck containers via docker compose..."
|
||||
log "Attempting to recover crash-looping containers..."
|
||||
for container in $CRASHLOOP_CONTAINERS; do
|
||||
ATTEMPTS=$(track_restart "$container")
|
||||
|
||||
if [ "$ATTEMPTS" -gt 3 ]; then
|
||||
log " SKIP: $container has been restarted $ATTEMPTS times in the last hour, needs manual intervention"
|
||||
send_notification "🚨 <b>Container needs manual fix</b>\n\n$container has crashed $ATTEMPTS times. Check logs:\n<code>docker logs $container</code>" "high"
|
||||
continue
|
||||
fi
|
||||
|
||||
log " Recreating $container (attempt $ATTEMPTS/3)..."
|
||||
# Stop, remove and recreate the container
|
||||
docker stop "$container" 2>/dev/null || true
|
||||
docker rm "$container" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
|
||||
# Handle stuck containers (Created/Exited)
|
||||
if [ -n "$STUCK_CONTAINERS" ]; then
|
||||
log "WARNING: Found containers not running:"
|
||||
for container in $STUCK_CONTAINERS; do
|
||||
STATUS=$(docker inspect "$container" --format '{{.State.Status}}' 2>/dev/null || echo "unknown")
|
||||
log " - $container (status: $STATUS)"
|
||||
done
|
||||
fi
|
||||
|
||||
# Combine all containers that need to be started
|
||||
ALL_PROBLEM_CONTAINERS=$(echo -e "$STUCK_CONTAINERS\n$CRASHLOOP_CONTAINERS" | grep -v "^$" | sort -u || true)
|
||||
|
||||
if [ -z "$ALL_PROBLEM_CONTAINERS" ]; then
|
||||
log "OK: No containers need recovery"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "Starting containers via docker compose..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Use docker compose up for the specific services
|
||||
# This ensures dependencies are respected
|
||||
for container in $STUCK_CONTAINERS; do
|
||||
for container in $ALL_PROBLEM_CONTAINERS; do
|
||||
# Extract service name from container name (remove mana-app- or mana-* prefix)
|
||||
# Container naming: mana-{category}-{service} or mana-app-{service}-{type}
|
||||
SERVICE_NAME=""
|
||||
|
|
@ -139,18 +203,21 @@ done
|
|||
# Wait for containers to start
|
||||
sleep 10
|
||||
|
||||
# Verify containers are now running
|
||||
# Verify containers are now running (check for created, exited, AND restarting)
|
||||
STILL_STUCK=$(docker ps -a --filter "status=created" --filter "status=exited" --format "{{.Names}}" | grep "^mana-" || true)
|
||||
STILL_CRASHING=$(docker ps -a --filter "status=restarting" --format "{{.Names}}" | grep "^mana-" || true)
|
||||
ALL_STILL_BROKEN=$(echo -e "$STILL_STUCK\n$STILL_CRASHING" | grep -v "^$" | sort -u || true)
|
||||
|
||||
if [ -z "$STILL_STUCK" ]; then
|
||||
FIXED_MSG="Auto-fixed stuck containers: $(echo $STUCK_CONTAINERS | tr '\n' ', ')"
|
||||
if [ -z "$ALL_STILL_BROKEN" ]; then
|
||||
FIXED_MSG="Auto-fixed containers: $(echo $ALL_PROBLEM_CONTAINERS | tr '\n' ', ')"
|
||||
log "SUCCESS: $FIXED_MSG"
|
||||
send_notification "🔧 <b>ManaCore Auto-Recovery</b>\n\n$FIXED_MSG"
|
||||
else
|
||||
log "ERROR: Some containers still not running:"
|
||||
echo "$STILL_STUCK" | while read container; do
|
||||
log " - $container"
|
||||
log "ERROR: Some containers still have issues:"
|
||||
for container in $ALL_STILL_BROKEN; do
|
||||
STATUS=$(docker inspect "$container" --format '{{.State.Status}}' 2>/dev/null || echo "unknown")
|
||||
log " - $container (status: $STATUS)"
|
||||
done
|
||||
send_notification "⚠️ <b>ManaCore Container Issue</b>\n\nContainers still stuck: $(echo $STILL_STUCK | tr '\n' ', ')"
|
||||
send_notification "⚠️ <b>ManaCore Container Issue</b>\n\nContainers still broken: $(echo $ALL_STILL_BROKEN | tr '\n' ', ')" "high"
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
56
scripts/mac-mini/launchd/README.md
Normal file
56
scripts/mac-mini/launchd/README.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# LaunchD Services for Mac Mini
|
||||
|
||||
These plist files configure automatic services on the Mac Mini server.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Copy all plists to LaunchAgents
|
||||
cp *.plist ~/Library/LaunchAgents/
|
||||
|
||||
# Load all services
|
||||
for f in *.plist; do launchctl load ~/Library/LaunchAgents/$f; done
|
||||
```
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Description | Interval |
|
||||
|---------|-------------|----------|
|
||||
| `docker-startup` | Starts Docker containers on boot | At login |
|
||||
| `ensure-containers` | Detects and restarts stuck containers | Every 5 min |
|
||||
| `health-check` | Checks all services and sends alerts | Every 5 min |
|
||||
| `ssd-check` | Monitors SSD health | Periodic |
|
||||
| `mana-stt` | Speech-to-text service (Whisper) | At login |
|
||||
| `mana-tts` | Text-to-speech service (Kokoro) | At login |
|
||||
| `image-gen` | Image generation service | At login |
|
||||
| `telegram-ollama-bot` | Telegram bot with Ollama | At login |
|
||||
|
||||
## Management Commands
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
launchctl list | grep manacore
|
||||
|
||||
# View logs
|
||||
tail -f /tmp/manacore-*.log
|
||||
|
||||
# Reload a service
|
||||
launchctl unload ~/Library/LaunchAgents/com.manacore.health-check.plist
|
||||
launchctl load ~/Library/LaunchAgents/com.manacore.health-check.plist
|
||||
|
||||
# Stop a service
|
||||
launchctl unload ~/Library/LaunchAgents/com.manacore.<service>.plist
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Exit codes in `launchctl list`:
|
||||
- `0` = Running successfully
|
||||
- `1` = Last run had errors (check logs)
|
||||
- `-` = Not running / waiting for next interval
|
||||
- `78` = Configuration error
|
||||
|
||||
Check error logs:
|
||||
```bash
|
||||
cat /tmp/manacore-<service>.error.log
|
||||
```
|
||||
35
scripts/mac-mini/launchd/com.manacore.backup-databases.plist
Normal file
35
scripts/mac-mini/launchd/com.manacore.backup-databases.plist
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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.backup-databases</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>/Users/mana/projects/manacore-monorepo/scripts/mac-mini/backup-databases.sh</string>
|
||||
</array>
|
||||
|
||||
<!-- Run daily at 3:00 AM -->
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
<key>Hour</key>
|
||||
<integer>3</integer>
|
||||
<key>Minute</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/manacore-backup.log</string>
|
||||
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/manacore-backup.error.log</string>
|
||||
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
26
scripts/mac-mini/launchd/com.manacore.docker-startup.plist
Normal file
26
scripts/mac-mini/launchd/com.manacore.docker-startup.plist
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?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>/Users/mana/projects/manacore-monorepo/scripts/mac-mini/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>
|
||||
24
scripts/mac-mini/launchd/com.manacore.health-check.plist
Normal file
24
scripts/mac-mini/launchd/com.manacore.health-check.plist
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?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>/Users/mana/projects/manacore-monorepo/scripts/mac-mini/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>
|
||||
53
scripts/mac-mini/launchd/com.manacore.image-gen.plist
Normal file
53
scripts/mac-mini/launchd/com.manacore.image-gen.plist
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?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.image-gen</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/mana/projects/manacore-monorepo/services/mana-image-gen/.venv/bin/python3</string>
|
||||
<string>-m</string>
|
||||
<string>uvicorn</string>
|
||||
<string>app.main:app</string>
|
||||
<string>--host</string>
|
||||
<string>0.0.0.0</string>
|
||||
<string>--port</string>
|
||||
<string>3025</string>
|
||||
</array>
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/mana/projects/manacore-monorepo/services/mana-image-gen</string>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/opt/homebrew/bin:/Users/mana/projects/manacore-monorepo/services/mana-image-gen/.venv/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
<key>HOME</key>
|
||||
<string>/Users/mana</string>
|
||||
<key>PORT</key>
|
||||
<string>3025</string>
|
||||
<key>FLUX_BINARY</key>
|
||||
<string>/Users/mana/flux2/flux</string>
|
||||
<key>FLUX_MODEL_DIR</key>
|
||||
<string>/Users/mana/flux2/model</string>
|
||||
<key>DEFAULT_STEPS</key>
|
||||
<string>4</string>
|
||||
<key>GENERATION_TIMEOUT</key>
|
||||
<string>300</string>
|
||||
<key>CORS_ORIGINS</key>
|
||||
<string>https://mana.how,https://picture.mana.how,https://chat.mana.how</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<dict>
|
||||
<key>SuccessfulExit</key>
|
||||
<false/>
|
||||
<key>Crashed</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/manacore-image-gen.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/manacore-image-gen.error.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
39
scripts/mac-mini/launchd/com.manacore.mana-stt.plist
Normal file
39
scripts/mac-mini/launchd/com.manacore.mana-stt.plist
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?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.mana-stt</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-c</string>
|
||||
<string>cd /Users/mana/projects/manacore-monorepo/services/mana-stt && set -a && source .env && set +a && .venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 3020</string>
|
||||
</array>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/mana/projects/manacore-monorepo/services/mana-stt</string>
|
||||
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
</dict>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/mana/logs/mana-stt.log</string>
|
||||
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/mana/logs/mana-stt.error.log</string>
|
||||
|
||||
<key>ThrottleInterval</key>
|
||||
<integer>10</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
39
scripts/mac-mini/launchd/com.manacore.mana-tts.plist
Normal file
39
scripts/mac-mini/launchd/com.manacore.mana-tts.plist
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?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.mana-tts</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-c</string>
|
||||
<string>cd /Users/mana/projects/manacore-monorepo/services/mana-tts && set -a && source .env && set +a && .venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 3022</string>
|
||||
</array>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/mana/projects/manacore-monorepo/services/mana-tts</string>
|
||||
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
</dict>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/mana/logs/mana-tts.log</string>
|
||||
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/mana/logs/mana-tts.error.log</string>
|
||||
|
||||
<key>ThrottleInterval</key>
|
||||
<integer>10</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
18
scripts/mac-mini/launchd/com.manacore.ssd-check.plist
Normal file
18
scripts/mac-mini/launchd/com.manacore.ssd-check.plist
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?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.ssd-check</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/mana/check-ssd.sh</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/mana/Library/Logs/ssd-check.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/mana/Library/Logs/ssd-check.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?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.telegram-ollama-bot</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/opt/homebrew/bin/node</string>
|
||||
<string>/Users/mana/projects/manacore-monorepo/services/telegram-ollama-bot/dist/main.js</string>
|
||||
</array>
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/mana/projects/manacore-monorepo/services/telegram-ollama-bot</string>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
<key>TELEGRAM_BOT_TOKEN</key>
|
||||
<string>8559479868:AAHF3g7vYLs0eOvDLh7hFVnIB-V8CKehUOM</string>
|
||||
<key>OLLAMA_URL</key>
|
||||
<string>http://localhost:11434</string>
|
||||
<key>OLLAMA_MODEL</key>
|
||||
<string>gemma3:4b</string>
|
||||
<key>PORT</key>
|
||||
<string>3301</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/mana/Library/Logs/telegram-ollama-bot.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/mana/Library/Logs/telegram-ollama-bot.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
74
scripts/mac-mini/setup-docker-logging.sh
Executable file
74
scripts/mac-mini/setup-docker-logging.sh
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
#!/bin/bash
|
||||
# Configure Docker daemon for log rotation
|
||||
# This prevents docker logs from consuming unlimited disk space
|
||||
#
|
||||
# Run once after Docker Desktop installation
|
||||
|
||||
set -e
|
||||
|
||||
DOCKER_CONFIG_DIR="$HOME/.docker"
|
||||
DAEMON_JSON="$DOCKER_CONFIG_DIR/daemon.json"
|
||||
|
||||
echo "=== Docker Log Rotation Setup ==="
|
||||
|
||||
# Create config directory if needed
|
||||
mkdir -p "$DOCKER_CONFIG_DIR"
|
||||
|
||||
# Backup existing config
|
||||
if [ -f "$DAEMON_JSON" ]; then
|
||||
cp "$DAEMON_JSON" "${DAEMON_JSON}.backup.$(date +%Y%m%d)"
|
||||
echo "Backed up existing daemon.json"
|
||||
fi
|
||||
|
||||
# Check if config exists and has content
|
||||
if [ -f "$DAEMON_JSON" ] && [ -s "$DAEMON_JSON" ]; then
|
||||
# Merge with existing config using jq if available
|
||||
if command -v jq &> /dev/null; then
|
||||
echo "Merging with existing daemon.json..."
|
||||
jq '. + {
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "50m",
|
||||
"max-file": "3",
|
||||
"compress": "true"
|
||||
}
|
||||
}' "$DAEMON_JSON" > "${DAEMON_JSON}.tmp" && mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON"
|
||||
else
|
||||
echo "WARNING: jq not installed, cannot merge configs"
|
||||
echo "Please manually add log settings to $DAEMON_JSON"
|
||||
echo ""
|
||||
echo 'Add this to your daemon.json:'
|
||||
echo ' "log-driver": "json-file",'
|
||||
echo ' "log-opts": {'
|
||||
echo ' "max-size": "50m",'
|
||||
echo ' "max-file": "3",'
|
||||
echo ' "compress": "true"'
|
||||
echo ' }'
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Create new config
|
||||
echo "Creating new daemon.json..."
|
||||
cat > "$DAEMON_JSON" << 'EOF'
|
||||
{
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "50m",
|
||||
"max-file": "3",
|
||||
"compress": "true"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Log rotation configured:"
|
||||
echo " - Max size per log file: 50MB"
|
||||
echo " - Max files per container: 3"
|
||||
echo " - Compression: enabled"
|
||||
echo " - Total max logs per container: ~150MB"
|
||||
echo ""
|
||||
echo "IMPORTANT: Restart Docker Desktop for changes to take effect!"
|
||||
echo ""
|
||||
echo "To verify after restart:"
|
||||
echo " docker info | grep -A5 'Logging Driver'"
|
||||
Loading…
Add table
Add a link
Reference in a new issue