From 4ebe3ec57490b9dce2ed443b9d47634c2f7145f1 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:17:37 +0100 Subject: [PATCH] feat: add multi-arch Docker builds and Mac Mini deployment - CI: Build Docker images for linux/amd64 + linux/arm64 - CI: Add manacore-web to build matrix - Add docker-compose.macmini.yml for Mac Mini deployment - Add cloudflared-config.yml for Cloudflare Tunnel routing - Add Mac Mini deployment scripts and documentation - Configure Cloudflared as launchd service for auto-start Co-Authored-By: Claude Opus 4.5 --- .env.macmini.example | 33 ++ .github/workflows/ci.yml | 6 + .gitignore | 4 + cloudflared-config.yml | 25 ++ docker-compose.macmini.yml | 329 ++++++++++++++++++ docs/MAC_MINI_DEPLOYMENT.md | 234 +++++++++++++ scripts/mac-mini/deploy.sh | 113 ++++++ scripts/mac-mini/setup-cloudflared-service.sh | 79 +++++ 8 files changed, 823 insertions(+) create mode 100644 .env.macmini.example create mode 100644 cloudflared-config.yml create mode 100644 docker-compose.macmini.yml create mode 100644 docs/MAC_MINI_DEPLOYMENT.md create mode 100755 scripts/mac-mini/deploy.sh create mode 100755 scripts/mac-mini/setup-cloudflared-service.sh diff --git a/.env.macmini.example b/.env.macmini.example new file mode 100644 index 000000000..376fc80ae --- /dev/null +++ b/.env.macmini.example @@ -0,0 +1,33 @@ +# Mac Mini Production Environment +# Copy to .env.macmini and fill in the values + +# ============================================ +# Database (PostgreSQL) +# ============================================ +POSTGRES_PASSWORD=your-secure-password-here + +# ============================================ +# Redis +# ============================================ +REDIS_PASSWORD=your-redis-password-here + +# ============================================ +# JWT Keys (generate with: openssl rand -base64 32) +# For EdDSA keys, use mana-core-auth key generation +# ============================================ +JWT_SECRET=your-jwt-secret-here +# Leave empty to use auto-generated keys +JWT_PUBLIC_KEY= +JWT_PRIVATE_KEY= + +# ============================================ +# Supabase (optional, for legacy features) +# ============================================ +SUPABASE_URL= +SUPABASE_SERVICE_ROLE_KEY= + +# ============================================ +# Azure OpenAI (for Chat AI features) +# ============================================ +AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/ +AZURE_OPENAI_API_KEY=your-api-key-here diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cedde3411..dd5876a30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,7 @@ jobs: run: pnpm run lint || echo "Lint warnings found" # Build Docker images - only on push to dev/main (not PRs) + # Multi-arch build: linux/amd64 (Hetzner) + linux/arm64 (Mac Mini) build-docker-images: name: Build ${{ matrix.service.name }} runs-on: ubuntu-latest @@ -69,6 +70,7 @@ jobs: matrix: service: - { name: 'mana-core-auth', path: 'services/mana-core-auth', port: '3001' } + - { name: 'manacore-web', path: 'apps/manacore/apps/web', port: '5173' } - { name: 'chat-backend', path: 'apps/chat/apps/backend', port: '3002' } - { name: 'chat-web', path: 'apps/chat/apps/web', port: '3000' } - { name: 'todo-backend', path: 'apps/todo/apps/backend', port: '3018' } @@ -82,6 +84,9 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -118,6 +123,7 @@ jobs: with: context: . file: ${{ matrix.service.path }}/Dockerfile + platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore index 5303d2a89..643166e29 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,7 @@ yarn.lock # Claude Flow metrics .claude-flow/ .claude-flow/metrics/ + +# Mac Mini deployment +.env.macmini +ssh-key-command.txt diff --git a/cloudflared-config.yml b/cloudflared-config.yml new file mode 100644 index 000000000..19368a1ec --- /dev/null +++ b/cloudflared-config.yml @@ -0,0 +1,25 @@ +tunnel: bb0ea86d-8253-4a54-838b-107bb7945be9 +credentials-file: /Users/mana/.cloudflared/bb0ea86d-8253-4a54-838b-107bb7945be9.json + +ingress: + - hostname: auth.mana.how + service: http://localhost:3001 + - hostname: mana.how + service: http://localhost:5173 + - hostname: chat.mana.how + service: http://localhost:3000 + - hostname: chat-api.mana.how + service: http://localhost:3002 + - hostname: todo.mana.how + service: http://localhost:5188 + - hostname: todo-api.mana.how + service: http://localhost:3018 + - hostname: calendar.mana.how + service: http://localhost:5186 + - hostname: calendar-api.mana.how + service: http://localhost:3016 + - hostname: clock.mana.how + service: http://localhost:5187 + - hostname: clock-api.mana.how + service: http://localhost:3017 + - service: http_status:404 diff --git a/docker-compose.macmini.yml b/docker-compose.macmini.yml new file mode 100644 index 000000000..aceb51dcc --- /dev/null +++ b/docker-compose.macmini.yml @@ -0,0 +1,329 @@ +# ManaCore Mac Mini Configuration +# Domain: mana.how (via Cloudflare Tunnel) + +services: + # ============================================ + # Infrastructure Services + # ============================================ + + postgres: + image: postgres:16-alpine + container_name: manacore-postgres + restart: always + environment: + POSTGRES_DB: manacore + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-manacore123} + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: redis:7-alpine + container_name: manacore-redis + restart: always + command: redis-server --requirepass ${REDIS_PASSWORD:-redis123} + volumes: + - redis_data:/data + ports: + - "6379:6379" + healthcheck: + test: ["CMD", "redis-cli", "--raw", "incr", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + # ============================================ + # Auth Service + # ============================================ + + mana-core-auth: + image: ghcr.io/memo-2023/mana-core-auth:latest + container_name: mana-core-auth + restart: always + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 3001 + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-manacore123}@postgres:5432/manacore_auth + REDIS_HOST: redis + REDIS_PORT: 6379 + REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} + JWT_SECRET: ${JWT_SECRET:-your-jwt-secret-change-me} + JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY:-} + JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY:-} + CORS_ORIGINS: https://mana.how,https://chat.mana.how,https://todo.mana.how,https://calendar.mana.how,https://clock.mana.how + ports: + - "3001:3001" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3001/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # ============================================ + # ManaCore Dashboard + # ============================================ + + manacore-web: + image: ghcr.io/memo-2023/manacore-web:latest + container_name: manacore-web + restart: always + depends_on: + mana-core-auth: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 5173 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how + PUBLIC_TODO_API_URL: http://todo-backend:3018 + PUBLIC_TODO_API_URL_CLIENT: https://todo-api.mana.how + PUBLIC_CALENDAR_API_URL: http://calendar-backend:3016 + PUBLIC_CALENDAR_API_URL_CLIENT: https://calendar-api.mana.how + PUBLIC_CLOCK_API_URL: http://clock-backend:3017 + PUBLIC_CLOCK_API_URL_CLIENT: https://clock-api.mana.how + ports: + - "5173:5173" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5173/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # ============================================ + # Chat App + # ============================================ + + chat-backend: + image: ghcr.io/memo-2023/chat-backend:latest + container_name: chat-backend + restart: always + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 3002 + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-manacore123}@postgres:5432/chat + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + SUPABASE_URL: ${SUPABASE_URL:-} + SUPABASE_SERVICE_KEY: ${SUPABASE_SERVICE_ROLE_KEY:-} + AZURE_OPENAI_ENDPOINT: ${AZURE_OPENAI_ENDPOINT:-} + AZURE_OPENAI_API_KEY: ${AZURE_OPENAI_API_KEY:-} + AZURE_OPENAI_API_VERSION: 2024-12-01-preview + CORS_ORIGINS: https://chat.mana.how,https://mana.how + ports: + - "3002:3002" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3002/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + chat-web: + image: ghcr.io/memo-2023/chat-web:latest + container_name: chat-web + restart: always + depends_on: + chat-backend: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 3000 + PUBLIC_BACKEND_URL: http://chat-backend:3002 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_BACKEND_URL_CLIENT: https://chat-api.mana.how + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how + ports: + - "3000:3000" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # ============================================ + # Todo App + # ============================================ + + todo-backend: + image: ghcr.io/memo-2023/todo-backend:latest + container_name: todo-backend + restart: always + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 3018 + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-manacore123}@postgres:5432/todo + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + CORS_ORIGINS: https://todo.mana.how,https://mana.how + ports: + - "3018:3018" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3018/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + todo-web: + image: ghcr.io/memo-2023/todo-web:latest + container_name: todo-web + restart: always + depends_on: + todo-backend: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 5188 + PUBLIC_BACKEND_URL: http://todo-backend:3018 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_BACKEND_URL_CLIENT: https://todo-api.mana.how + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how + ports: + - "5188:5188" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5188/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # ============================================ + # Calendar App + # ============================================ + + calendar-backend: + image: ghcr.io/memo-2023/calendar-backend:latest + container_name: calendar-backend + restart: always + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 3016 + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-manacore123}@postgres:5432/calendar + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: postgres + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + CORS_ORIGINS: https://calendar.mana.how,https://mana.how + ports: + - "3016:3016" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3016/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + calendar-web: + image: ghcr.io/memo-2023/calendar-web:latest + container_name: calendar-web + restart: always + depends_on: + calendar-backend: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 5186 + PUBLIC_BACKEND_URL: http://calendar-backend:3016 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_BACKEND_URL_CLIENT: https://calendar-api.mana.how + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how + ports: + - "5186:5186" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5186/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # ============================================ + # Clock App + # ============================================ + + clock-backend: + image: ghcr.io/memo-2023/clock-backend:latest + container_name: clock-backend + restart: always + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 3017 + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-manacore123}@postgres:5432/clock + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: postgres + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + CORS_ORIGINS: https://clock.mana.how,https://mana.how + ports: + - "3017:3017" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3017/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + clock-web: + image: ghcr.io/memo-2023/clock-web:latest + container_name: clock-web + restart: always + depends_on: + clock-backend: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 5187 + PUBLIC_BACKEND_URL: http://clock-backend:3017 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_BACKEND_URL_CLIENT: https://clock-api.mana.how + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how + ports: + - "5187:5187" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5187/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +# ============================================ +# Volumes +# ============================================ + +volumes: + postgres_data: + name: manacore-postgres + redis_data: + name: manacore-redis diff --git a/docs/MAC_MINI_DEPLOYMENT.md b/docs/MAC_MINI_DEPLOYMENT.md new file mode 100644 index 000000000..b95ceb298 --- /dev/null +++ b/docs/MAC_MINI_DEPLOYMENT.md @@ -0,0 +1,234 @@ +# Mac Mini Deployment Guide + +Production deployment auf Mac Mini M2 via Cloudflare Tunnel. + +**Domain:** mana.how +**Tunnel ID:** bb0ea86d-8253-4a54-838b-107bb7945be9 + +--- + +## Architektur + +``` +Internet → Cloudflare Tunnel → Mac Mini (Docker) → Apps + ↓ + mana.how → localhost:5173 (Dashboard) + auth.mana.how → localhost:3001 (Auth API) + chat.mana.how → localhost:3000 (Chat Web) + chat-api.mana.how → localhost:3002 (Chat API) + todo.mana.how → localhost:5188 (Todo Web) + todo-api.mana.how → localhost:3018 (Todo API) + calendar.mana.how → localhost:5186 (Calendar Web) + calendar-api.mana.how → localhost:3016 (Calendar API) + clock.mana.how → localhost:5187 (Clock Web) + clock-api.mana.how → localhost:3017 (Clock API) +``` + +--- + +## Voraussetzungen + +- Mac Mini mit Apple Silicon (ARM64) +- Docker Desktop for Mac +- Homebrew +- Cloudflared + +--- + +## Erstmaliges Setup + +### 1. Repository klonen + +```bash +mkdir -p ~/projects +cd ~/projects +git clone https://github.com/Memo-2023/manacore-monorepo.git +cd manacore-monorepo +``` + +### 2. Cloudflared installieren & konfigurieren + +```bash +brew install cloudflared + +# Bereits erledigt: Tunnel ist erstellt und konfiguriert +# Die Config liegt in: cloudflared-config.yml +``` + +### 3. Cloudflared als Service einrichten + +```bash +chmod +x scripts/mac-mini/setup-cloudflared-service.sh +./scripts/mac-mini/setup-cloudflared-service.sh +``` + +Das Script erstellt einen launchd-Service, der: +- Automatisch beim Login startet +- Bei Abstürzen neu startet +- Logs nach `/tmp/cloudflared.log` schreibt + +### 4. Environment konfigurieren + +```bash +# Template kopieren +cp .env.macmini.example .env.macmini + +# Werte eintragen +nano .env.macmini +``` + +**Wichtige Werte:** +- `POSTGRES_PASSWORD` - Sicheres Passwort für PostgreSQL +- `REDIS_PASSWORD` - Sicheres Passwort für Redis +- `JWT_SECRET` - Für JWT-Token Generierung +- `AZURE_OPENAI_*` - Für Chat AI Features (optional) + +### 5. Container starten + +```bash +chmod +x scripts/mac-mini/deploy.sh +./scripts/mac-mini/deploy.sh +``` + +--- + +## Tägliche Operationen + +### Container Status prüfen + +```bash +docker compose -f docker-compose.macmini.yml ps +``` + +### Logs anschauen + +```bash +# Alle Services +docker compose -f docker-compose.macmini.yml logs -f + +# Einzelner Service +docker compose -f docker-compose.macmini.yml logs -f mana-core-auth +``` + +### Neustart aller Services + +```bash +docker compose -f docker-compose.macmini.yml restart +``` + +### Update auf neue Images + +```bash +# Neuste Images pullen +docker compose -f docker-compose.macmini.yml pull + +# Container mit neuen Images starten +docker compose -f docker-compose.macmini.yml up -d + +# Alte Images aufräumen +docker image prune -f +``` + +--- + +## Cloudflared Service verwalten + +```bash +# Status prüfen +launchctl list | grep cloudflared + +# Logs anschauen +tail -f /tmp/cloudflared.log + +# Service stoppen +launchctl unload ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist + +# Service starten +launchctl load ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist +``` + +--- + +## Troubleshooting + +### Container startet nicht + +```bash +# Logs des Services anschauen +docker compose -f docker-compose.macmini.yml logs + +# Beispiel +docker compose -f docker-compose.macmini.yml logs mana-core-auth +``` + +### Datenbank-Probleme + +```bash +# In PostgreSQL einloggen +docker compose -f docker-compose.macmini.yml exec postgres psql -U postgres + +# Datenbanken auflisten +\l + +# Zu Datenbank wechseln +\c manacore_auth +``` + +### Cloudflare Tunnel nicht erreichbar + +1. Prüfen ob der Service läuft: + ```bash + launchctl list | grep cloudflared + ``` + +2. Logs prüfen: + ```bash + cat /tmp/cloudflared.error.log + ``` + +3. Manuell testen: + ```bash + cloudflared tunnel --config cloudflared-config.yml run + ``` + +### Health Checks + +```bash +curl http://localhost:3001/api/v1/health # Auth +curl http://localhost:5173/health # Dashboard +curl http://localhost:3000/health # Chat Web +curl http://localhost:3002/api/v1/health # Chat API +curl http://localhost:5188/health # Todo Web +curl http://localhost:3018/api/health # Todo API +curl http://localhost:5186/health # Calendar Web +curl http://localhost:3016/api/v1/health # Calendar API +curl http://localhost:5187/health # Clock Web +curl http://localhost:3017/api/v1/health # Clock API +``` + +--- + +## CI/CD + +Docker Images werden automatisch bei Push zu `main` gebaut: +- Multi-Arch: `linux/amd64` (Hetzner) + `linux/arm64` (Mac Mini) +- Registry: `ghcr.io/memo-2023/:latest` + +Nach einem neuen Build: +```bash +cd ~/projects/manacore-monorepo +git pull +./scripts/mac-mini/deploy.sh +``` + +--- + +## Wichtige Dateien + +| Datei | Beschreibung | +|-------|--------------| +| `docker-compose.macmini.yml` | Docker Compose für Mac Mini | +| `cloudflared-config.yml` | Cloudflare Tunnel Routing | +| `.env.macmini` | Environment Variables | +| `scripts/mac-mini/deploy.sh` | Deployment Script | +| `scripts/mac-mini/setup-cloudflared-service.sh` | Cloudflared Service Setup | diff --git a/scripts/mac-mini/deploy.sh b/scripts/mac-mini/deploy.sh new file mode 100755 index 000000000..bbf6ccf1b --- /dev/null +++ b/scripts/mac-mini/deploy.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# Mac Mini Deployment Script +# Pulls latest images and starts all containers + +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 Mac Mini Deployment ===" +echo "" +echo "Project root: $PROJECT_ROOT" +echo "Compose file: $COMPOSE_FILE" +echo "" + +# Check if env file exists +if [ ! -f "$ENV_FILE" ]; then + echo "Warning: $ENV_FILE not found" + echo "Creating from template..." + cat > "$ENV_FILE" << 'EOF' +# Mac Mini Production Environment +# Copy this to .env.macmini and fill in the values + +# Database +POSTGRES_PASSWORD=your-secure-password + +# Redis +REDIS_PASSWORD=your-redis-password + +# JWT Keys (from mana-core-auth) +JWT_SECRET=your-jwt-secret +JWT_PUBLIC_KEY= +JWT_PRIVATE_KEY= + +# Supabase (if needed) +SUPABASE_URL= +SUPABASE_SERVICE_ROLE_KEY= + +# Azure OpenAI (for chat) +AZURE_OPENAI_ENDPOINT= +AZURE_OPENAI_API_KEY= +EOF + echo "" + echo "Please edit $ENV_FILE with your values and run this script again." + exit 1 +fi + +# Login to GitHub Container Registry +echo "=== Logging into GitHub Container Registry ===" +echo "Please enter your GitHub Personal Access Token (with read:packages scope):" +read -s GITHUB_TOKEN +echo "$GITHUB_TOKEN" | docker login ghcr.io -u memo-2023 --password-stdin + +echo "" +echo "=== Pulling latest images ===" +docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" pull + +echo "" +echo "=== Starting containers ===" +docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d + +echo "" +echo "=== Waiting for services to start (30s) ===" +sleep 30 + +echo "" +echo "=== Container Status ===" +docker compose -f "$COMPOSE_FILE" ps + +echo "" +echo "=== Creating databases ===" +docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE manacore_auth;" 2>/dev/null || echo "manacore_auth exists" +docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE chat;" 2>/dev/null || echo "chat exists" +docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE todo;" 2>/dev/null || echo "todo exists" +docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE calendar;" 2>/dev/null || echo "calendar exists" +docker compose -f "$COMPOSE_FILE" exec -T postgres psql -U postgres -c "CREATE DATABASE clock;" 2>/dev/null || echo "clock exists" + +echo "" +echo "=== Health Checks ===" +check_health() { + local name=$1 + local url=$2 + if curl -s -o /dev/null -w "%{http_code}" "$url" | grep -q "200"; then + echo " $name: OK" + else + echo " $name: FAILED" + fi +} + +check_health "Auth API" "http://localhost:3001/api/v1/health" +check_health "ManaCore Web" "http://localhost:5173/health" +check_health "Chat Backend" "http://localhost:3002/api/v1/health" +check_health "Chat Web" "http://localhost:3000/health" +check_health "Todo Backend" "http://localhost:3018/api/health" +check_health "Todo Web" "http://localhost:5188/health" +check_health "Calendar Backend" "http://localhost:3016/api/v1/health" +check_health "Calendar Web" "http://localhost:5186/health" +check_health "Clock Backend" "http://localhost:3017/api/v1/health" +check_health "Clock Web" "http://localhost:5187/health" + +echo "" +echo "=== Deployment Complete ===" +echo "" +echo "URLs via Cloudflare Tunnel:" +echo " https://mana.how - Dashboard" +echo " https://auth.mana.how - Auth API" +echo " https://chat.mana.how - Chat" +echo " https://todo.mana.how - Todo" +echo " https://calendar.mana.how - Calendar" +echo " https://clock.mana.how - Clock" +echo "" diff --git a/scripts/mac-mini/setup-cloudflared-service.sh b/scripts/mac-mini/setup-cloudflared-service.sh new file mode 100755 index 000000000..1ed83a412 --- /dev/null +++ b/scripts/mac-mini/setup-cloudflared-service.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# Setup Cloudflared as a launchd service on macOS +# Run this script once on the Mac Mini to enable auto-start + +set -e + +TUNNEL_ID="bb0ea86d-8253-4a54-838b-107bb7945be9" +CONFIG_FILE="$HOME/projects/manacore-monorepo/cloudflared-config.yml" +CREDENTIALS_FILE="$HOME/.cloudflared/${TUNNEL_ID}.json" +PLIST_FILE="$HOME/Library/LaunchAgents/com.cloudflare.cloudflared.plist" + +echo "=== Cloudflared Service Setup ===" +echo "" + +# Check if credentials exist +if [ ! -f "$CREDENTIALS_FILE" ]; then + echo "Error: Credentials file not found: $CREDENTIALS_FILE" + echo "Run 'cloudflared tunnel login' first" + exit 1 +fi + +# Check if config exists +if [ ! -f "$CONFIG_FILE" ]; then + echo "Error: Config file not found: $CONFIG_FILE" + exit 1 +fi + +# Create LaunchAgents directory if needed +mkdir -p ~/Library/LaunchAgents + +# Create the plist file +cat > "$PLIST_FILE" << EOF + + + + + Label + com.cloudflare.cloudflared + ProgramArguments + + /opt/homebrew/bin/cloudflared + tunnel + --config + ${CONFIG_FILE} + run + + RunAtLoad + + KeepAlive + + StandardOutPath + /tmp/cloudflared.log + StandardErrorPath + /tmp/cloudflared.error.log + + +EOF + +echo "Created plist: $PLIST_FILE" + +# Unload if already loaded +launchctl unload "$PLIST_FILE" 2>/dev/null || true + +# Load the service +launchctl load "$PLIST_FILE" + +echo "" +echo "=== Service Status ===" +launchctl list | grep cloudflared || echo "Service loaded" + +echo "" +echo "Cloudflared is now running as a service." +echo "" +echo "Useful commands:" +echo " Check status: launchctl list | grep cloudflared" +echo " View logs: tail -f /tmp/cloudflared.log" +echo " Stop service: launchctl unload $PLIST_FILE" +echo " Start service: launchctl load $PLIST_FILE" +echo ""